/*
 * 
 */
package com.fp.bpmlib;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.jbpm.services.task.audit.impl.model.BAMTaskSummaryImpl;
import org.kie.api.task.model.Task;
import org.kie.api.task.model.TaskData;

import com.fp.base.persistence.util.helper.GeneralDescriptions;
import com.fp.bpmlib.db.DataHelper;
import com.fp.bpmlib.flow.Monitor;
import com.fp.dto.Request;
import com.fp.persistence.commondb.PersistenceHelper;
import com.fp.persistence.pgeneral.log.TgeneTransactionLog;
import com.fp.simple.dto.TaskInfo;

// TODO: Auto-generated Javadoc
/**
 * Class ProcessUtil encargada de.
 * 
 * @author gfiallos
 */
public final class ProcessUtil {

    /** Constante ACTUAL_TASK. */
    public static final String ACTUAL_TASK = "actualTask";

    /** Constante DATA. */
    public static final String DATA = "maia";

    /** El valor de instance. */
    private static ProcessUtil instance = null;

    /** Constante PID. */
    public static final String PID = "pid";

    /** Constante REQUEST. */
    public static final String REQUEST = "request";

    /** Constante SNAPSHOT. */
    public static final String SNAPSHOT = "snapshot";

    /** Constante TASK_METADATA. */
    public static final String TASK_METADATA = "taskMetaData";

    /** Constante TASKS_METADATA. */
    public static final String TASKS_METADATA = "tasksMetaData";

    /**
     * Obtiene el valor de done task meta data.
     * 
     * @param pProcess the process
     * @param pName the name
     * @return Valor de done task meta data
     * @throws Exception la exception
     */
    @SuppressWarnings("unchecked")
    public static Object getDoneTaskMetaData(Monitor monitor, String pName) throws Exception {
        Object tasks = monitor.getVariable(ProcessUtil.TASKS_METADATA);
        if (tasks != null) {
            Map<String, Object> m = (Map<String, Object>) tasks;
            Map<String, Object> record = new HashMap<String, Object>();
            record.put(pName, ProcessUtil.manageHistory(monitor,(List<TaskInfo>) m.get(pName)));
            return record;
        }
        return null;
    }

    /**
     * Obtiene el valor de first done task meta data.
     * 
     * @param pProcess the process
     * @return Valor de first done task meta data
     * @throws Exception la exception
     */
    @SuppressWarnings("unchecked")
    public static Map<String, Object> getFirstDoneTaskMetaData(Monitor monitor) throws Exception {
        Object tasks = monitor.getVariable(ProcessUtil.TASKS_METADATA);
        if (tasks != null) {
            Map<String, Object> m = (Map<String, Object>) tasks;
            for (Entry<String, Object> entry : m.entrySet()) {
                Map<String, Object> record = new HashMap<String, Object>();
                record.put(entry.getKey(), ProcessUtil.getDoneTaskMetaData(monitor, entry.getKey()));
                return record;
            }
        }
        return null;
    }

    /**
     * Obtiene la única instancia de ProcessUtil.
     * 
     * @return única instancia de ProcessUtil
     */
    public static ProcessUtil getInstance() {
        synchronized (ProcessUtil.class) {
            if (ProcessUtil.instance == null) {
                ProcessUtil.instance = new ProcessUtil();
            }
            return ProcessUtil.instance;
        }
    }

    /**
     * Manage history.
     * 
     * @param pHistory the history
     * @return list
     * @throws Exception la exception
     */
    protected static List<TaskInfo> manageHistory(Monitor monitor,List<TaskInfo> pHistory) throws Exception {
        if (pHistory == null) {
            return null;
        }
        for (TaskInfo taskInfo : pHistory) {
            Object tid = taskInfo.getTaskId();
            if (tid == null) {
                tid = taskInfo.getTaskId();
            }
            if (tid != null) {
                ProcessUtil.manageTaskId(monitor, taskInfo, Long.valueOf("" + tid));
            }
        }
        return pHistory;
    }

    /**
     * Manage task id.
     * 
     * @param pTask the task
     * @param pTID the tID
     * @throws Exception la exception
     */
    private static void manageTaskId(Monitor monitor,TaskInfo pTask, Long pTID) throws Exception {
        pTask.setTaskId(pTID);
        Map<Object, Object> aditionalData = pTask.getAditionalData();

        Task t = monitor.getTaskService().getTaskById(pTID);
        BAMTaskSummaryImpl bam =  monitor.getBAMTaskSummaryImpl(pTID);
        pTask.setCreated(new Timestamp(t.getTaskData().getCreatedOn().getTime()) );
        pTask.setStarted(new Timestamp(bam.getStartDate().getTime()) );
        pTask.setCompleted(new Timestamp(bam.getEndDate().getTime()));
        TaskData td = t.getTaskData();
        aditionalData.put("status", td.getStatus().name());
        aditionalData.put("userId", td.getActualOwner().getId());
        aditionalData.put("name", GeneralDescriptions.getUsername(td.getActualOwner().getId()));

    }

    /**
     * Crea una nueva instancia de process util.
     */
    private ProcessUtil() {
    }


    /**
     * Prepare record.
     * 
     * @param pName the name
     * @param pValue the value
     * @param pRequest the request
     * @param label the label
     * @return map
     * @throws Exception la exception
     */
    public Map<String, Object> prepareRecord(String pName, Object pValue, Request pRequest, boolean label) throws Exception {
        Map<String, Object> m = new HashMap<String, Object>();
        if (label) {
            m.put("NAME", GeneralDescriptions.getLabel(pName, pRequest.getLanguage(), pRequest.getChannelCode()));
        } else {
            m.put("NAME", pName);
        }
        m.put("VALUE", pValue);
        m.put("CODE", pName);
        return m;
    }

    /**
     * Prepare record.
     * 
     * @param pName the name
     * @param pValue the value
     * @param pRequest the request
     * @return map
     * @throws Exception la exception
     */
    public Map<String, Object> prepareRecord(String pName, Object pValue, Request pRequest) throws Exception {
        return this.prepareRecord(pName, pValue, pRequest, true);
    }



    /**
     * Transaction data.
     * 
     * @param pJournalId the journal id
     * @param pRequest the request
     * @param label the label
     * @return list
     * @throws Exception la exception
     */
    public List<Map<String, Object>> transactionData(String pJournalId, Request pRequest, boolean label) throws Exception {
        TgeneTransactionLog log = TgeneTransactionLog.find(PersistenceHelper.getEntityManager(), pJournalId);
        List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
        SimpleDateFormat sdf = DataHelper.getInstance().getDateTimeFormat(pRequest.getCompany());
        
        if(log!=null){
        	
        
        data.add(this.prepareRecord("creationdate", sdf.format(log.getRealdate()), pRequest, label));
        data.add(this.prepareRecord("user", log.getUsercode(), pRequest, label));
        data.add(this.prepareRecord("name", GeneralDescriptions.getOfficername(log.getUsercode()), pRequest, label));
        data.add(this.prepareRecord("email", GeneralDescriptions.getEmailByUser(log.getUsercode()), pRequest, label));
        data.add(this.prepareRecord("branch",
                log.getBranchcode() + " " + GeneralDescriptions.getBranchdesc(log.getBranchcode(), pRequest.getCompany()), pRequest, label));
        data.add(this.prepareRecord("office",
                log.getOfficecode() + " " + GeneralDescriptions.getOfficedesc(log.getOfficecode(), log.getBranchcode(), pRequest.getCompany()),
                pRequest, label));

        data.add(this.prepareRecord("transaction", log.getTransactionmodule() + "-" + log.getTransactioncode() + "-" + log.getTransactionversion()
                + " " + GeneralDescriptions.getTransactiondesc(log.getTransactionmodule(), log.getTransactioncode(), log.getTransactionversion()),
                pRequest, label));
        if (log.getAditionaldata() != null) {
            data.add(this.prepareRecord("message", log.getAditionaldata(), pRequest, label));
        }
        
        }
        return data;
    }

    /**
     * Transaction data.
     * 
     * @param pJournalId the journal id
     * @param pRequest the request
     * @return list
     * @throws Exception la exception
     */
    public List<Map<String, Object>> transactionData(String pJournalId, Request pRequest) throws Exception {
        return this.transactionData(pJournalId, pRequest, true);
    }
}
