package com.fp.bpmlib.flow;

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

import com.fp.dto.Request;
import com.fp.persistence.commondb.PersistenceHelper;
import com.fp.persistence.pgeneral.gene.TgeneParameters;
import com.fp.persistence.pgeneral.gene.TgeneParametersKey;
import com.fp.simple.action.TaskAction;
import com.fp.simple.dto.Kind;
import com.fp.simple.dto.TaskInfo;
import com.fp.simple.flow.FlowClass;
import com.fp.simple.maia.MailRecipient;
import com.fp.simple.maia.MailRecipientGroup;

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

    /**
     * Crea una nueva instancia de flow util.
     */
    private FlowUtil() {
    }

    /**
     * Crea la instancia de task info.
     * 
     * @param pModule the module
     * @param pTransaction the transaction
     * @param pVersion the version
     * @param pMinutes the minutes
     * @param pKind the kind
     * @return task info
     * @throws Exception la exception
     */
    private static TaskInfo create(String pModule, Integer pTransaction, Integer pVersion, long pMinutes, String pKind) throws Exception {
        TaskInfo ti = new TaskInfo();
        ti.setModule(pModule);
        ti.setTransaction(pTransaction);
        ti.setVersion(pVersion);
        ti.setExpectedTime(pMinutes * 60000);
        ti.setKind(Kind.OK_NO);
        if (pKind.equals("OK")) {
            ti.setKind(Kind.OK);
        }
        if (pKind.equals("OK_NO_REVIEW")) {
            ti.setKind(Kind.OK_NO_REVIEW);
        }
        return ti;
    }

    /**
     * Crea la instancia de task info.
     * 
     * @param pModule the module
     * @param pTransaction the transaction
     * @param pVersion the version
     * @param pMinutes the minutes
     * @param pRule the rule
     * @param pKind the kind
     * @return task info
     * @throws Exception la exception
     */
    public static TaskInfo createTaskInfo(String pModule, Integer pTransaction, Integer pVersion, long pMinutes, String pRule, String pKind)
            throws Exception {
        TaskInfo ti = FlowUtil.create(pModule, pTransaction, pVersion, pMinutes, pKind);
        ti.setRuleCode(pRule);
        return ti;
    }

    /**
     * Crea la instancia de task info.
     * 
     * @param pModule the module
     * @param pTransaction the transaction
     * @param pVersion the version
     * @param pMinutes the minutes
     * @param pKind the kind
     * @return task info
     * @throws Exception la exception
     */
    public static TaskInfo createTaskInfo(String pModule, Integer pTransaction, Integer pVersion, long pMinutes,
            String taskName, Integer pMessageCode, String pKind) throws Exception {
        TaskInfo ti = FlowUtil.create(pModule, pTransaction, pVersion, pMinutes, pKind);
        ti.setMessageCode(pMessageCode);
        ti.setTname(taskName);
        return ti;
    }

    /**
     * Crea la instancia de task info.
     * 
     * @param pModule the module
     * @param pTransaction the transaction
     * @param pVersion the version
     * @param pMinutes the minutes
     * @param pClassName Paquete clase encargado de obtener el responsable de ejecutar una tarea.
     * @param pKind the kind
     * @return task info
     * @throws Exception la exception
     */
    public static TaskInfo createTaskInfoByClassName(String pModule, Integer pTransaction, Integer pVersion, long pMinutes, String pClassName,
            String taskName, Integer pMessageCode, String pKind) throws Exception {
        TaskInfo ti = FlowUtil.create(pModule, pTransaction, pVersion, pMinutes, pKind);
        ti.setClassCode(pClassName);
        ti.setMessageCode(pMessageCode);
        ti.setTname(taskName);
        return ti;
    }

    /**
     * Eval rule.
     * 
     * @param pName the name
     * @param pParam the param
     * @throws Exception la exception
     */
    public static void evalRule(String pName, Object pParam) throws Exception {
        if (pName == null) {
            return;
        }
        Class<?> c = Class.forName("com.fp.bpmlib.GuvnorClient");
        Object obj = c.getConstructor(String.class).newInstance(pName);
        c.getMethod("eval", Object.class).invoke(obj, pParam);
    }

    /**
     * Eval rule.
     * 
     * @param pName the name
     * @param pContext the context
     * @param pVar the var
     * @throws Exception la exception
     */
    public static void evalRule(String pName, Object pContext, String pVar) throws Exception {
        if (pName == null) {
            return;
        }
        Object val = FlowUtil.getVariable(pContext, pVar);
        FlowUtil.evalRule(pName, val);
        FlowUtil.setVariable(pContext, pVar, val);
    }

    /**
     * Eval rule.
     * 
     * @param pName the name
     * @param pParam the param
     * @throws Exception la exception
     */
    public static void executeClass(String pClassName, Object pParam) throws Exception {
        if (pClassName == null) {
            return;
        }
        TaskAction taction = (TaskAction) Class.forName(pClassName).newInstance();
        taction.assignOwner(pParam);
    }

    /**
     * Obtiene el valor de variable.
     * 
     * @param pContext the context
     * @param pVar the var
     * @return Valor de variable
     * @throws Exception la exception
     */
    public static Object getVariable(Object pContext, String pVar) throws Exception {
        return pContext.getClass().getMethod("getVariable", String.class).invoke(pContext, pVar);
    }

    /**
     * Fija el valor de variable.
     * 
     * @param pContext the context
     * @param pVar the var
     * @param pVal the val
     * @throws Exception la exception
     */
    public static void setVariable(Object pContext, String pVar, Object pVal) throws Exception {
        pContext.getClass().getMethod("setVariable", String.class, Object.class).invoke(pContext, pVar, pVal);
    }

    /**
     * End flow.
     * 
     * @param pContext the context
     * @throws Exception la exception
     */
    public static void endFlow(Object pContext) throws Exception {
        Class<?> c = Class.forName("com.fp.bpmlib.query.monitor.FlowEnd");
        FlowClass o = (FlowClass) c.getConstructor(Object.class).newInstance(pContext);
        o.process();
    }

    /**
     * Metodo que se encarga de enviar mails a un grupo de usuarios bpm definidos en TbpmGroupsUsers.
     * 
     * @param pClassName Paquete clase, que se encarga de obtener la lista de email asociados a un grupo.
     * @param pParam Request con los parametros de un flujo.
     * @param pSubjectTemplate Codigo de plantilla para generar el asusnto del mail.
     * @param pContentTemplate Codigo de plantilla para generar el contenido del maial.
     * @param pGroupCode Codigo de grupo del bpm.
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public static void mailGroup(String pClassName, Object pParam, TaskInfo taskinfo, Integer pSubjectTemplate, Integer pContentTemplate,
            String pGroupCode) throws Exception {
        RuleUtil.setSubjectTemplate(pSubjectTemplate);
        RuleUtil.setContentTemplate(pContentTemplate);
        List<String> lemail = new ArrayList<String>();
        if (pClassName != null) {
            MailRecipientGroup mail = (MailRecipientGroup) Class.forName(pClassName).newInstance();
            Map<String, Object> mresp = mail.getEmailAddress(pParam, pGroupCode);
            lemail = (List<String>) mresp.get("lemail");
        }
        for (String email : lemail) {
            RuleUtil.toField(email);
        }
        if (!lemail.isEmpty()) {
            HashMap<String, Object> m = (HashMap<String, Object>) pParam;
            ((Request) m.get("request")).put("cusuariobpm", taskinfo.getUserId());
            RuleUtil.sendMail((Request) m.get("request"));
        }
    }

    /**
     * Metodo que se encarga del envio de emails a destinatarios enteragdos por la clase que llega como parametro.
     * 
     * @param pClassName Paquete clase, que se encarga de obtener la lista de email a los cuales se envia
     *            notificaciones.
     * @param pParam Request con los parametros de un flujo.
     * @param pSubjectTemplate Codigo de plantilla para generar el asusnto del mail.
     * @param pContentTemplate Codigo de plantilla para generar el contenido del maial.
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public static void mail(String pClassName, Object pParam, TaskInfo taskinfo, Integer pSubjectTemplate, Integer pContentTemplate) throws Exception {
        RuleUtil.setSubjectTemplate(pSubjectTemplate);
        RuleUtil.setContentTemplate(pContentTemplate);
        List<String> lemail = new ArrayList<String>();
        if (pClassName != null) {
            MailRecipient mail = (MailRecipient) Class.forName(pClassName).newInstance();
            Map<String, Object> mresp = mail.getEmailAddress(pParam);
            lemail = (List<String>) mresp.get("lemail");
        }

        for (String email : lemail) {
            RuleUtil.toAddress(email);
        }
        if (!lemail.isEmpty()) {
            HashMap<String, Object> m = (HashMap<String, Object>) pParam;
            ((Request) m.get("request")).put("cusuariobpm", taskinfo.getUserId());
            if(taskinfo!=null && taskinfo.getAditionalData()!=null && taskinfo.getAditionalData().get("datosmail")!=null && !taskinfo.getAditionalData().get("datosmail").equals("")){
           	 	((Request) m.get("request")).putAll((Map)taskinfo.getAditionalData().get("datosmail"));
            }
            RuleUtil.sendMail((Request) m.get("request"));
        }else{
        	RuleUtil.setSubjectTemplate(63);
        	TgeneParameters addres=TgeneParameters.find(PersistenceHelper.getEntityManager(), new TgeneParametersKey("MAIL.CENTRAL", 1));
        	RuleUtil.toAddress(addres.getTextvalue());
        	 HashMap<String, Object> m = (HashMap<String, Object>) pParam;
             ((Request) m.get("request")).put("cusuariobpm", taskinfo.getUserId());
             if(taskinfo!=null && taskinfo.getAditionalData()!=null && taskinfo.getAditionalData().get("datosmail")!=null && !taskinfo.getAditionalData().get("datosmail").equals("")){
            	 ((Request) m.get("request")).putAll((Map)taskinfo.getAditionalData().get("datosmail"));
             }
             RuleUtil.sendMail((Request) m.get("request"));
        }
    }
    
    /**
     * Metodo que se encarga del envio de emails a destinatarios enteragdos por la clase que llega como parametro.
     * 
     * @param pClassName Paquete clase, que se encarga de obtener la lista de email a los cuales se envia
     *            notificaciones.
     * @param pParam Request con los parametros de un flujo.
     * @param pSubjectTemplate Codigo de plantilla para generar el asusnto del mail.
     * @param pContentTemplate Codigo de plantilla para generar el contenido del maial.
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public static void mailDocumentoAdjunto(String pClassName, Object pParam, TaskInfo taskinfo, Integer pSubjectTemplate, Integer pContentTemplate) throws Exception {
        RuleUtil.setSubjectTemplate(pSubjectTemplate);
        RuleUtil.setContentTemplate(pContentTemplate);
        List<String> lemail = new ArrayList<String>();
        if (pClassName != null) {
            MailRecipient mail = (MailRecipient) Class.forName(pClassName).newInstance();
            Map<String, Object> mresp = mail.getEmailAddress(pParam);
            lemail = (List<String>) mresp.get("lemail");
        }

        for (String email : lemail) {
            RuleUtil.toAddress(email);
        }
        if (!lemail.isEmpty()) {
            HashMap<String, Object> m = (HashMap<String, Object>) pParam;
            ((Request) m.get("request")).put("cusuariobpm", taskinfo.getUserId());
            if(taskinfo!=null && taskinfo.getAditionalData()!=null && taskinfo.getAditionalData().get("datosmail")!=null){
           	 ((Request) m.get("request")).putAll((Map)taskinfo.getAditionalData().get("datosmail"));
            }
            RuleUtil.sendMail((Request) m.get("request"));
        }else{
        	RuleUtil.setSubjectTemplate(63);
        	TgeneParameters addres=TgeneParameters.find(PersistenceHelper.getEntityManager(), new TgeneParametersKey("MAIL.CENTRAL", 1));
        	RuleUtil.toAddress(addres.getTextvalue());
        	 HashMap<String, Object> m = (HashMap<String, Object>) pParam;
             ((Request) m.get("request")).put("cusuariobpm", taskinfo.getUserId());
             if(taskinfo!=null && taskinfo.getAditionalData()!=null && taskinfo.getAditionalData().get("datosmail")!=null){
            	 ((Request) m.get("request")).putAll((Map)taskinfo.getAditionalData().get("datosmail"));
             }
            RuleUtil.sendMail((Request) m.get("request"));
        }
    }


}
