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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.EntityManager;

import org.apache.log4j.Logger;
import org.jbpm.ruleflow.instance.RuleFlowProcessInstance;
import org.kie.api.runtime.process.ProcessContext;

import com.fp.bpmlib.task.TaskCleaner;
import com.fp.bpmlib.task.client.HumanTaskClient;
import com.fp.common.helper.Constant;
import com.fp.dto.data.SaveData;
import com.fp.dto.save.SaveRequest;
import com.fp.persistence.commondb.PersistenceHelper;
import com.fp.persistence.commondb.helper.FormatDates;
import com.fp.persistence.pbpm.gene.TbpmProcessInstance;
import com.fp.persistence.pbpm.gene.TbpmProcessVariables;
import com.fp.persistence.pbpm.gene.TbpmProcessVariablesKey;
import com.fp.simple.flow.FlowClass;

/**
 * Class FlowEnd encargada de.
 * 
 * @author gfiallos
 */
public class FlowEnd implements FlowClass {
    /**
     * Logger
     */
    private static final Logger LOG = Logger.getLogger(FlowEnd.class);

    /** El valor de instance. */
    private final TbpmProcessInstance instance;

    /** El valor de . */
    private final RuleFlowProcessInstance p;

    /** El valor de htc. */
    private final HumanTaskClient htc;

    /** El valor de tc. */
    private final TaskCleaner tc;

    private final List<TbpmProcessVariables> lprocessvariable = new ArrayList<TbpmProcessVariables>();

//    private final List<TbpmActivities> lactivities = new ArrayList<TbpmActivities>();

    /**
     * Crea una nueva instancia de flow end.
     * 
     * @param pContext the context
     * @throws Exception la exception
     */
    public FlowEnd(Object pContext) throws Exception {
        ProcessContext ctx = (ProcessContext) pContext;
        p = (RuleFlowProcessInstance) ctx.getProcessInstance();
        long processId = p.getId();
        EntityManager em = PersistenceHelper.getEntityManager();
        instance = TbpmProcessInstance.findByProcessId(em, processId);
        // TgeneTransactionLog log = TgeneTransactionLog.find(this.em, this.instance.getPk());
        // this.p = new Process(this.processId, this.instance.getSnapshot());
        htc = new HumanTaskClient();
        tc = new TaskCleaner();
    }

    /**
     * Process.
     * 
     * @throws Exception la exception
     */
    @SuppressWarnings("unchecked")
    @Override
    public void process() throws Exception {
        try {
            FlowEnd.LOG.info("Inicia respaldo Flujo");
            Map<String, Object> m = p.getVariables();
            for (Entry<String, Object> e : m.entrySet()) {
//                if (e.getKey().compareTo("tasksMetaData") == 0) {
//                    this.manageActivities((Map<String, Object>) e.getValue());
//                    continue;
//                }
                if (e.getKey().compareTo("maia") == 0) {
                    for (Entry<String, Object> e1 : ((Map<String, Object>) e.getValue()).entrySet()) {
                        this.saveVariable(e1.getKey(), e1.getValue());
                    }
                    continue;
                }
                this.saveVariable(e.getKey(), e.getValue());
            }
            // PersistenceHelper.flushTransaction();
//            FlowEnd.LOG.info("Luego de Variables");
            instance.setEnddate(FormatDates.getInstance().getDataBaseDate());
            instance.setFinalized(Constant.STR_Y);
            PersistenceHelper.saveOrUpdate(instance);
            this.close();

            SaveRequest sr = SaveData.getSaveRequest();
            sr.putSaveBean("TBPMPROCESSVARIABLES", lprocessvariable);
            // sr.putSaveBean("TBPMACTIVITIES", lactivities);
            // sr.putSaveBean("TBPMTASKCOMMENTS", ltaskcomments);

            // Eliminar tareas para que no tengan un workitem, puede ser de proceso diferentes.
            tc.deleteTasks();
            FlowEnd.LOG.info("Luego de Instancia");
        } catch (Exception e) {
            FlowEnd.LOG.error(e, e);
            throw e;
        }
    }

    /**
     * Save variable.
     * 
     * @param pKey the key
     * @param pValue the value
     * @throws Exception la exception
     */
    private void saveVariable(String pKey, Object pValue) throws Exception {
        TbpmProcessVariablesKey pk = new TbpmProcessVariablesKey(instance.getPk(), pKey);
        TbpmProcessVariables var = new TbpmProcessVariables();
        var.setPk(pk);
        if (pValue == null) {
            return;
        }
        Map<String, Object> rec = new HashMap<String, Object>();
        rec.put(pKey, pValue);
        try {
            var.setContent(".");
            // Serializer ser = new Serializer((Serializable) rec);
            // var.setContent(ser.toJSON());
            // PersistenceHelper.saveOrUpdate(var);
            // PersistenceHelper.getEntityManager().persist(var);
            var.put("isnew", true);
            lprocessvariable.add(var);
        } catch (Exception e) {
            // no hacer nada
        }

    }

//    /**
//     * Manage activities.
//     * 
//     * @param pValues the values
//     * @throws Exception la exception
//     */
//    private void manageActivities(Map<String, Object> pValues) throws Exception {
//        FlowEnd.LOG.info("Maneja Actividades");
//        for (Entry<String, Object> e : pValues.entrySet()) {
//            @SuppressWarnings("unchecked")
//            List<TaskInfo> l = (List<TaskInfo>) e.getValue();
//            for (int i = 0; i < l.size(); i++) {
//                try {
//                    TaskInfo taskInfo = l.get(i);
//                    this.manageActivity(taskInfo, e.getKey(), i);
//                } catch (Exception e1) {
//                    if (e1 instanceof SQLException) {
//                        throw e1;
//                    }
//                    continue;
//                }
//            }
//        }
//        FlowEnd.LOG.info("Fin de Maneja Actividades");
//    }

//    /**
//     * Manage activity.
//     * 
//     * @param pTaskInfo the task info
//     * @param pActivityname the activityname
//     * @param pSequence the sequence
//     * @throws Exception la exception
//     */
//    private void manageActivity(TaskInfo pTaskInfo, String pActivityname, Integer pSequence) throws Exception {
//        TbpmActivitiesKey k = new TbpmActivitiesKey(instance.getPk(), pActivityname, pSequence);
//        TbpmActivities act = new TbpmActivities();
//        act.setPk(k);
//        Field[] fs = TbpmActivities.class.getDeclaredFields();
//        for (Field field : fs) {
//            try {
//                Object val = BeanManager.getBeanAttributeValue(pTaskInfo, field.getName());
//                val = BeanManager.convertObject(val, BeanManager.getBeanGetterMethod(act, field.getName()).getReturnType());
//                BeanManager.setBeanAttributeValue(act, field.getName(), val);
//            } catch (NoSuchMethodException e) {
//                continue;
//            }
//        }
//        if (pTaskInfo.getAditionalData() != null) {
//            Serializer ser = new Serializer((Serializable) pTaskInfo.getAditionalData());
//            act.setAditionaldata(ser.toJSON());
//        }
//        act.setGroupcode(pTaskInfo.getGroupId());
//        act.setUsercode(pTaskInfo.getUserId());
//        act.setExpectedtime(pTaskInfo.getExpectedTime());
//        act.setTaskjournalid(pTaskInfo.getJournalId());
//        act.setTaskid(pTaskInfo.getTaskId());
//        act.setRulecode(pTaskInfo.getRuleCode());
//        act.setRulecodedefault(pTaskInfo.getRuleCodeDefault());
//        act.setTaskid(pTaskInfo.getTaskId());
//        act.setInternalcode("" + pTaskInfo.getInternalCode());
//
//        BAMTaskSummaryImpl bam = this.getBAMTaskSummaryImpl(act.getTaskid());
//        act.setStarted(new Timestamp(bam.getStartDate().getTime()));
//        act.setCompleted(new Timestamp(bam.getEndDate().getTime()));
//
//        AuditTaskImpl atask = this.getAuditTaskImpl(act.getTaskid());
//        act.setCreated(new Timestamp(atask.getCreatedOn().getTime()));
//
//        this.manageTask(act);
//        PersistenceHelper.saveOrUpdate(act);
//        lactivities.add(act);
//
//    }

//    /**
//     * Manage task.
//     * 
//     * @param pAct the act
//     * @throws Exception la exception
//     */
//    private void manageTask(TbpmActivities pAct) throws Exception {
//        Task t = htc.getTaskById(pAct.getTaskid());
//        TaskData td = t.getTaskData();
//        pAct.setUsercode(td.getActualOwner().getId());
//        List<Comment> lc = td.getComments();
//        for (Comment comment : lc) {
//            TbpmTaskComments c = new TbpmTaskComments(comment.getId(), new Date(comment.getAddedAt().getTime()), comment.getText(), pAct.getTaskid());
//            c.setUsercode(comment.getAddedBy().getId());
//            PersistenceHelper.saveOrUpdate(c);
//        }
//    }

    /**
     * Close.
     * 
     * @throws Exception la exception
     */
    private void close() throws Exception {
        // this.p.close();
        htc.close();

    }

//    /**
//     * JPQL TAREA_SUMMARY
//     */
//    private static final String TAREA_SUMMARY = "select t from BAMTaskSummaryImpl t where t.taskId = :idtarea";

//    /**
//     * Obtiene el valor de unfinished tasks por Grupo.
//     * 
//     * @param pGroupId the user id
//     * @param pCri the cri
//     * @return Valor de unfinished tasks
//     * @throws Exception la exception
//     */
//    public BAMTaskSummaryImpl getBAMTaskSummaryImpl(long idtarea) throws Exception {
//        JbpmBeanLocal local = (JbpmBeanLocal) new InitialContext().lookup("java:global/maiaear-2.1/bpmlib/jbpmbean");
//        EntityManager em = null;
//        BAMTaskSummaryImpl dato = null;
//        try {
//            em = local.getEmf().createEntityManager();
//            Query qry = em.createQuery(TAREA_SUMMARY);
//            qry.setParameter("idtarea", idtarea);
//            dato = (BAMTaskSummaryImpl) qry.getSingleResult();
//        } catch (NoResultException e) {
//            // retorna el objeto en null.
//        } finally {
//            if (em.isOpen()) {
//                em.close();
//            }
//        }
//        return dato;
//    }
//
//    /**
//     * JPQL TAREA_SUMMARY
//     */
//    private static final String TAREA_AUDIT_IMP = "select t from AuditTaskImpl t where t.taskId = :idtarea";
//
//    public AuditTaskImpl getAuditTaskImpl(long idtarea) throws Exception {
//        JbpmBeanLocal local = (JbpmBeanLocal) new InitialContext().lookup("java:global/maiaear-2.1/bpmlib/jbpmbean");
//        EntityManager em = null;
//        AuditTaskImpl dato = null;
//        try {
//            em = local.getEmf().createEntityManager();
//            Query qry = em.createQuery(TAREA_AUDIT_IMP);
//            qry.setParameter("idtarea", idtarea);
//            dato = (AuditTaskImpl) qry.getSingleResult();
//        } catch (NoResultException e) {
//            // retorna el objeto en null.
//        } finally {
//            if (em.isOpen()) {
//                em.close();
//            }
//        }
//        return dato;
//    }
}
