package org.exoplatform.services.workflow.impl.bonita;
import java.util.Date;
import java.util.Iterator;

import org.hibernate.Query;
import org.hibernate.Session;
import org.ow2.bonita.pvm.internal.hibernate.HibernateJobDbSession;
import org.ow2.bonita.pvm.internal.job.TimerImpl;
import org.ow2.bonita.pvm.internal.jobexecutor.JobExecutor;
import org.ow2.bonita.facade.uuid.ProcessInstanceUUID;
import org.ow2.bonita.pvm.env.Environment;
import org.ow2.bonita.runtime.XpdlExecution;
import org.ow2.bonita.util.Command;

/**
 * The CommandTimer modifies the due date of all timers
 * attached to an activity. It should be used if you need to
 * set the due date of a timer with a process property.
 *
 * @author Rodrigue Le Gall
 */
public class CommandTimer implements Command<Boolean> {

  /**
   * Generated uuid
   */
  private static final long serialVersionUID = 3148260409538618806L;

  /**
   * the due date to set to the timers
   */
  private Date dueDate;
  /**
   * The instance uuid
   */
  private ProcessInstanceUUID puuid;
  /**
   * the id of the activity
   */
  private String activity;

  public CommandTimer(ProcessInstanceUUID processUUID,String activityId,Date aDueDate){
    this.puuid = processUUID;
    this.dueDate = aDueDate;
    this.activity = activityId;
  }

  /**
   * Execute the modification of the timers' due date.
   * @return boolean true: timers were succefully updated, false: no timer found
   */
  public Boolean execute(Environment env) throws Exception {
    // WARNING : Only works if bonita is configure with Hibernate
    Session session = env.get(HibernateJobDbSession.class).getSession();

    // Create the hibernate query
    String query = "select timer " + "from " + TimerImpl.class.getName() + " as timer, "
        + XpdlExecution.class.getName() + " as xpdl " + "where timer.execution = xpdl "
        + " and xpdl.xpdlInstance.uuid.value='" + this.puuid + "'" + " and xpdl.node.name='"
        + this.activity + "'"
                ;
    Query q = session.createQuery(query);

    boolean timerIn = false;
    // Get the timers
    Iterator it = (Iterator) q.iterate();
    while(it.hasNext()){
      TimerImpl timer = (TimerImpl)it.next();
      // Set the dueDate
      timer.setDueDate(this.dueDate);
      timerIn = true;
    }
    // If no timer was modified, return a false result
    if(!timerIn) return false;

    // update the jobExecutor : modifications are taken in count
    JobExecutor jobE = env.get(JobExecutor.class);
    jobE.jobWasAdded();

    return true;
  }

}
