package org.motrice.coordinatrice

import org.activiti.engine.history.HistoricProcessInstance
import java.util.concurrent.TimeUnit

/**
 * Information about the execution of an historic BPMN process instance.
 * This class is NOT PERSISTED, constructed read-only from the BPMN engine.
 */
class PastProcinst {
  final static String DATE_FMT = 'yyyy-MM-dd HH:mm'

  /**
   * Id. We avoid using 'id' because it might interfere with Grails.
   */
  String uuid

  /**
   * Id of super process, or null.
   */
  String superProcessInstanceId

  /**
   * Process definition.
   */
  Procdef procdef

  /**
   * Business key: a unique label attached to a process instance.
   * It may be generated by the application or by Activiti.
   */
  String businessKey

  /**
   * Point in time when the process instance started its execution.
   */
  Date startTime

  /**
   * Point in time when the process instance finished its execution.
   */
  Date endTime

  /**
   * Start activity.
   */
  String startActivityId

  /**
   * Starting user.
   */
  String startUserId

  /**
   * Reason for deletion.
   */
  String deleteReason

  /**
   * Process variables (transient).
   */
  Map variables

  /**
   * Number of finished instances (transient).
   * Used for summaries.
   */
  Integer finishedCount

  /**
   * Number of unfinished instances (transient).
   * Used for summaries.
   */
  Integer unfinishedCount

  /**
   * Not a database object, never to be persisted
   */
  static mapWith = 'none'

  // Nothing is persisted, but the transient feature is used to flag these
  // fields as even more transient.
  static transients = ['finishedCount', 'unfinishedCount', 'variables']
  static constraints = {
    procdef nullable: false
  }

  def assignFromHistoricProcessInstance(HistoricProcessInstance hpi) {
    uuid = hpi.id
    superProcessInstanceId = hpi.superProcessInstanceId
    businessKey = hpi.businessKey
    startTime = hpi.startTime
    endTime = hpi.endTime
    startActivityId = hpi.startActivityId
    startUserId = hpi.startUserId
    deleteReason = hpi.deleteReason
    def varMap = hpi.processVariables
    if (varMap) {
      variables = new TreeMap(varMap)
    } else {
      variables = [:]
    }
  }

  /**
   * Generated a formatted string containing the duration of the process
   * instance execution.
   */
  String getDurationFmt() {
    def millis = durationMillis
    def result = '-d --:--'
    if (millis >= 0) {
      def days = TimeUnit.MILLISECONDS.toDays(millis)
      millis = millis - TimeUnit.DAYS.toMillis(days)
      def hours = TimeUnit.MILLISECONDS.toHours(millis)
      millis = millis - TimeUnit.HOURS.toMillis(hours)
      def minutes = TimeUnit.MILLISECONDS.toMinutes(millis)
      result = String.format('%01dd %02d:%02d', days, hours, minutes)
    }

    return result
  }

  Long getDurationMillis() {
    finished? (endTime.time - startTime.time) : -1
  }

  String getEndTimeFmt() {
    endTime?.format(DATE_FMT)
  }

  String getStartTimeFmt() {
    startTime?.format(DATE_FMT)
  }

  boolean isFinished() {
    endTime != null
  }

  String toString() {
    "[PastProcessinst(${uuid}): ${startTimeFmt},${endTimeFmt},${procdef}]"
  }

}
