package com.fp.frontend.controller.bpm;

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

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

import org.primefaces.component.accordionpanel.AccordionPanel;
import org.primefaces.event.TabChangeEvent;

import com.fp.dto.AbstractDataTransport;
import com.fp.dto.Request;
import com.fp.dto.Response;
import com.fp.dto.query.DtoQuery;
import com.fp.dto.query.SubQuery;
import com.fp.frontend.controller.AbstractController;
import com.fp.frontend.controller.armas.parametros.TarmCentroControlJurController;
import com.fp.frontend.controller.armas.solicitud.DocumentoHabilitanteController;
import com.fp.frontend.controller.armas.solicitud.SolicitudController;
import com.fp.frontend.controller.armas.solicitud.TarmTramiteController;
import com.fp.frontend.controller.pcustomer.PersonDetailController;
import com.fp.frontend.controller.pgeneral.gene.CatalogDetailController;
import com.fp.frontend.controller.pgeneral.gene.ParametersController;
import com.fp.frontend.controller.pgeneral.gene.ProvinceController;
import com.fp.frontend.helper.MessageHelper;
import com.fp.persistence.parmas.param.TarmCentroControlJur;
import com.fp.persistence.parmas.param.TarmTramite;
import com.fp.persistence.parmas.soli.TarmDocumentoHabilitante;
import com.fp.persistence.parmas.soli.TarmSolicitud;
import com.fp.persistence.pbpm.gene.TbpmGroupsUsers;
import com.fp.persistence.pcustomer.gene.TcustPersonDetail;
import com.fp.persistence.pgeneral.gene.TgeneParameters;
import com.fp.persistence.pgeneral.gene.TgeneProvince;
import com.fp.persistence.pgeneral.log.TgeneTransactionLog;
import com.fp.persistence.pgeneral.safe.TsafeUserDetail;
import org.primefaces.context.RequestContext;

/**
 * Clase que muestra
 *
 * @author amerchan
 * @version 2.1
 */
@ManagedBean
@SessionScoped
public class InboxController extends AbstractController<TgeneTransactionLog> {

    private static final long serialVersionUID = 1L;

    private List<TbpmGroupsUsers> lBpmGroups;

    private List<Map<String, Object>> lTransactionsByGroup;

    private List<Map<String, Object>> lTransactions;
    private String beanGroupsName;

    private String codBpmGroupSelected;

    private String bpmDataStatus;

    private String bpmDataComment;

    private String filterTaskName;

    private int tabDiaryId;

    private int accordionTaskTabId;

    private int accordionGroupTabId;

    private List<String> ltaskidinprocess = new ArrayList<>();

    public InboxController() throws Exception {
        super(TgeneTransactionLog.class);
    }

    @PostConstruct
    private void postconstruct() {
        this.init();
        // Inicializa autoconsulta
        super.startQuery();
    }

    /**
     * Incializa el controlador, cuando se esta utilizando una pagina que utliza
     * el controlador.
     */
    private void init() {
        try {
            beanGroupsName = "BPMGROUPS";
            this.listGroups();

        } catch (Exception e) {
            MessageHelper.setMessageError(e);
        }
    }

    @Override
    protected void querydatabase() {

    }

    @SuppressWarnings("unchecked")
    protected void listGroups() {
        try {
            Request request = callerhelper.getRequest();
            Map<String, String> mGroupsFilter = new HashMap<String, String>();
            mGroupsFilter.put("pk.usercode", super.getLoginController().getRequest().getUser());
            mGroupsFilter.put("pk.companycode", super.getLoginController().getRequest().getCompany().toString());
            DtoQuery dto = new DtoQuery(TbpmGroupsUsers.class.getName(), page, 100, true, mGroupsFilter);
            SubQuery subquery = new SubQuery("TbpmGroups", "description", "groupName",
                    "i.pk.groupcode = t.pk.groupcode and i.pk.companycode=t.pk.companycode");
            dto.addSubQuery(subquery);

            HashMap<String, DtoQuery> mtables = new HashMap<String, DtoQuery>();
            mtables.put(beanGroupsName, dto); // permite adicionar mas de una tabla.
            request.setQueryTables(mtables);

            Response resp = callerhelper.executeQuery(request);

            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) != 0) {
                lBpmGroups = new ArrayList<TbpmGroupsUsers>();
                MessageHelper.setMessageError(resp);
            } else {
                lBpmGroups = (List<TbpmGroupsUsers>) resp.get(beanGroupsName);
                if ((lBpmGroups != null) && !lBpmGroups.isEmpty()) {
                    codBpmGroupSelected = lBpmGroups.get(0).getPk().getGroupcode();
                }
                super.postQuery((List<AbstractDataTransport>) resp.get(beanGroupsName));
            }

        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    @SuppressWarnings("unchecked")
    public void queryTransactionsByGroup() {
        try {
            ltaskidinprocess = new ArrayList<>();
            this.initBpmData();
            Request request = callerhelper.getRequest();
            request.put("queryalias", "INBOX_TRN_GROUP");
            request.put("querytype", "P");
            request.put("groupId", codBpmGroupSelected);
            Response resp = callerhelper.executeQuery(request);
            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) != 0) {
                lTransactionsByGroup = new ArrayList<Map<String, Object>>();
                MessageHelper.setMessageError(resp);
            } else {
                 lTransactionsByGroup = (List<Map<String, Object>>) resp.get("transactions");


            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
        if ((lTransactionsByGroup != null) && !lTransactionsByGroup.isEmpty()) {
            this.fillTransactions(lTransactionsByGroup, true);
        }
    }

    @SuppressWarnings("unchecked")
    public void queryTransactions() {
        try {
            ltaskidinprocess = new ArrayList<>();
            this.initBpmData();
            Request request = callerhelper.getRequest();
            request.put("queryalias", "INBOX_TRN");
            request.put("querytype", "P");
            /** VARIABLES PARA BUSCAR EL TIPO AUTORIZACION SI ES QUE ES SOLICITUD */
            String logSolicitude = null;
            TarmSolicitud solicitud= null;
            TarmTramite tramite = null; 
            String tipoAutorizacionAux = null;
            String tipoAutorizacion = null;
            Response resp = callerhelper.executeQuery(request);
            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) != 0) {
                lTransactions = new ArrayList<Map<String, Object>>();
                MessageHelper.setMessageError(resp);
            } else {
                //Manipular la respuesta de transacciones 'No conozco la base del jbpm'
                List<Map<String, Object>> lstAux = (List<Map<String, Object>>) resp.get("transactions");
                List<Map<String, Object>> lTasks;
                Map<String,Object> mapaPadre;
                Map<String, Object> lTask;
                for (int i = 0; i < lstAux.size(); i++) {
                    mapaPadre = lstAux.get(i);
                    lTasks =(List<Map<String, Object>>) mapaPadre.get("tasks");
                    if(lTasks !=null){
                        for (int j = 0; j < lTasks.size(); j++) {
                            logSolicitude =  lTasks.get(j).get("logsolicitude").toString();

                            tipoAutorizacion = verificarTipoAutorizacion(logSolicitude, solicitud, tramite, tipoAutorizacionAux);
                            lTask = (Map<String, Object>) lTasks.get(j);
                            lTask.put("tipoAutorizacion", tipoAutorizacion);
                            lTasks.set(j, lTask);
                        }
                    }
                    
                    
                    
                    mapaPadre.put("tasks",lTasks); 
                    lstAux.set(i, mapaPadre);
                   
                    /**
                    Map<String, Object> objeto = lstAux.get(i) ;
                    objeto.put("tasks", task);
                    lstAux.set(i, objeto);*/
                }
                lTransactions = lstAux;
            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
        if ((lTransactions != null) && !lTransactions.isEmpty()) {
            // no hacer la consulta entrega el detalle de la tarea.
            // this.fillTransactions(this.lTransactions, false);
        }
    }
    
    /**
     * METODO PARA OBTENER EL TIPO DE AUTORIZACION CON LOGSOLICITUDE
     */
    public String verificarTipoAutorizacion(String logSolicitude,TarmSolicitud solicitud, TarmTramite tramite,String tipoAutorizacion){
        try {
            if(logSolicitude!= null && logSolicitude.trim().startsWith("SOL-")){
                solicitud = SolicitudController.findSolicitudxnumerosolicitud(logSolicitude.trim());
                tramite = TarmTramiteController.find(solicitud.getCtramite().toString());
                tipoAutorizacion = CatalogDetailController.findCatalogo(tramite.getTipoautorizacioncodigo(), tramite.getTipoautorizacion()).getDescription();

            }
        } catch (Exception e) {
            tipoAutorizacion="";
            e.printStackTrace();
        }
        return tipoAutorizacion;
    }
    private void fillTransactions(List<Map<String, Object>> lTransactions, boolean isGroup) {
        String tModule;
        Integer tCode;
        Integer tVersion;
        for (Map<String, Object> map : lTransactions) {
            tModule = (String) map.get("m");
            tCode = (Integer) map.get("t");
            tVersion = (Integer) map.get("v");
            this.fillTasks(map, tModule, tCode, tVersion, isGroup);
        }
    }

    @SuppressWarnings("unchecked")
    private void fillTasks(Map<String, Object> map, String tModule, Integer tCode, Integer tVersion, boolean isGroup) {
        try {
            Request request = callerhelper.getNewRequest(tModule, tCode, tVersion);
            String filtertasks = filterTaskName;
            if (isGroup) {
                request.put("queryalias", "INBOX_TASK_TRN_GROUP");
                request.put("querytype", "P");
                request.put("groupId", codBpmGroupSelected);
            } else {
                request.put("queryalias", "INBOX_TASK_TRN");
            }

            if ((filtertasks == null) || filtertasks.isEmpty()) {
                filtertasks = "%";
            }
            request.put("cri", filtertasks);

            Response resp = callerhelper.executeQuery(request);
            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) != 0) {
                MessageHelper.setMessageError(resp);
            } else {
                List<Map<String, Object>> lTasks = (List<Map<String, Object>>) resp.get("tasks");
                map.put("tasks", lTasks);
                
                /**
                 * BUSCANDO EL TIPO AUTORIZACION
                 */
                String logSolicitude;
                String tipoAutorizacion;
                TarmSolicitud solicitud= null;
                TarmTramite tramite = null; 
                String tipoAutorizacionAux = null;
                for (Map<String, Object> mapTask : lTasks) {
                    logSolicitude = mapTask.get("logsolicitude").toString();
                    if(logSolicitude.startsWith("SOL-")){
                        tipoAutorizacion = verificarTipoAutorizacion(logSolicitude, solicitud, tramite, tipoAutorizacionAux);
                        mapTask.put("tipoAutorizacion",  tipoAutorizacion);
                    }
                    this.fillTaskDetail(mapTask);
                }
            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    @SuppressWarnings("unchecked")
    private void fillTaskDetail(Map<String, Object> mapTask) {
        try {
            Request request = callerhelper.getNewRequest(null, null, null);
            request.put("queryalias", "INBOX_TASK_DETAIL");
            request.put("querytype", "P");
            request.put("TID", mapTask.get("tid"));

            Response resp = callerhelper.executeQuery(request);
            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) != 0) {
                MessageHelper.setMessageError(resp);
            } else {
                Map<String, Object> param = (Map<String, Object>) resp.get("param");
                
                param.put("TID", mapTask.get("tid"));
                param.put("KIND", resp.get("k"));
                mapTask.put("taskDetail", resp);
                
            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    public void initBpmData() throws Exception {
        lTransactionsByGroup = new ArrayList<Map<String, Object>>();
        lTransactions = new ArrayList<Map<String, Object>>();
        bpmDataStatus = "";
        bpmDataComment = "";
        filterTaskName = "";
        String tabDiaryId = super.getRequestParameter("tabDiary");
        try {
            this.tabDiaryId = Integer.parseInt(tabDiaryId);
        } catch (Exception e) {
        }
    }

    public void enableBpmData() {
        try {
            String kind = super.getRequestParameter("kind");
            String status = super.getRequestParameter("s");
            if (kind == null) {
                return;
            }
            if (status.compareTo("Reserved") == 0) {
                this.initTask();
            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    public void initTask() throws Throwable {
        String tid = super.getRequestParameter("tid");
        if (ltaskidinprocess.contains(tid)) {
            return;
        }
        Request request = callerhelper.getNewRequest("2", 2001, 1);
        request.modifiedData().put("TID", tid);
        Response resp = callerhelper.executeSave(request);
        if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) == 0) {
            ltaskidinprocess.add(tid);
            this.postCommit(resp);
            MessageHelper.setMessageInfo(resp);
        } else {
            MessageHelper.setMessageError(resp);
        }
    }

    public void assignTask() {
        try {
            String taskId = super.getRequestParameter("tid");
            Request request = callerhelper.getNewRequest("2", 2000, 1);
            request.modifiedData().put("TID", taskId);
            Response resp = callerhelper.executeSave(request);
            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) == 0) {
                this.postCommit(resp);
                MessageHelper.setMessageInfo(resp);
            } else {
                MessageHelper.setMessageError(resp);
            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    public void filterTasks() {
        try {
            String tModule = super.getRequestParameter("tModule");
            Integer tCode = Integer.parseInt(super.getRequestParameter("tCode"));
            Integer tVersion = Integer.parseInt(super.getRequestParameter("tVersion"));
            filterTaskName = super.getRequestParameter("filterTaskName");

            Map<String, Object> map = this.getTransactionMap(lTransactions, tModule, tCode, tVersion);
            this.fillTasks(map, tModule, tCode, tVersion, false);
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    public void filterTasksGroups() {
        try {
            String tModule = super.getRequestParameter("tModule");
            Integer tCode = Integer.parseInt(super.getRequestParameter("tCode"));
            Integer tVersion = Integer.parseInt(super.getRequestParameter("tVersion"));
            filterTaskName = super.getRequestParameter("filterTaskName");

            Map<String, Object> map = this.getTransactionMap(lTransactionsByGroup, tModule, tCode, tVersion);

            this.fillTasks(map, tModule, tCode, tVersion, true);
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    private Map<String, Object> getTransactionMap(List<Map<String, Object>> lTransactions, String tModule, Integer tCode, Integer tVersion) {
        String module = null;
        Integer transaction = null;
        Integer version = null;
        for (Map<String, Object> map : lTransactions) {
            
            module = (String) map.get("m");
             transaction = (Integer) map.get("t");
             version = (Integer) map.get("v");

            if ((tModule.compareTo(module) == 0) && (tCode.compareTo(transaction) == 0) && (tVersion.compareTo(version) == 0)) {
                return map;
            }
        }
        return null;
    }

    public void onAccordionTasksTabChange(TabChangeEvent event) {
        // System.out.println(((AccordionPanel)event.getSource()).getPage());
        accordionTaskTabId = Integer.parseInt(((AccordionPanel) event.getSource()).getActiveIndex());
    }

    public void onAccordionGroupsTabChange(TabChangeEvent event) {
        // event.getTab().getId()
        accordionGroupTabId = Integer.parseInt(((AccordionPanel) event.getSource()).getActiveIndex());
    }

    /**
     * Entrega el valor de: beanGroupsName
     *
     * @return String
     */
    public String getBeanGroupsName() {
        return beanGroupsName;
    }

    /**
     * Fija el valor de: beanGroupsName
     *
     * @param beanGroupsName Valor a fijar en el atributo
     */
    public void setBeanGroupsName(String beanGroupsName) {
        this.beanGroupsName = beanGroupsName;
    }

    /**
     * Entrega el valor de: lBpmGroups
     *
     * @return List<TbpmGroupsUsers>
     */
    public List<TbpmGroupsUsers> getlBpmGroups() {
        return lBpmGroups;
    }

    /**
     * Fija el valor de: lBpmGroups
     *
     * @param lBpmGroups Valor a fijar en el atributo
     */
    public void setlBpmGroups(List<TbpmGroupsUsers> lBpmGroups) {
        this.lBpmGroups = lBpmGroups;
    }

    /**
     * Entrega el valor de: lTransactionsByGroup
     *
     * @return List<Map<String,Object>>
     */
    public List<Map<String, Object>> getlTransactionsByGroup() {
        return lTransactionsByGroup;
    }

    /**
     * Fija el valor de: lTransactionsByGroup
     *
     * @param lTransactionsByGroup Valor a fijar en el atributo
     */
    public void setlTransactionsByGroup(List<Map<String, Object>> lTransactionsByGroup) {
        this.lTransactionsByGroup = lTransactionsByGroup;
    }

    /**
     * Entrega el valor de: lTransactions
     *
     * @return List<Map<String,Object>>
     */
    public List<Map<String, Object>> getlTransactions() {
        return lTransactions;
    }

    /**
     * Fija el valor de: lTransactions
     *
     * @param lTransactions Valor a fijar en el atributo
     */
    public void setlTransactions(List<Map<String, Object>> lTransactions) {
        this.lTransactions = lTransactions;
    }
   
    

    /**
     * Entrega el valor de: bpmDataStatus
     *
     * @return String
     */
    @Override
    public String getBpmDataStatus() {
        return bpmDataStatus;
    }

    /**
     * Fija el valor de: bpmDataStatus
     *
     * @param bpmDataStatus Valor a fijar en el atributo
     */
    @Override
    public void setBpmDataStatus(String bpmDataStatus) {
        this.bpmDataStatus = bpmDataStatus;
    }

    /**
     * Entrega el valor de: bpmDataComment
     *
     * @return String
     */
    @Override
    public String getBpmDataComment() {
        return bpmDataComment;
    }

    /**
     * Fija el valor de: bpmDataComment
     *
     * @param bpmDataComment Valor a fijar en el atributo
     */
    @Override
    public void setBpmDataComment(String bpmDataComment) {
        this.bpmDataComment = bpmDataComment;
    }

    /**
     * Entrega el valor de: taskFilter
     *
     * @return String
     */
    public String getFilterTaskName() {
        return filterTaskName;
    }

    /**
     * Fija el valor de: taskFilter
     *
     * @param taskFilter Valor a fijar en el atributo
     */
    public void setFilterTaskName(String taskFilter) {
        filterTaskName = taskFilter;
    }

    /**
     * Entrega el valor de: tabDiaryId
     *
     * @return int
     */
    public int getTabDiaryId() {
        return tabDiaryId;
    }

    /**
     * Fija el valor de: tabDiaryId
     *
     * @param tabDiaryId Valor a fijar en el atributo
     */
    public void setTabDiaryId(int tabDiaryId) {
        this.tabDiaryId = tabDiaryId;
    }

    /**
     * Entrega el valor de: accordionTaskTabId
     *
     * @return int
     */
    public int getAccordionTaskTabId() {
        return accordionTaskTabId;
    }

    /**
     * Fija el valor de: accordionTaskTabId
     *
     * @param accordionTaskTabId Valor a fijar en el atributo
     */
    public void setAccordionTaskTabId(int accordionTaskTabId) {
        this.accordionTaskTabId = accordionTaskTabId;
    }

    /**
     * Entrega el valor de: accordionGroupTabId
     *
     * @return int
     */
    public int getAccordionGroupTabId() {
        return accordionGroupTabId;
    }

    /**
     * Fija el valor de: accordionGroupTabId
     *
     * @param accordionGroupTabId Valor a fijar en el atributo
     */
    public void setAccordionGroupTabId(int accordionGroupTabId) {
        this.accordionGroupTabId = accordionGroupTabId;
    }

    /**
     * Entrega el valor de: codBpmGroupSelected
     *
     * @return String
     */
    public String getCodBpmGroupSelected() {
        return codBpmGroupSelected;
    }

    /**
     * Fija el valor de: codBpmGroupSelected
     *
     * @param codBpmGroupSelected Valor a fijar en el atributo
     */
    public void setCodBpmGroupSelected(String codBpmGroupSelected) {
        this.codBpmGroupSelected = codBpmGroupSelected;
    }

    public void logout() {
        FacesContext fc = FacesContext.getCurrentInstance();
        if (fc != null) {
            fc.getExternalContext().invalidateSession();
        }
    }
    
    /**
     ================== METODOS DE ALERTAS ==================
     
     */
    
    
    /**
     * OBTENER PERSONA DE USUARIO LOGEADO
     */
    private TcustPersonDetail buscarPersonaSesion(){
        TcustPersonDetail person = null;
        try {
            TsafeUserDetail tsafeUserDetail = (TsafeUserDetail) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("TSAFEUSERDETAIL");
            person = PersonDetailController.find(tsafeUserDetail.getPk().getPersoncode().toString());

        } catch (Exception e) {
            MessageHelper.setMessageError(String.format("Verifique que el usuario este asociado a una persona: %s", e.getMessage()));
        }
        return person;
    }
}
