package com.fp.bpmlib.flow;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fp.dto.Request;
import com.fp.dto.save.SaveRequest;
import com.fp.simple.flow.Asign;

// TODO: Auto-generated Javadoc
/**
 * Class RuleUtil encargada del manejo de las operaciones de una Regla.
 * 
 * @author gfiallos
 */
public final class RuleUtil {

    /**
     * Crea una nueva instancia de rule util.
     */
    private RuleUtil() {
    }

    /** El valor de message. */
    private static ThreadLocal<Map<String, Object>> message = new ThreadLocal<Map<String, Object>>();

    /**
     * Asign.
     * 
     * @param pMaia the maia
     * @param pClass the class
     * @throws Exception la exception
     */
    public static void asign(Map<String, Object> pMaia, String pClass) throws Exception {
        Asign asign = (Asign) Class.forName(pClass).newInstance();
        asign.setRequest(RuleUtil.getRequest(pMaia));
        RuleUtil.setAction(pMaia, "A");
        if (!asign.isGroup()) {
            RuleUtil.setUser(pMaia, asign.getId());
        } else {
            RuleUtil.setGroup(pMaia, asign.getId());
        }

    }

    /**
     * Asign officer.
     * 
     * @param pMaia the maia
     */
    public static void asignOfficer(Map<String, Object> pMaia) {
        String officer = RuleUtil.getRequest(pMaia).getString("officer");
        RuleUtil.setUser(pMaia, officer);
        RuleUtil.setAction(pMaia, "A");
    }

    /**
     * Obtiene el valor de amount.
     * 
     * @param pMaia the maia
     * @return Valor de amount
     */
    public static BigDecimal getAmount(Map<String, Object> pMaia) {
        return RuleUtil.getRequest(pMaia).getBigDecimal("amount");
    }

    /**
     * Obtiene el valor de financial amount.
     * 
     * @param pMaia the maia
     * @return Valor de financial amount
     */
    public static BigDecimal getFinancialAmount(Map<String, Object> pMaia) {
        return RuleUtil.getRequest(pMaia).getBigDecimal("financialamount");
    }

    /**
     * Obtiene el valor de rate.
     * 
     * @param pMaia the maia
     * @return Valor de rate
     */
    public static BigDecimal getRate(Map<String, Object> pMaia) {
        return RuleUtil.getRequest(pMaia).getBigDecimal("rate");
    }

    /**
     * Obtiene el valor de request.
     * 
     * @param pMaia the maia
     * @return Valor de request
     */
    public static Request getRequest(Map<String, Object> pMaia) {
        return (Request) pMaia.get("request");
    }

    /**
     * Obtiene el valor de save request.
     * 
     * @param pMaia the maia
     * @return Valor de save request
     */
    public static SaveRequest getSaveRequest(Map<String, Object> pMaia) {
        return (SaveRequest) RuleUtil.getRequest(pMaia);
    }

    /**
     * Obtiene el valor de term.
     * 
     * @param pMaia the maia
     * @return Valor de term
     */
    public static Integer getTerm(Map<String, Object> pMaia) {
        return RuleUtil.getRequest(pMaia).getInteger("term");
    }

    /**
     * Fija el valor de action.
     * 
     * @param pMaia the maia
     * @param pAction the action
     */
    public static void setAction(Map<String, Object> pMaia, String pAction) {
        pMaia.put("action", pAction);
    }

    /**
     * Fija el valor de action intermediate.
     * 
     * @param pMaia the maia
     * @param pAction the action
     */
    public static void setActionIntermediate(Map<String, Object> pMaia, String pAction) {
        pMaia.put("action", pAction);
        pMaia.put("internalCode", "Y");

    }

    /**
     * Fija el valor de group.
     * 
     * @param pMaia the maia
     * @param pGroup the group
     */
    public static void setGroup(Map<String, Object> pMaia, String pGroup) {
        pMaia.put("groupId", pGroup);
        RuleUtil.toGroup(pGroup);
    }

    /**
     * Fija el valor de user.
     * 
     * @param pMaia the maia
     * @param pUser the user
     */
    public static void setUser(Map<String, Object> pMaia, String pUser) {
        pMaia.put("userId", pUser);
    }

    /**
     * Obtiene el valor de message.
     * 
     * @return Valor de message
     */
    private static Map<String, Object> getMessage() {
        Map<String, Object> msg = null;
        synchronized (RuleUtil.message) {
            msg = RuleUtil.message.get();
            if (msg == null) {
                msg = new HashMap<String, Object>();
                RuleUtil.message.set(msg);
            }
        }
        return msg;
    }

    /**
     * To user.
     * 
     * @param pUser the user
     */
    public static void toUser(String pUser) {
        Map<String, Object> msg = RuleUtil.getMessage();
        @SuppressWarnings("unchecked")
        List<String> user = (List<String>) msg.get("user");
        if (user == null) {
            user = new ArrayList<String>();
            msg.put("user", user);
        }
        user.add(pUser);
    }

    /**
     * To group.
     * 
     * @param pGroup the group
     */
    public static void toGroup(String pGroup) {
        Map<String, Object> msg = RuleUtil.getMessage();
        @SuppressWarnings("unchecked")
        List<String> group = (List<String>) msg.get("group");
        if (group == null) {
            group = new ArrayList<String>();
            msg.put("group", group);
        }
        group.add(pGroup);
    }

    /**
     * To field.
     * 
     * @param pField the field
     */
    public static void toField(String pField) {
        Map<String, Object> msg = RuleUtil.getMessage();
        @SuppressWarnings("unchecked")
        List<String> field = (List<String>) msg.get("field");
        if (field == null) {
            field = new ArrayList<String>();
            msg.put("field", field);
        }
        field.add(pField);
    }

    /**
     * To address.
     * 
     * @param pField the field
     */
    public static void toAddress(String pAddress) {
        Map<String, Object> msg = RuleUtil.getMessage();
        @SuppressWarnings("unchecked")
        List<String> laddress = (List<String>) msg.get("address");
        if (laddress == null) {
            laddress = new ArrayList<String>();
            msg.put("address", laddress);
        }
        if (!laddress.contains(pAddress)) {
            laddress.add(pAddress);
        }
    }

    /**
     * Fija el valor de subject template.
     * 
     * @param pTemplate es el valor nuevo de subject template
     */
    public static void setSubjectTemplate(Integer pTemplate) {
        Map<String, Object> msg = RuleUtil.getMessage();
        msg.put("subject", pTemplate);
    }

    /**
     * Fija el valor de content template.
     * 
     * @param pTemplate es el valor nuevo de content template
     */
    public static void setContentTemplate(Integer pTemplate) {
        Map<String, Object> msg = RuleUtil.getMessage();
        msg.put("content", pTemplate);
    }

    /**
     * Send mail.
     * 
     * @param pRequest the request
     * @throws Exception la exception
     */
    public static void sendMail(Request pRequest) throws Exception {
        Class<?> c = Class.forName("com.fp.bpmlib.mail.MailCommand");
        Map<String, Object> msg = RuleUtil.getMessage();
        msg.put("request", pRequest);
        Constructor<?> con = c.getConstructor(Map.class);
        Object obj = con.newInstance(msg);
        Method m = c.getMethod("send");
        m.invoke(obj);
    }

}
