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

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
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.servlet.http.HttpServletResponse;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jboss.logging.Logger;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.UploadedFile;

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.armas.funcionalidad.RegistroArmController;
import com.fp.frontend.controller.armas.solicitud.AuxArmasController;
import com.fp.frontend.controller.armas.solicitud.DecomisoArmaController;
import com.fp.frontend.controller.armas.solicitud.DecomisoController;
import com.fp.frontend.controller.pcustomer.PersonDetailController;
import com.fp.frontend.controller.pgeneral.gene.ParametersController;
import com.fp.frontend.helper.MessageHelper;
import com.fp.persistence.parmas.param.TarmCentroControl;
import com.fp.persistence.parmas.soli.TarmArmas;
import com.fp.persistence.pcustomer.gene.TcustPersonDetail;
import com.fp.persistence.pgeneral.gene.TgeneParameters;
import com.fp.persistence.pgeneral.safe.TsafeUserDetail;

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

    /**
     * Variable para listar los errores al cargar el excel
     */
    private List<String> listaErrores;
    /**
     * Mensaje de error
     */
    private String mensajeError;
    /**
     * numero de armas procesadas
     */
    private Integer numArmasProcesadas;
    /**
     * numero de armas con error
     */
    private Integer numArmasError;
    /**
     * numero de armas con error
     */
    private Integer numCorrectas;
    /**
     * Centro de control Policoa Judicia 2/PN07
     */
    private TarmCentroControl centroControl;

    /**
     * Detalle del usuario
     */
    @SuppressWarnings("unused")
    private TcustPersonDetail usuario;

    /**
     * Nombre del centro de control logeado
     */
    private String centroControlNombreLogeado;

    /*Constante centro control*/
    @SuppressWarnings("unused")
    private String nombreInstitucion;
    @SuppressWarnings("unused")
    private String institucion;
    /*Cedula del propietario*/
    @SuppressWarnings("unused")
    private String cedulaPropietario;
    /*motivo incautacion*/
    @SuppressWarnings("unused")
    private String motivocatalogo;
    /*cantidad de armas*/
    @SuppressWarnings("unused")
    private Integer cantidad = 1;

    @ManagedProperty(value = "#{registroArmController}")
    private RegistroArmController registroArmasController;

    /**
     * Controlador que maneja el decomiso TarmDecomiso
     */
    @ManagedProperty(value = "#{decomisoController}")
    private DecomisoController decomisoController;

    /**
     * Controlador que maneja TarmDecomisoArma
     */
    @ManagedProperty(value = "#{decomisoArmaController}")
    private DecomisoArmaController decomisoArmaController;

    private final static Logger LOG = Logger.getLogger(AuxCargaArmasController.class.getName());

    public AuxCargaArmasController() 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<>();
            this.record = new TarmArmas();
            this.beanalias = "AUXARMAS";
//			listArmas = new ArrayList<TarmArmas>();
            cargaParametros();
            cargaUsuarioLogeado();
        } catch (Exception e) {
            MessageHelper.setMessageError(e);
        }
    }

    public void cargaParametros() {
        nombreInstitucion = codigos("CODIGO.NOM.INSTIT.IMPORTE");//"PJ01"
        institucion = codigos("CODIGO.INSTITUCION.IMPORTE");//2
        /*Cedula del propietario*/
        cedulaPropietario = codigos("CEDULA.PROPIETARIO.IMPORTE");//"999999999";
        /*motivo incautacion*/
        motivocatalogo = codigos("MOTIVO.IMPORTE");//"9";	
    }

    /**
     * M&eacute;todo para obtener los codigos
     */
    private String codigos(String parametro) {
        TgeneParameters tgeneParameters = ParametersController.find(parametro, "1");
        return tgeneParameters.getTextvalue();
    }

    public void cargaUsuarioLogeado() {
        TsafeUserDetail tsafeUserDetail = (TsafeUserDetail) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("TSAFEUSERDETAIL");
        usuario = PersonDetailController.find(tsafeUserDetail.getPk().getPersoncode().toString());
        centroControlNombreLogeado = tsafeUserDetail.getModifiedData().get("centrocontrol").toString();
    }


    /*
	 * (non-Javadoc)
	 * 
	 * @see com.fp.frontend.controller.AbstractController#querydatabase()
     */
    @SuppressWarnings("unchecked")
    @Override
    public void querydatabase() {
        try {

            DtoQuery dto = super.getDtoQuery(true);
            Filter filtrofecha = new Filter();
            filtrofecha
                    .setSql("t.fecharegistro=(select max(ta.fecharegistro) from TarmArmas ta where t.codigoarma=ta.codigoarma and t.cregistro=ta.cregistro) and t.estado !='DEST' and t.estado !='CDP'");
            dto.addFiltro(filtrofecha);
            dto.setOrderby("pk");

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

            Request request = this.callerhelper.getRequest();
            request.setQueryTables(mtables);
            request.put("queryalias", "ARMASCOMPLETE");

            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);
                if (!lrecord.isEmpty()) {
                    record = lrecord.get(0);
                }
                super.postQuery(this.lrecord);
            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    @Override
    public void save() {
        try {
            if (lrecord == null || lrecord.size() == 0 || lrecord.isEmpty()) {
                MessageHelper.setMessageError("NO EXISTEN ARMAS CARGADAS ");
                return;
            }
            HashMap<String, DtoSave> msave = new HashMap<String, DtoSave>();
            Request request = this.callerhelper.getRequest();

            DtoSave dtosave = super.getDtoSave(true);
            dtosave.setPosition(1);
            msave.put(this.beanalias, dtosave);

            request.setSaveTables(msave);
            //request.getModifiedData().put("REGISTRO", this.registroArma);

            Response resp = this.callerhelper.executeSave(request);
            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) == 0) {
                this.postCommit(resp);
                mensajeError = null;
                MessageHelper.setMessageInfo(resp);
                lrecord.clear();
            } else {
                MessageHelper.setMessageError(resp);
            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

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

    /**
     * Metodo que carga y valida el contenido de un archivo excel con
     * informaci&oacute;n de armas
     *
     * @param event
     */
    public void cargarArchivo(FileUploadEvent event) {
        // cargar Armas
        lrecord.clear();
        this.clearAll();
        listaErrores = new ArrayList<String>();
        int cont = 0;
        try {
            UploadedFile selectedFile = event.getFile();
            InputStream archivo = selectedFile.getInputstream();
            XSSFWorkbook libro = new XSSFWorkbook(archivo);
            XSSFSheet hoja = libro.getSheetAt(0);
            // Iterando sobre las filas
            Iterator<Row> rowIterator = hoja.iterator();
            // Cargando el contenido de las celdas a una lista de objetos
            Set<String> listaCodigoArmas = new HashSet<String>();
            while (rowIterator.hasNext()) {
                Row row = rowIterator.next();
                System.out.println("contador........." + cont);
                if (cont != 0) {
                    Cell codigoArma = row.getCell(0);
                    if (!this.celdaVacia(codigoArma)) {
                        listaCodigoArmas.add(codigoArma.toString().trim());
                    } else {
                        listaErrores.add("CELDA VACIA: " + codigoArma + " Num:" + cont);
                    }
                    cont++;
                    LOG.info("Contador " + cont);
                } else {
                    cont++;
                }
            }
            archivo.close();
            LOG.info("ARMAS CARGADAS: " + listaCodigoArmas.size());
            int auxi = 0;
            //procesar armas
            for (String item : listaCodigoArmas) {
                System.out.println("contador2: " + auxi++);
                TarmArmas arma = AuxArmasController.findByPK(item);
                if (arma != null) {
                    record = arma;
                    record.setPk(null);
                    record.setIsnew(true);
                    record.setEstado("DEST");
                    record.setFecharegistro(new java.sql.Date(new Date().getTime()));
                    SimpleDateFormat formato = new SimpleDateFormat("dd/MM/yyyy");
                    record.setEstadoDecomiso("DESTRUIDAS: " + formato.format(new Date()));
                    super.update();
                } else {
                    listaErrores.add("ARMA NO ENCONTRADA: " + item + " ");
                }
            }
        } catch (Exception e) {
            MessageHelper.setMessageError(e);
        } finally {
            numArmasProcesadas = cont - 1;
            if (!listaErrores.isEmpty()) {
                MessageHelper.setMessageError("ERRORES ENCONTRADOS DENTRO DEL ARCHIVO EXCEL: ");
                mensajeError = "ERROR EN LA CARGA DE ARMAS";
                numCorrectas = lrecord.size();
                lrecord.clear();
                this.clearAll();
            } else {
                numCorrectas = lrecord.size();
            }
            numArmasError = listaErrores.size();
        }
    }

    /**
     * Metodo que indica cuando una celda esta vacia
     *
     * @param celda
     * @return
     */
    private Boolean celdaVacia(Cell celda) {
        Boolean vacia = false;
        if (celda == null || celda.getCellType() == Cell.CELL_TYPE_BLANK
                || (celda.getCellType() == Cell.CELL_TYPE_STRING && celda.getStringCellValue().isEmpty())) {
            vacia = true;
        }
        return vacia;
    }

    @SuppressWarnings("finally")
    private File generarArchivoError(Long key) {
        if (listaErrores.isEmpty()) {
            return null;
        }
        PrintWriter escribir = null;
        File archivo = null;
        try {
            archivo = File.createTempFile("errorlog" + key, ".txt");
            escribir = new PrintWriter(archivo);
            for (String err : listaErrores) {
                escribir.print(err + "\r\n");
            }
            limpiar();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            escribir.flush();
            escribir.close();
            return archivo;
        }
    }

    /**
     * Llama a la construccion del metodo para recargar
     */
    public void descargarArchivo() {
        if (listaErrores != null && listaErrores.size() > 0) {
            Long key = new Date().getTime();
            File archivoTemporal = generarArchivoError(key);
            if (archivoTemporal == null) {
                return;
            }
            try {
                HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
                response.addHeader("Content-disposition", "attachment; filename=errorlog" + key + ".txt");
                OutputStream out = response.getOutputStream();
                InputStream inputStream = new FileInputStream(archivoTemporal.getAbsolutePath());
                int read = 0;
                byte[] bytes = new byte[1024];

                while ((read = inputStream.read(bytes)) != -1) {
                    out.write(bytes, 0, read);
                }

                inputStream.close();
                out.flush();
                FacesContext.getCurrentInstance().responseComplete();
            } catch (Exception e) {
            }
        } else {
            MessageHelper.setMessageError("NO TIENE ERRORES");
        }
    }

    /**
     * Limpia las los valores en las listas
     */
    public void limpiar() {
        try {
            create();
            while (lrecord.iterator().hasNext()) {
                record = lrecord.get(0);
                remove();
            }
        } catch (Exception e) {
            MessageHelper.setMessageError(e);
        }
    }

    public String getCodigoCiudad() {
        return codigoCiudad;
    }

    public void setCodigoCiudad(String codigoCiudad) {
        this.codigoCiudad = codigoCiudad;
    }

    String codigoCiudad;

    public void codigoCiudad() {
    }

    public void addPersoncodeFilter(String personcode) {
        super.addFilter("pk.personcode", personcode);
    }

    public List<String> getListaErrores() {
        return listaErrores;
    }

    public void setListaErrores(List<String> listaErrores) {
        this.listaErrores = listaErrores;
    }

    public RegistroArmController getRegistroArmasController() {
        return registroArmasController;
    }

    public void setRegistroArmasController(
            RegistroArmController registroArmasController) {
        this.registroArmasController = registroArmasController;
    }

    public String getMensajeError() {
        return mensajeError;
    }

    public void setMensajeError(String mensajeError) {
        this.mensajeError = mensajeError;
    }

    public Integer getNumArmasProcesadas() {
        return numArmasProcesadas;
    }

    public void setNumArmasProcesadas(Integer numArmasProcesadas) {
        this.numArmasProcesadas = numArmasProcesadas;
    }

    public Integer getNumArmasError() {
        return numArmasError;
    }

    public void setNumArmasError(Integer numArmasError) {
        this.numArmasError = numArmasError;
    }

    public TarmCentroControl getCentroControl() {
        return centroControl;
    }

    public void setCentroControl(TarmCentroControl centroControl) {
        this.centroControl = centroControl;
    }

    public String getCentroControlNombreLogeado() {
        return centroControlNombreLogeado;
    }

    public void setCentroControlNombreLogeado(String centroControlNombreLogeado) {
        this.centroControlNombreLogeado = centroControlNombreLogeado;
    }

    public DecomisoController getDecomisoController() {
        return decomisoController;
    }

    public void setDecomisoController(DecomisoController decomisoController) {
        this.decomisoController = decomisoController;
    }

    public DecomisoArmaController getDecomisoArmaController() {
        return decomisoArmaController;
    }

    public void setDecomisoArmaController(
            DecomisoArmaController decomisoArmaController) {
        this.decomisoArmaController = decomisoArmaController;
    }

    public Integer getNumCorrectas() {
        return numCorrectas;
    }

    public void setNumCorrectas(Integer numCorrectas) {
        this.numCorrectas = numCorrectas;
    }

}
