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

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

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 javax.faces.event.AjaxBehaviorEvent;

import org.primefaces.context.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.query.SubQuery;
import com.fp.dto.save.DtoSave;
import com.fp.frontend.controller.AbstractController;
import com.fp.frontend.controller.armas.parametros.CentroControlArmasController;
import com.fp.frontend.controller.armas.solicitud.DocumentoHabilitanteController;
import com.fp.frontend.controller.armas.solicitud.SolicitudController;
import com.fp.frontend.controller.armas.solicitud.SolicitudTramiteController;
import com.fp.frontend.controller.armas.solicitud.TarmSolicitudTramiteController;
import com.fp.frontend.controller.pgeneral.gene.CatalogDetailController;
import com.fp.frontend.helper.MessageHelper;
import com.fp.persistence.parmas.fun.TarmCarga;
import com.fp.persistence.parmas.param.TarmCentroControl;
import com.fp.persistence.parmas.soli.TarmArmas;
import com.fp.persistence.parmas.soli.TarmDocumentoHabilitante;
import com.fp.persistence.parmas.soli.TarmSolicitud;
import com.fp.persistence.parmas.soli.TarmSolicitudTramite;
import com.fp.persistence.pgeneral.gene.TgeneCatalogDetail;
import com.fp.persistence.pgeneral.safe.TsafeUserDetail;

@SuppressWarnings("serial")
@ManagedBean
@ViewScoped
public class DesaduanizacionController extends AbstractController<TarmArmas> {

    private static final long serialVersionUID = 1L;

    @ManagedProperty(value = "#{solicitudTramiteController}")
    private SolicitudTramiteController tarmSolicitudTramiteController;

    private Date fechaDesaduanizacion;
    private List<TarmSolicitudTramite> tramites;
    //private TarmTramite tramiteSeleccionado;
    private String noSolicitud;
    //private List<TarmArmas> larmas=new ArrayList<TarmArmas>();
    private Boolean salvarDeshabilitado = false;

    private TsafeUserDetail tsafeUserDetailUsuario = null;

    /**
     * Listado de colores
     */
    private List<TgeneCatalogDetail> lcolor;

    /*@ManagedProperty(value = "#{tarmSolicitudArmasController}")
    private TarmSolicitudArmasController tarmSolicitudArmasController;*/
    public DesaduanizacionController() throws Exception {
        super(TarmArmas.class);
    }

    /**
     * Metodo invocado despues de instanciar el controlador
     */
    @PostConstruct
    private void postconstruct() {
        this.init();
        // Inicializa autoconsulta
//		super.startQuery();
    }

    /**
     * Incializa variables del controlador, cuando se esta utilizando una pagina
     * que utliza el controlador.
     */
    private void init() {
        try {
            this.recperpage = 15; // Cambiar al # reg a mirar.
            this.lrecord = new ArrayList<>();
            noSolicitud = null;
//			this.record=new TarmArmas();
            this.beanalias = "DESADUANIZACION";
            lcolor = CatalogDetailController.find("COLOR");
            this.create();

            //Fecha de desaduanizacion
            this.fechaDesaduanizacion = Calendar.getInstance().getTime();

            //Cargando los tramites
            caragarTramiteSolicitud();

            this.tsafeUserDetailUsuario = (TsafeUserDetail) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("TSAFEUSERDETAIL");

            this.salvarDeshabilitado = true;

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

    public void caragarTramiteSolicitud() {
        this.tramites = TarmSolicitudTramiteController.findTramites();
    }

    /**
     * Retorna un {@link DtoQuery} con los atributos a presentarse
     *
     * @return
     * @throws Exception
     */
    private DtoQuery getDtoQuery() throws Exception {
        DtoQuery dto = super.getDtoQuery(true);
        SubQuery subqueryMarca = new SubQuery("TgeneCatalogDetail", "description", "marca", "i.pk.catalog=t.marca and i.pk.catalogcode=t.marcacodigo");
        dto.addSubQuery(subqueryMarca);
        SubQuery subqueryColor = new SubQuery("TgeneCatalogDetail", "description", "color", "i.pk.catalog=t.color and i.pk.catalogcode=t.colorcodigo");
        dto.addSubQuery(subqueryColor);
        SubQuery subqueryEstado = new SubQuery("TgeneCatalogDetail", "description", "estado", "i.pk.catalog=t.estado and i.pk.catalogcode=t.estadocodigo");
        dto.addSubQuery(subqueryEstado);
        SubQuery subqueryClase = new SubQuery("TarmTipoArmaExplosivo", "clase", "cclase", "i.pk=t.ctipoarmaexplosivo");
        dto.addSubQuery(subqueryClase);
        SubQuery subqueryClaseCodigo = new SubQuery("TarmTipoArmaExplosivo", "clasecodigo", "cclasecodigo", "i.pk=t.ctipoarmaexplosivo");
        dto.addSubQuery(subqueryClaseCodigo);
        SubQuery subqueryLongitud = new SubQuery("TarmTipoArmaExplosivo", "longitud", "clongitud", "i.pk=t.ctipoarmaexplosivo");
        dto.addSubQuery(subqueryLongitud);
        SubQuery subqueryLongitudCodigo = new SubQuery("TarmTipoArmaExplosivo", "longitudcodigo", "clongitudcodigo", "i.pk=t.ctipoarmaexplosivo");
        dto.addSubQuery(subqueryLongitudCodigo);
        SubQuery subqueryCalibre = new SubQuery("TarmTipoArmaExplosivo", "calibre", "ccalibre", "i.pk=t.ctipoarmaexplosivo");
        dto.addSubQuery(subqueryCalibre);
        SubQuery subqueryCalibreCodigo = new SubQuery("TarmTipoArmaExplosivo", "calibrecodigo", "ccalibrecodigo", "i.pk=t.ctipoarmaexplosivo");
        dto.addSubQuery(subqueryCalibreCodigo);
        SubQuery subqueryTipoArma = new SubQuery("TarmTipoArmaExplosivo", "tipoarmaexplosivo", "ctipoarmaexplosivo", "i.pk=t.ctipoarmaexplosivo");
        dto.addSubQuery(subqueryTipoArma);
        SubQuery subqueryTipoArmaCodigo = new SubQuery("TarmTipoArmaExplosivo", "tipoarmaexplosivocodigo", "ctipoarmaexplosivocodigo", "i.pk=t.ctipoarmaexplosivo");
        dto.addSubQuery(subqueryTipoArmaCodigo);
        SubQuery subqueryUnidad = new SubQuery("TarmTipoArmaExplosivo", "unidadmedidapeso", "cunidadmedidapeso", "i.pk=t.ctipoarmaexplosivo");
        dto.addSubQuery(subqueryUnidad);
        SubQuery subqueryUnidadCodigo = new SubQuery("TarmTipoArmaExplosivo", "unidadmedidapesocodigo", "cunidadmedidapesocodigo", "i.pk=t.ctipoarmaexplosivo");
        dto.addSubQuery(subqueryUnidadCodigo);
        SubQuery subqueryUnidadMedida = new SubQuery("TgeneCatalogDetail", "description", "unidadmedida", "i.pk.catalog=t.unidadmedidacantidad and i.pk.catalogcode=t.unidadmedidacantidadcodigo");
        dto.addSubQuery(subqueryUnidadMedida);
        SubQuery subquerycpersoncode = new SubQuery("TarmRegistroArmas", "personcode", "personcode", "i.pk=t.cregistro");
        dto.addSubQuery(subquerycpersoncode);
        SubQuery subqueryTipo = new SubQuery("TgeneCatalogDetail", "description", "tipo", "i.pk.catalog=    (select o.tipoarmaexplosivo       from TarmTipoArmaExplosivo o where o.pk=t.ctipoarmaexplosivo) and "
                + " i.pk.catalogcode=(select o.tipoarmaexplosivocodigo from TarmTipoArmaExplosivo o where o.pk=t.ctipoarmaexplosivo)");
        dto.addSubQuery(subqueryTipo);

        SubQuery subqueryCalibreD = new SubQuery("TgeneCatalogDetail", "description", "calibreD", "i.pk.catalog= (select o.calibre from TarmTipoArmaExplosivo o where o.pk=t.ctipoarmaexplosivo) and "
                + " i.pk.catalogcode=(select o.calibrecodigo from TarmTipoArmaExplosivo o where o.pk=t.ctipoarmaexplosivo)");
        dto.addSubQuery(subqueryCalibreD);

        SubQuery subqueryTipoArmaExplosivo = new SubQuery("TgeneCatalogDetail", "description", "tipoarmaexplosivo", "i.pk.catalog=    (select o.tipoarmaexplosivo       from TarmTipoArmaExplosivo o where o.pk=t.ctipoarmaexplosivo) and "
                + " i.pk.catalogcode=(select o.tipoarmaexplosivocodigo from TarmTipoArmaExplosivo o where o.pk=t.ctipoarmaexplosivo)");

        dto.addSubQuery(subqueryTipoArmaExplosivo);
        SubQuery subqueryClasecatalogo = new SubQuery("TgeneCatalogDetail", "description", "clase", "i.pk.catalog=    (select o.clase       from TarmTipoArmaExplosivo o where o.pk=t.ctipoarmaexplosivo) and "
                + " i.pk.catalogcode=(select o.clasecodigo from TarmTipoArmaExplosivo o where o.pk=t.ctipoarmaexplosivo)");
        dto.addSubQuery(subqueryClasecatalogo);
        return dto;
    }

    @SuppressWarnings("unchecked")
    @Override
    public void querydatabase() {
        try {
            DtoQuery dto = this.getDtoQuery();
            Filter filtro = new Filter();
            if (this.getMfilelds().get("cregistro") != null) {
                filtro.setSql(this.getMfilelds().get("cregistro").toString() + " and t.estado = 'IMPO' and t.lote is null "
                        + " and t.fecharegistro=(select max(ta.fecharegistro) from TarmArmas ta where t.codigoarma=ta.codigoarma and t.cregistro=ta.cregistro)"
                        + " and t.pk in (select tar.codigoarma from TarmArmas tar where tar.pk in( select ar.pk.carma from TarmSolicitudArmas ar where ar.pk.csolicitud= '" + this.noSolicitud + "'))"
                        + " and (t.peso>0 or t.cantidad>0)");
                dto.addFiltro(filtro);
            }
            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) {
                this.lrecord = new ArrayList<TarmArmas>();
                MessageHelper.setMessageError(resp);
            } else {
                this.lrecord = (List<TarmArmas>) resp.get(this.beanalias);
                super.postQuery(this.lrecord);
//				for(int i = 0; i<lrecord.size(); i++){
//					TarmArmas arm = lrecord.get(i);
//					arm.setLote("L"+i);
//				}
            }

//            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) != 0) {
//                lrecord = new ArrayList<TarmArmas>();
//                MessageHelper.setMessageError(resp);
//            } else {
//                lrecord = (List<TarmArmas>) resp.get(beanalias);
//                if(!lrecord.isEmpty()){
//                	record=lrecord.get(0);
//                }
//                super.postQuery(lrecord);
//                Collections.sort(lrecord,new Comparator<TarmArmas>(){
//                    public int compare(TarmArmas f1, TarmArmas f2)
//                    {
//                        return f1.getModifiedData().get("tipo").toString().compareTo(f1.getModifiedData().get("tipo").toString());
//                    }        
//                 });
//            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    public boolean validarSerieDuplicadas() {
        Set<String> lista = new HashSet<String>();
        for (TarmArmas ar : this.lrecord) {
            lista.add(ar.getLote());
        }
        if (this.lrecord.size() > lista.size()) {
            return true;
        }
        return false;

    }

    @Override
    public void save() {
        try {
            for (TarmArmas armas : this.lrecord) {
                this.record = armas;
                this.record.setEstado("REG");
                this.record.setColorcodigo("COLOR");
                Calendar calendario = Calendar.getInstance();
                calendario.setTime(this.fechaDesaduanizacion);
                this.record.setFdesaduanizacion(new java.sql.Date(calendario.getTimeInMillis()));
                if (this.record.getLote() != null) {
                    if (this.validarSerieDuplicadas()) {
                        MessageHelper.setMessageError("LOS ARTÍCULOS NO PUEDEN TENER SERIES IGUALES");
                        return;
                    }
                    update();
                } else {
                    StringBuilder err = new StringBuilder("EL CAMPO SERIE NO PUEDE ESTAR VACÍO");
                    //err.append(this.record.getPk());
                    MessageHelper.setMessageError(err.toString());
                    return;
                }

            }
            HashMap<String, DtoSave> msave = new HashMap<String, DtoSave>();
            Request request = callerhelper.getRequest();

            DtoSave dtosave = super.getDtoSave();
            dtosave.setReturnpk(true); // Para que el core devuelva el pk de los registros nuevos.
            msave.put(beanalias, dtosave); // adicionar metadata de mantenimiento para cada tabla.
            for (TarmSolicitudTramite tramite : tramites) {
                if (this.noSolicitud.equals(tramite.getPk().getCsolicitud())) {
                    tarmSolicitudTramiteController.setRecord(tramite);
                    break;
                }
            }

//            tarmSolicitudTramiteController.getRecord().setEstadotramite("FIN");
//            tarmSolicitudTramiteController.update();
//            DtoSave dtosaveTramite = tarmSolicitudTramiteController.getDtoSave();
//            msave.put(tarmSolicitudTramiteController.getBeanalias(), dtosaveTramite); // adicionar metadata de mantenimiento para cada tabla.
            request.getModifiedData().put("noSolicitud", noSolicitud);
            request.setSaveTables(msave);
            request.getModifiedData().put("REQUIEREDESGLOCE", Boolean.FALSE);
            Response resp = callerhelper.executeSave(request);
            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) == 0) {
                this.postCommit(resp);
//                tarmSolicitudTramiteController.postCommit(resp);
                MessageHelper.setMessageInfo(resp);
                this.salvarDeshabilitado = true;
                caragarTramiteSolicitud();
                this.query();
            } else {
                MessageHelper.setMessageError(resp);
            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    @SuppressWarnings("unchecked")
    public void desaduanizarArmas() {
        try {
            System.out.println("*** INICIA PROCESO DESADUANIZACION ARMAS: " + noSolicitud);
            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 = this.callerhelper.getRequest();
            msave.put(this.beanalias, dtosave); // adicionar metadata de mantenimiento para cada tabla.
            request.setSaveTables(msave);
            TarmSolicitud solicitudObj = SolicitudController.findSolicitudxcodsolicitud(noSolicitud);
            if (solicitudObj != null) {
                request.getModifiedData().put("SOLICITUD", solicitudObj);
                request.getModifiedData().put("REQUIEREDESGLOCE", Boolean.TRUE);
            } else {
                MessageHelper.setMessageError("NO EXISTE UN CODIGO DE AUCP ASOCIADO A LA SOLICITUD");
                return;
            }
            Response resp = this.callerhelper.executeSave(request);
            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) == 0) {
                this.postCommit(resp);
                MessageHelper.setMessageInfo(resp);
                querydatabase();
            } else {
                MessageHelper.setMessageError(resp);
            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }

//    	try {
//    		System.out.println("*** INICIA PROCESO DESADUANIZACION ARMAS: " +  noSolicitud);
//    		Request request = this.callerhelper.getRequest();
////			request.modifiedData().put("querytype", "P");
////			request.modifiedData().put("queryalias", "DESGLOCEDESADUANIZACION");
//			TarmSolicitud solicitudObj = SolicitudController.findSolicitudxcodsolicitud(noSolicitud);
//			if(solicitudObj!=null){
//				request.getModifiedData().put("SOLICITUD", solicitudObj);
//			}
//			else{
//				MessageHelper.setMessageError("NO EXISTE UN CODIGO DE AUCP ASOCIADO A LA SOLICITUD");
//				return;
//			}			
//			Response resp = this.callerhelper.executeQuery(request);
//			if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) != 0) {
//				this.lrecord = new ArrayList<TarmArmas>();
//				MessageHelper.setMessageError(resp);
//			} else {
//				this.lrecord = (List<TarmArmas>) resp.get(this.beanalias);
//			}    		
//    	} catch (Throwable e) {
//            MessageHelper.setMessageError(e);
//        }    	
    }

    /**
     * Obtiene un arma por su codigo
     *
     * @param codigopersona
     * @return
     */
    public static TarmArmas findByCode(String carma) {
        try {
            DesaduanizacionController cc = new DesaduanizacionController();
            cc.init();
            cc.recperpage = 300000;
            cc.addFilter("pk", carma);
            cc.querydatabase();
            if ((cc.lrecord != null) && !cc.lrecord.isEmpty()) {
                return cc.lrecord.get(0);
            }
            return null;
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
            return null;
        }
    }

    public Date getFechaDesaduanizacion() {
        return fechaDesaduanizacion;
    }

    public void setFechaDesaduanizacion(Date fechaDesaduanizacion) {
        this.fechaDesaduanizacion = fechaDesaduanizacion;
    }

    public void setDatos(final AjaxBehaviorEvent event) {
        try {
            TarmSolicitudTramite soltra = TarmSolicitudTramiteController.findPorCSolicitud(this.noSolicitud);
            // Verificacion del desgloce de desaduanizacion 			
            TarmSolicitud solicitudObj = SolicitudController.findSolicitudxcodsolicitud(soltra.getPk().getCsolicitud());
            TarmCarga carga = CargaController.findByAUCP(solicitudObj.getAucp());

            this.record = new TarmArmas();
            this.record.modifiedData().put("tipotramitedesc", soltra.modifiedData().get("tipotramitedesc"));
            this.record.modifiedData().put("categoriadesc", soltra.modifiedData().get("categoriadesc"));
            this.record.modifiedData().put("usodesc", soltra.modifiedData().get("usodesc"));
            this.record.modifiedData().put("cedula", soltra.modifiedData().get("cedula"));
            this.record.modifiedData().put("nombre", soltra.modifiedData().get("nombre"));
            this.record.modifiedData().put("personcode", soltra.modifiedData().get("personcode"));
            this.record.modifiedData().put("aucp", (solicitudObj.getAucp() != null && !solicitudObj.getAucp().isEmpty()) ? solicitudObj.getAucp() : "");
            TarmCentroControl centroControlObj = CentroControlArmasController.findPorCodigo(solicitudObj.getCcentrocontrol());
            if (centroControlObj != null) {
                String ccentrocontrol = CatalogDetailController.findxCodigoCodcatalogo(centroControlObj.getNombreinstitucion(),
                        centroControlObj.getNombreinstitucioncodigo()).getDescription();
                this.record.modifiedData().put("nombreCentroControl", (ccentrocontrol != null && !ccentrocontrol.isEmpty()) ? ccentrocontrol : "");
            }

            TarmDocumentoHabilitante dochab = DocumentoHabilitanteController.findPorSolicitud(this.noSolicitud);
            if (dochab != null) {
                this.record.modifiedData().put("fechaemision", dochab.getFechaemision());
            }

            //cregistro propietario
//			List<TarmRegistroArmas> regArmas = RegistroArmController.findxPersoncode(soltra.modifiedData().get("personcode").toString());
//			StringBuilder sql = new StringBuilder("cregistro in");
//			Integer aux=0;
//			for(TarmRegistroArmas t :regArmas){
//				if(aux==0){
//					sql.append("("+t.getPk());
//					aux++;
//				}else{
//					sql.append(","+t.getPk());
//				}
//			}
//			sql.append(")");
            //armas codigoarma que debe filtar
            String sql = "cregistro in (Select r.pk from TarmRegistroArmas r where personcode=" + soltra.modifiedData().get("personcode").toString() + ")";
            addField("cregistro", sql);
            this.salvarDeshabilitado = true;
            if (carga.getEsdesaduanizado().equals("N")) {
                RequestContext.getCurrentInstance().execute("PF('dialog').show()");
            } else {
                querydatabase();

            }
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

    /**
     * Metodo que indica las acciones asociadas de cerrar el dialogo sin
     * desanuanizar
     */
    public void cerrar() {
        init();
    }

    public void habilitaGrabar(final AjaxBehaviorEvent event) {
        Integer aux = 0;
        for (TarmArmas armas : this.lrecord) {
            if (!this.lrecord.isEmpty() && armas.getLote() != null) {
                aux++;
            }
        }
        if (aux.compareTo(this.lrecord.size()) == 0) {
            this.salvarDeshabilitado = false;
        }
    }

    public static long getSerialversionuid() {
        return serialVersionUID;
    }

    public List<TarmSolicitudTramite> getTramites() {
        return tramites;
    }

    public void setTramites(List<TarmSolicitudTramite> tramites) {
        this.tramites = tramites;
    }

    public String getNoSolicitud() {
        return noSolicitud;
    }

    public void setNoSolicitud(String noSolicitud) {
        this.noSolicitud = noSolicitud;
    }

    public Boolean getSalvarDeshabilitado() {
        return salvarDeshabilitado;
    }

    public void setSalvarDeshabilitado(Boolean salvarDeshabilitado) {
        this.salvarDeshabilitado = salvarDeshabilitado;
    }

    public SolicitudTramiteController getTarmSolicitudTramiteController() {
        return tarmSolicitudTramiteController;
    }

    public void setTarmSolicitudTramiteController(
            SolicitudTramiteController tarmSolicitudTramiteController) {
        this.tarmSolicitudTramiteController = tarmSolicitudTramiteController;
    }

    public List<TgeneCatalogDetail> getLcolor() {
        return lcolor;
    }

    public void setLcolor(List<TgeneCatalogDetail> lcolor) {
        this.lcolor = lcolor;
    }

}
