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

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.ViewScoped;

import org.primefaces.event.SelectEvent;

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.dto.save.DtoSave;
import com.fp.frontend.controller.AbstractController;
import com.fp.frontend.controller.armas.eval.RespuestasController;
import com.fp.frontend.controller.pgeneral.gene.CatalogDetailController;
import com.fp.frontend.helper.MessageHelper;
import com.fp.persistence.parmas.eval.TarmPreguntas;
import com.fp.persistence.parmas.eval.TarmRespuestas;
import com.fp.persistence.pgeneral.gene.TgeneCatalogDetail;

/**
 * Clase controladora del bean TarmPreguntas.
 *
 * @author Christian Pazmino
 * @version 2.1
 */
@SuppressWarnings("serial")
@ManagedBean
@ViewScoped
public class PreguntasParaEvaluacionesController extends
        AbstractController<TarmPreguntas> {

    /**
     * Lista de catalogos de tipos de evaluaciones
     */
    List<TgeneCatalogDetail> lTipoEvaluacion;
    /**
     * Lista de catalogos de tipos de personas
     */
    List<TgeneCatalogDetail> lTipoPersona;
    /**
     * Lista de catalogos de tipos de estados de preguntas
     */
    List<TgeneCatalogDetail> lEstados;
    /**
     * Variable tipo map utilizada para generar el numero de pregunta segun el
     * tipo de persona y tipo de evaluacion escogidos
     */
    private Map<String, Integer> numeroPreguntaMAP = new HashMap<String, Integer>();
    /**
     * Constante usada para referirse al codigo de tipo de evaluacion
     */
    private final String TIPOEVALUACIONCODIGO = "TIPOEVALUACION";
    /**
     * Constante usada para referirse al codigo de tipo de persona
     */
    private final String TIPOPERSONACODIGO = "PERSONTYPE";
    /**
     * Constante usada para referirse a codigo de estado de preguntas
     */
    private final String ESTADOPREGUNTACODIGO = "ESTADOPRUEBAS";
    /**
     * Variable de tipo boleano para indicar si el dialog esta en modo edicion o
     * creacion
     */
    private Boolean esEdicionBln;
    /**
     * Variable de tipo boleano para indicar si existe alguna respuesta a la
     * pregunta
     */
    private Boolean existeRespuestasBln;

    public PreguntasParaEvaluacionesController() throws Exception {
        super(TarmPreguntas.class);
    }

    @PostConstruct
    private void postconstruct() {
        this.init();
        lTipoEvaluacion = CatalogDetailController.find("TIPOEVALUACION");
        lTipoPersona = CatalogDetailController.find(TIPOPERSONACODIGO);
        lEstados = CatalogDetailController.find("ESTADOPRUEBAS");
        if (lEstados != null && lEstados.size() == 2) {
            TgeneCatalogDetail activado = lEstados.get(0);
            lEstados.set(0, lEstados.get(1));
            lEstados.set(1, activado);

        }
        for (TgeneCatalogDetail tEvaluacion : lTipoEvaluacion) {
            for (TgeneCatalogDetail tPersona : lTipoPersona) {
                numeroPreguntaMAP.put(tEvaluacion.getPk().getCatalog()
                        + tPersona.getPk().getCatalog(), 0);
            }
        }
        // Inicializa autoconsulta
        super.startQuery();
    }

    /**
     * M&eacute;todo de busqueda que consulta una lista de preguntas mediante
     * codigo de evaluacion y codigo de persona
     *
     * @param String codigoEvaluacion
     * @param String codigoPersona
     * @return List<TarmPreguntas> lista de pregunta
     */
    public List<TarmPreguntas> findByCodEvaluacionPersona(String codigoEvaluacion, String codigoPersona) {
        try {
            PreguntasParaEvaluacionesController cc = new PreguntasParaEvaluacionesController();
            cc.init();
            cc.recperpage = 300;
            cc.addFilter("tipoevaluacion", codigoEvaluacion);
            cc.addFilter("tipopersona", codigoPersona);
            cc.querydatabase();
            if ((cc.lrecord != null) && !cc.lrecord.isEmpty()) {
                return cc.lrecord;
            }
            return null;
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
            return null;
        }
    }

    /**
     * M&eacute;todo que obtiene el numero de pregunta
     *
     * @param String codigo Evaluacion
     * @param String codigo Persona
     * @return numero de pregunta
     */
    private void generaNumeroPregunta(String codigoEvaluacion, String codigoPersona) {
        if (codigoEvaluacion != null && codigoPersona != null) {
            List<TarmPreguntas> lista = findByCodEvaluacionPersona(codigoEvaluacion, codigoPersona);
            if (lista != null) {
                Integer ultimoValor = 0;
                for (TarmPreguntas pregunta : lista) {
                    if ((codigoEvaluacion.compareTo(pregunta.getTipoevaluacion()) == 0) && (codigoPersona.compareTo(pregunta.getTipopersona()) == 0)) {
                        if (ultimoValor < pregunta.getNumeropregunta()) {
                            ultimoValor = pregunta.getNumeropregunta();
                        }
                    }
                }
                record.setNumeropregunta(ultimoValor + 1);
            } else {
                record.setNumeropregunta(1);
            }
        } else {
            record.setNumeropregunta(null);
        }
    }

    /**
     * M&eacute;todo que gestiona el cambio de tipo de evaluacion por parte del
     * usuario en el dialogo de crear
     *
     * @return numero de pregunta
     */
    public void setNombreTipoEvaluacion() {
        for (TgeneCatalogDetail r : lTipoEvaluacion) {
            if (r.getPk().getCatalog().compareTo(record.getTipoevaluacion()) == 0) {
                record.put("nTipoEvaluacion", r.getDescription());
            }
        }
        record.setTipoevaluacioncodigo(TIPOEVALUACIONCODIGO);
        generaNumeroPregunta(record.getTipoevaluacion(), record.getTipopersona());
    }

    /**
     * M&eacute;todo que gestiona el cambio de tipo de persona por parte del
     * usuario en el dialogo de crear
     */
    public void setNombreTipoPersona() {
        for (TgeneCatalogDetail r : lTipoPersona) {
            if (r.getPk().getCatalog().compareTo(record.getTipopersona()) == 0) {
                record.put("nTipoPersona", r.getDescription());
            }
        }
        record.setTipopersonacodigo(TIPOPERSONACODIGO);
        generaNumeroPregunta(record.getTipoevaluacion(), record.getTipopersona());
    }

    /**
     * M&eacute;todo que devuelve el estado de la pregunta
     */
    public void setEstadoPregunta() {
        for (TgeneCatalogDetail r : lEstados) {
            if (r.getPk().getCatalog().compareTo(record.getEstadopregunta()) == 0) {
                record.put("nEstado", r.getDescription());
            }
        }
        record.setEstadopreguntacodigo(ESTADOPREGUNTACODIGO);
    }

    /**
     * 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 = "PREGUNTASPARAEVALUACIONES";
            esEdicionBln = Boolean.FALSE;
            existeRespuestasBln = Boolean.FALSE;
        } catch (Exception e) {
            MessageHelper.setMessageError(e);
        }
    }

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

        for (TgeneCatalogDetail estadoObj : lEstados) {
            if (estadoObj.getPk().getCatalog().equalsIgnoreCase("INA")) {
                record.setEstadopregunta("INA");
                record.setEstadopreguntacodigo(ESTADOPREGUNTACODIGO);
                record.getModifiedData().put("nEstado", estadoObj.getDescription());
            }
        }
        esEdicionBln = Boolean.FALSE;
        existeRespuestasBln = Boolean.FALSE;
    }

    /**
     * Metodo ejecutado al editar un item de la tabla
     */
    public void edicion() {
        esEdicionBln = Boolean.TRUE;
        existeRespuestasBln = consultarExisteResuestas();
    }

    /**
     * Metodo que verifica si existe o no al menos una respuesta para la
     * pregunta
     */
    public Boolean consultarExisteResuestas() {
        List<TarmRespuestas> respuestaList = RespuestasController.findxPregunta(record.getPk().toString());
        if (respuestaList != null && respuestaList.size() > 0) {
            return Boolean.TRUE;
        } else {
            return Boolean.FALSE;
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void querydatabase() {
        try {

            DtoQuery dto = super.getDtoQuery(true);
            dto.setOrderby("t.numeropregunta");
            // Subquery
            SubQuery subqueryTipoEval = new SubQuery("TgeneCatalogDetail",
                    "description", "nTipoEvaluacion",
                    "i.pk.catalog = t.tipoevaluacion and i.pk.catalogcode = t.tipoevaluacioncodigo");
            dto.addSubQuery(subqueryTipoEval);

            // Subquery
            SubQuery subqueryTipoPers = new SubQuery("TgeneCatalogDetail",
                    "description", "nTipoPersona",
                    "i.pk.catalog = t.tipopersona and i.pk.catalogcode = t.tipopersonacodigo");
            dto.addSubQuery(subqueryTipoPers);

            // Subquery de Estado Pregunta
            SubQuery subqueryEstado = new SubQuery("TgeneCatalogDetail",
                    "description", "nEstado",
                    "i.pk.catalog = t.estadopregunta and i.pk.catalogcode = t.estadopreguntacodigo");
            dto.addSubQuery(subqueryEstado);

            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<TarmPreguntas>();
                MessageHelper.setMessageError(resp);
            } else {
                lrecord = (List<TarmPreguntas>) resp.get(beanalias);
                if (lEstados == null) {
                    lEstados = CatalogDetailController.find("ESTADOPRUEBAS");
                }
                for (TarmPreguntas pregunta : lrecord) {
                    for (TgeneCatalogDetail estado : lEstados) {
                        if (pregunta.getEstadopregunta() != null && pregunta.getEstadopregunta().equalsIgnoreCase(estado.getPk().getCatalog())) {
                            pregunta.modifiedData.put("nEstado", estado.getDescription());
                        }
                    }
                }

                super.postQuery(lrecord);
            }

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

    @Override
    public void save() {
        try {
            DtoSave dtosave = super.getDtoSave();
            if (!dtosave.pendingProcess()) {
                return;
            }
            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);
            } else {
                MessageHelper.setMessageError(resp);
            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

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

    /**
     * Consulta preguntas por codigo de pregunta
     *
     * @param cpreguntas
     * @return
     * @throws Exception
     */
    public static List<TarmPreguntas> find(String cpreguntas) throws Exception {
        PreguntasParaEvaluacionesController r = new PreguntasParaEvaluacionesController();
        r.addFilter("pk", cpreguntas);
        r.querydatabase();
        return r.getLrecord();
    }

    /**
     * Consulta todas las preguntas filtradas por tipo de persona y por tipo de
     * evaluacion
     */
    public static List<TarmPreguntas> findxPregunta(String tipopersona, String tipoevaluacion) {
        try {
            PreguntasParaEvaluacionesController cc = new PreguntasParaEvaluacionesController();
            cc.init();
            cc.recperpage = 300;
            cc.addFilter("tipopersona", tipopersona);
            cc.addFilter("tipoevaluacion", tipoevaluacion);
            cc.addFilter("estadopregunta", "ACT");
            cc.querydatabase();
            if ((cc.lrecord != null) && !cc.lrecord.isEmpty()) {
                return cc.lrecord;
            }
            return null;
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
            return null;
        }
    }

    /**
     * Busca en la lista de estados la descripcion del codigo de estado recibido
     * como parametro
     */
    public String descripcionEstadoPregunta(String estadoCodigo) {
        String estado = "";

        for (TgeneCatalogDetail e : lEstados) {
            if (estadoCodigo.equalsIgnoreCase(e.getPk().getCatalog())) {
                return e.getDescription();
            }
        }

        return estado;
    }

    public List<TgeneCatalogDetail> getlTipoEvaluacion() {
        return lTipoEvaluacion;
    }

    public void setlTipoEvaluacion(List<TgeneCatalogDetail> lTipoEvaluacion) {
        this.lTipoEvaluacion = lTipoEvaluacion;
    }

    public List<TgeneCatalogDetail> getlTipoPersona() {
        return lTipoPersona;
    }

    public void setlTipoPersona(List<TgeneCatalogDetail> lTipoPersona) {
        this.lTipoPersona = lTipoPersona;
    }

    public Map<String, Integer> getNumeroPreguntaMAP() {
        return numeroPreguntaMAP;
    }

    public void setNumeroPreguntaMAP(Map<String, Integer> numeroPreguntaMAP) {
        this.numeroPreguntaMAP = numeroPreguntaMAP;
    }

    public Boolean getEsEdicionBln() {
        return esEdicionBln;
    }

    public void setEsEdicionBln(Boolean esEdicionBln) {
        this.esEdicionBln = esEdicionBln;
    }

    public Boolean getExisteRespuestasBln() {
        return existeRespuestasBln;
    }

    public void setExisteRespuestasBln(Boolean existeRespuestasBln) {
        this.existeRespuestasBln = existeRespuestasBln;
    }

    /**
     * Abre el dialogo de respuestas desde la pantalla principal para la
     * pregunta seleccionada
     */
    public void openRespuestasLov(TarmPreguntas preguntaSel) {
        Map<String, List<String>> params = new HashMap<>();
        List<String> preguntaPKLst = new ArrayList<>();
        preguntaPKLst.add(preguntaSel.getPk().toString());
        params.put("preguntaPK", preguntaPKLst);
        RespuestasLovController.openLov(params);
    }

    /**
     * Metodo usado para completar acciones al cerrar el dialogo de respuestas
     */
    public void onReturnRespuestasLov(SelectEvent event) throws Exception {
        System.out.println("*** Retorna del LOV de respuestas...");
//		querydatabase();
    }

    public List<TgeneCatalogDetail> getlEstados() {
        return lEstados;
    }

    public void setlEstados(List<TgeneCatalogDetail> lEstados) {
        this.lEstados = lEstados;
    }

    /**
     * Metodo usado por controladores externos para cargar en el bean pasado
     * como parametro en la variable record
     */
    public void update(TarmPreguntas bean) throws Exception {
        record = bean;
        update();
    }

}
