package com.fp.frontend.controller.armas.solicitud;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;

import org.apache.commons.fileupload.RequestContext;

import com.fp.dto.Request;
import com.fp.dto.Response;
import com.fp.dto.query.DtoQuery;
import com.fp.dto.query.Filter;
import com.fp.dto.save.DtoSave;
import com.fp.frontend.controller.AbstractController;
import com.fp.frontend.controller.ReportController;
import com.fp.frontend.controller.armas.parametros.CentroControlArmasController;
import com.fp.frontend.controller.armas.parametros.TarmCentroControlJurController;
import com.fp.frontend.controller.armas.parametros.TiposArmasExplosivosController;
import com.fp.frontend.controller.pcustomer.PersonAddressController;
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.helper.MessageHelper;
import com.fp.frontend.utility.MsgControlArmas;
import com.fp.persistence.parmas.param.TarmCentroControl;
import com.fp.persistence.parmas.param.TarmCentroControlJur;
import com.fp.persistence.parmas.param.TarmTipoArmaExplosivo;
import com.fp.persistence.parmas.soli.TarmArmas;
import com.fp.persistence.parmas.soli.TarmSolicitud;
import com.fp.persistence.parmas.soli.TarmSolicitudArmas;
import com.fp.persistence.parmas.soli.TarmSolicitudTramite;
import com.fp.persistence.pcustomer.gene.TcustPersonAddress;
import com.fp.persistence.pcustomer.gene.TcustPersonDetail;
import com.fp.persistence.pgeneral.gene.TgeneCatalogDetail;
import com.fp.persistence.pgeneral.gene.TgeneParameters;
import com.fp.persistence.pgeneral.safe.TsafeUserDetail;

@SuppressWarnings("serial")
@ManagedBean
@ViewScoped
public class VerificacionInformacionDevolucionController extends AbstractController<TarmSolicitudArmas> {

    private TarmCentroControl centroControl;
    TarmCentroControlJur jurisdiccionCentroControl;
    private String nombreCentroControl;
    TcustPersonDetail jefeCentroControl;
    String gradoFuncionario = "";

    private String csolicitud;

    private List<TarmArmas> lArmas = new ArrayList<TarmArmas>();

    private Boolean seleccionTodas = false;

    TarmSolicitudTramite solicitudTramite;
    TcustPersonDetail detallesPersona;
    TcustPersonDetail usuario;
    String numeroTramite;
    String nombreRazonSocial;
    String tipoDocumento;
    private Boolean generaReporte = Boolean.FALSE;

    @ManagedProperty(value = "#{reportController}")
    private ReportController reportController;

    public VerificacionInformacionDevolucionController() throws Exception {
        super(TarmSolicitudArmas.class);
        // TODO Auto-generated constructor stub
    }

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

    public void startQuery() {
        try {
            this.pasteBpmScreenParameters();
            csolicitud = super.getMfilters().get("csolicitud");//"cm:Decomiso/cm:A-2014/cm:M-10/cm:ENV-000000319/cm:ENV-000000319.pdf";//
            if (csolicitud != null) {
                FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("CSOLICITUD", csolicitud);
                FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("TID", tid);
            }
            if (csolicitud == null) {
                csolicitud = FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("CSOLICITUD").toString();
            }
            if (tid == null) {
                tid = "" + FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("TID");
            }
            super.getMfilters().clear();
            super.getMfilters().put("pk.csolicitud", csolicitud);
        } catch (Exception e) {
            MessageHelper.setMessageError(e);
        }
    }

    /**
     * Incializa el controlador, cuando se esta utilizando una pagina que utliza
     * el controlador.
     */
    private void init() {
        try {
            recperpage = 10; // Cambiar al # reg a mirar.
            lrecord = new ArrayList<>();
            beanalias = "VERIFICACIONINFORMACIONCONTROLLER";
            querydatabase();

            //Obteniendo el centro de control
            TsafeUserDetail tsafeUserDetail = (TsafeUserDetail) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("TSAFEUSERDETAIL");
            PersonAddressController direccion = new PersonAddressController();
            TcustPersonAddress tcustPersonAddres = direccion.findPrincipal(tsafeUserDetail.getPk().getPersoncode().toString());
            this.jurisdiccionCentroControl = TarmCentroControlJurController.findxProvincia(tcustPersonAddres.getProvincecode());
            centroControl = CentroControlArmasController.findPorCodigo(this.jurisdiccionCentroControl.getCcentrocontrol());
            this.nombreCentroControl = CatalogDetailController.findxCodigoCodcatalogo(centroControl.getNombreinstitucion(),
                    centroControl.getNombreinstitucioncodigo()).getDescription();

            //Obteniendo el jefe del centro de control
            this.jefeCentroControl = PersonDetailController.find(this.centroControl.getPersoncode().toString());

            //Obteniendo el grado del jefe del centro de control
            TgeneCatalogDetail grado = CatalogDetailController.findxCodigoCodcatalogo(this.jefeCentroControl.getMilitarygrade(), this.jefeCentroControl.getMilitarygradecode());
            if (grado != null) {
                gradoFuncionario = grado.getDescription() + " - ";
            }

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

    /**
     * Crea una instancia de TgeneTransactionProcess y marca el registro como
     * nuevo.
     *
     * @throws Exception
     */
    @Override
    public void create() throws Exception {
        super.create();
    }

    @Override
    public void query() throws Exception {
        // TODO Auto-generated method stub
        MessageHelper.setMessageError("msg_notQuery");
        super.query();
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void querydatabase() {
        try {
            this.lArmas.clear();

            DtoQuery dto = super.getDtoQuery(true);

            //Quemando el codigo de la solicitud
            if (csolicitud != null) {
                Filter filtro = new Filter("pk.csolicitud", csolicitud);
                dto.addFiltro(filtro);
                FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("CSOLICITUD", csolicitud);
            } else {
                Filter filtro = new Filter("pk.csolicitud", "" + FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("CSOLICITUD"));
                dto.addFiltro(filtro);
            }

            //Obteniendo el tramite
            solicitudTramite = TarmSolicitudTramiteController.findPorCSolicitud(csolicitud);

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

            Request request = callerhelper.getRequest();
            request.setQueryTables(mtables);

            Response resp = callerhelper.executeQuery(request);

            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) != 0) {
                lrecord = new ArrayList<TarmSolicitudArmas>();
                MessageHelper.setMessageError(resp);
            } else {
                lrecord = (List<TarmSolicitudArmas>) resp.get(beanalias);
                if (lrecord != null && !lrecord.isEmpty()) {

                    record = lrecord.get(0);

                    //Numero de tramite
                    if (solicitudTramite != null) {
                        this.numeroTramite = solicitudTramite.getNumerotramite();
                        this.record.put("ntramite", solicitudTramite.getNumerotramite());
                    }

                    //Obteniendo la solicitud
                    TarmSolicitud solicitud = ValidacionTramiteLibreTransitoController.findPorSolicitudSimple(solicitudTramite.getPk().getCsolicitud());
                    if (solicitud != null) {
                        detallesPersona = PersonDetailController.find(String.valueOf(solicitud.getPersoncode()));
                    }

                    //Obteniendo los datos del usuario logueado
                    TsafeUserDetail tsafeUserDetail = (TsafeUserDetail) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("TSAFEUSERDETAIL");
                    usuario = PersonDetailController.find(tsafeUserDetail.getPk().getPersoncode().toString());

                    //Obteniendo las armas
                    for (TarmSolicitudArmas solicitudArmas : lrecord) {
                        TarmArmas arma = ArmasController.findPorCodigo(solicitudArmas.getPk().getCarma());
                        if (arma != null) {
                            lArmas.add(arma);
                        }
                    }
                    actualizarArmas();
                }
                super.postQuery(lrecord);
            }

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

    @SuppressWarnings("unchecked")
    protected void querydatabaseArmas() {
        try {
            this.lArmas.clear();

            DtoQuery dto = super.getDtoQuery(true);

            if (csolicitud != null) {
                dto.addFiltro(new Filter("pk.csolicitud", csolicitud));
            }

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

            Request request = callerhelper.getRequest();
            request.setQueryTables(mtables);

            Response resp = callerhelper.executeQuery(request);

            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) != 0) {
                lrecord = new ArrayList<TarmSolicitudArmas>();
                MessageHelper.setMessageError(resp);
            } else {
                lrecord = (List<TarmSolicitudArmas>) resp.get(beanalias);
                if (lrecord != null && !lrecord.isEmpty()) {

                    record = lrecord.get(0);

                    //Obteniendo las armas
                    for (TarmSolicitudArmas solicitudArmas : lrecord) {
                        TarmArmas arma = ArmasController.findPorCodigo(solicitudArmas.getPk().getCarma());
                        if (arma != null) {
                            lArmas.add(ArmasController.findPorCodigo(solicitudArmas.getPk().getCarma()));
                        }
                    }
                    actualizarArmas();
                }
                super.postQuery(lrecord);
            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    @Override
    public void save() {
        try {

            //Actualizando el estado de las armas
            for (TarmArmas armaSeleccionada : lArmas) {
                for (TarmSolicitudArmas solicitudArmas : lrecord) {
                    if (armaSeleccionada.getPk().equals(solicitudArmas.getPk().getCarma())) {
                        record = solicitudArmas;
                        if (armaSeleccionada.modifiedData().containsValue(Boolean.TRUE)) {
                            record.setPordevolucion("Y");
                        } else {
                            record.setPordevolucion("N");
                        }
                        update();
                    }
                }
            }

            DtoSave dtosave = super.getDtoSave();
            dtosave.setReturnpk(true); // Para que el core devuelva el pk de los registros nuevos.
            HashMap<String, DtoSave> msave = new HashMap<String, DtoSave>();

            Request request = callerhelper.getRequest();
            msave.put(beanalias, dtosave); // adicionar metadata de mantenimiento para cada tabla.

            request.setSaveTables(msave);

            Response resp = callerhelper.executeSave(request);
            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) == 0) {
                this.postCommit(resp);
                MessageHelper.setMessageInfo(resp);
                generateReport();
            } else {
                MessageHelper.setMessageError(resp);
            }

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

    /**
     * Metodo para finalizar la tarea del flujo
     */
    public void completarTarea() {
        if (!generaReporte) {
            MessageHelper.setMessageError(MsgControlArmas.getProperty("msg_error_generereporte"));
            return;
        }
        try {
            Request request = callerhelper.getRequest();
            // limpiar request para finalizar la tarea.
            super.cleanRequest(request);
            //completa la tarea del flujo
            request.modifiedData().put("csolicitud", csolicitud);
            request.modifiedData().put("TID", tid);
            request.modifiedData().put("BPMStatus", bpmDataStatus == null ? "A" : bpmDataStatus); // A,D,R
            request.modifiedData().put("BPMObs", bpmDataComment == null ? "OK" : bpmDataComment);
            request.modifiedData().put("isnew", "Y");
            Response resp = callerhelper.executeSave(request);

            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) == 0) {
                MessageHelper.setMessageInfo(resp);
                MessageHelper.setMessageInfo("COMPLETA LA TAREA DEL FLUJO");
                generaReporte = Boolean.FALSE;
                FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove("TID");
                FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove("CSOLICITUD");
                org.primefaces.context.RequestContext.getCurrentInstance().execute("Maia.refreshusertasks()");
            } else {
                MessageHelper.setMessageError(resp);
            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    /**
     * Salva los datos de la verificaion
     */
    public String saveVerification() {
        String direccion = "";
        try {

            //Actualizando el estado de las armas
            for (TarmArmas armaSeleccionada : lArmas) {
                for (TarmSolicitudArmas solicitudArmas : lrecord) {
                    if (armaSeleccionada.getPk().equals(solicitudArmas.getPk().getCarma())) {
                        record = solicitudArmas;
                        if (armaSeleccionada.modifiedData().containsValue(Boolean.TRUE)) {
                            record.setPordevolucion("Y");
                        } else {
                            record.setPordevolucion("N");
                        }
                        update();
                    }
                }
            }

            DtoSave dtosave = super.getDtoSave();
            dtosave.setReturnpk(true); // Para que el core devuelva el pk de los registros nuevos.
            HashMap<String, DtoSave> msave = new HashMap<String, DtoSave>();

            Request request = callerhelper.getRequest();
            msave.put(beanalias, dtosave); // adicionar metadata de mantenimiento para cada tabla.

            request.setSaveTables(msave);
            Response resp = callerhelper.executeSave(request);
            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) == 0) {
                this.postCommit(resp);
                MessageHelper.setMessageInfo(resp);
                direccion = "/pages/armas/registrarNovedad?faces-redirect=true?csolicitud=" + csolicitud;
            } else {
                MessageHelper.setMessageError(resp);
            }

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

    @Override
    public void postCommit(Response response) throws Exception {
        super.postCommitGeneric(response, beanalias);
    }

    /**
     * Genera el reporte de la verificacion de las armas
     *
     * @param name Nombre del reporte a generar.
     */
    public void generateReport() {
        String path = "armas/reports/actaDevolucion2";
        String filename = MsgControlArmas.getProperty("lbl_actaDeDevolucion");

        //Fija parametros del report.
        HashMap<String, Object> parameters = new HashMap<>();

        parameters.put("pathLogoIzquierda", "repo:/maia/1/image/comandoconjunto");
        parameters.put("pathLogoDerecha", "repo:/maia/1/image/selloarmas");

        parameters.put("csolicitud", solicitudTramite.getPk().getCsolicitud());
        parameters.put("numeroTramite", this.numeroTramite);

        //Nombre del centro de control
        parameters.put("nombreCentro", this.nombreCentroControl);

        //Fecha
        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
        parameters.put("lugarFecha", sdf.format(Calendar.getInstance().getTime()));

        //Nombre y cedula
        parameters.put("nombreRazon", detallesPersona.getName());
        parameters.put("cedula", detallesPersona.getIdentification());

        //Codigo persona
        parameters.put("personcode", usuario.getPk().getPersoncode());

        //Funcionario
        parameters.put("gradoNombreFuncionario", gradoFuncionario + this.jefeCentroControl.getName());
        parameters.put("personcode", this.jefeCentroControl.getPk().getPersoncode());
        parameters.put("centroControl", "JEFE DEL " + this.nombreCentroControl);

        //Usuario
        parameters.put("usuario", this.usuario.getName());
        sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String fechaHora = sdf.format(Calendar.getInstance().getTime());
        parameters.put("fechaHora", fechaHora);

        String format = "pdf";

        try {
            this.reportController.execute(path, parameters, format, filename, this.getLoginController());
            //
            generaReporte = Boolean.TRUE;
        } catch (Exception ex) {
            MessageHelper.setMessageError(ex);
        }
    }

    /**
     * Metodod que asigna la seleccion del arma segun el estado de la solicitud
     * arma
     *
     * @throws Exception
     */
    @SuppressWarnings("unused")
    private void actualizarArmas() throws Exception {
        for (TarmSolicitudArmas solicitudArmas : lrecord) {
            for (int i = 0; i < lArmas.size(); i++) {
                TarmArmas armaSeleccionada = lArmas.get(i);
                if (armaSeleccionada.getPk().equals(solicitudArmas.getPk().getCarma())) {
                    if (solicitudArmas.getPordevolucion() != null && !solicitudArmas.getPordevolucion().isEmpty()
                            && solicitudArmas.getPordevolucion().equalsIgnoreCase("Y")) {
                        armaSeleccionada.modifiedData().put("seleccion", Boolean.TRUE);
                    } else {
                        armaSeleccionada.modifiedData().put("seleccion", Boolean.FALSE);
                    }
                }
            }
        }
    }

    /**
     * Metodo que selecciona todas las armas
     */
    public void seleccionarTodasArmas() {
        for (TarmArmas arma : lArmas) {
            arma.put("seleccion", Boolean.TRUE);
        }
    }

    /**
     * Obtiene los detalles de las armas segun el catalogo
     *
     * @param catalogo
     * @param catalogoCode
     * @return
     */
    public String aspectoArmaCatalogo(String catalogo, String catalogoCode) {
        if (catalogo != null && catalogoCode != null && !catalogo.isEmpty() && !catalogoCode.isEmpty()) {
            return CatalogDetailController.findxCodigoCodcatalogo(catalogo, catalogoCode).getDescription();
        }
        return null;
    }

    /**
     * Devuelve una descripcion de catalogo segun un tipo de aspecto
     *
     * @param arma
     * @param tipoAspecto
     * @return
     */
    public String aspectoArmaExplosivoCatalogo(TarmArmas arma, String tipoAspecto) {
        String aspecto = "";

        try {
            TarmTipoArmaExplosivo explosivo = TiposArmasExplosivosController.findarma(arma.getCtipoarmaexplosivo());
            if (explosivo != null) {
                if (tipoAspecto.equalsIgnoreCase("clase") && explosivo.getClase() != null && !explosivo.getClase().isEmpty()
                        && explosivo.getClasecodigo() != null && !explosivo.getClasecodigo().isEmpty()) {
                    aspecto = CatalogDetailController.findxCodigoCodcatalogo(explosivo.getClase(), explosivo.getClasecodigo()).getDescription();

                } else if (tipoAspecto.equalsIgnoreCase("tipo") && explosivo.getTipoarmaexplosivo() != null && !explosivo.getTipoarmaexplosivo().isEmpty()
                        && explosivo.getTipoarmaexplosivocodigo() != null && !explosivo.getTipoarmaexplosivocodigo().isEmpty()) {
                    aspecto = CatalogDetailController.findxCodigoCodcatalogo(explosivo.getTipoarmaexplosivo(), explosivo.getTipoarmaexplosivocodigo()).getDescription();

                } else if (tipoAspecto.equalsIgnoreCase("calibre") && explosivo.getCalibre() != null && !explosivo.getCalibre().isEmpty()
                        && explosivo.getCalibrecodigo() != null && !explosivo.getCalibrecodigo().isEmpty()) {
                    aspecto = CatalogDetailController.findxCodigoCodcatalogo(explosivo.getCalibre(), explosivo.getCalibrecodigo()).getDescription();
                }
            }

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

        return aspecto;
    }

    public String aspectoExplosivoArma(TarmSolicitudArmas solicitudArma, String aspecto) {
        String descripcionAspecto = "";
        try {
            TarmArmas arma = ArmasController.findPorCodigo(solicitudArma.getPk().getCarma());

            if (arma != null) {
                return this.aspectoArmaExplosivoCatalogo(arma, aspecto);
            }

        } catch (Exception e) {
            MessageHelper.setMessageWarn(e.getMessage());
        }

        return descripcionAspecto;
    }

    /**
     * Incrementa el numero del arma
     *
     * @param arma
     * @return
     */
    public int incrementarRowkey(TarmArmas arma) {
        int n = 0;

        for (int i = 0; i < lArmas.size(); i++) {
            if (arma.getPk() == lArmas.get(i).getPk()) {
                n = i + 1;
                break;
            }
        }

        return n;
    }

    /**
     * M\u00e9todo para encontrar por solicitud
     *
     * @param solicitudCode
     * @return
     */
    public static List<TarmSolicitudArmas> findSolicitudArmas(String solicitudCode) {
        try {
            VerificacionInformacionDevolucionController cc = new VerificacionInformacionDevolucionController();
            cc.init();
            cc.recperpage = 300;
            cc.addFilter("pk.csolicitud", solicitudCode);
            cc.querydatabase();
            if ((cc.lrecord != null) && !cc.lrecord.isEmpty()) {
                return cc.lrecord;
            }
            return null;
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
            return null;
        }
    }

    public List<TarmArmas> getlArmas() {
        return lArmas;
    }

    public void setlArmas(List<TarmArmas> lArmas) {
        this.lArmas = lArmas;
    }

    public Boolean getSeleccionTodas() {
        int verificadas = 0;
        for (TarmArmas arma : lArmas) {
            if (Boolean.parseBoolean(arma.modifiedData.get("seleccion").toString()) == Boolean.TRUE) {
                verificadas++;
            }
        }
        if (verificadas == lArmas.size()) {
            seleccionTodas = true;
        } else {
            seleccionTodas = false;
        }

        return seleccionTodas;
    }

    public void setSeleccionTodas(Boolean seleccionTodas) {
        this.seleccionTodas = seleccionTodas;

        if (this.seleccionTodas) {
            for (TarmArmas arma : lArmas) {
                arma.put("seleccion", Boolean.TRUE);
            }
        } else {
            for (TarmArmas arma : lArmas) {
                arma.put("seleccion", Boolean.FALSE);
            }
        }

    }

    public ReportController getReportController() {
        return reportController;
    }

    public void setReportController(ReportController reportController) {
        this.reportController = reportController;
    }

    public String getCsolicitud() {
        return csolicitud;
    }

    public void setCsolicitud(String csolicitud) {
        this.csolicitud = csolicitud;
    }

    public Boolean getGeneraReporte() {
        return generaReporte;
    }

    public void setGeneraReporte(Boolean generaReporte) {
        this.generaReporte = generaReporte;
    }

}
