package com.ejie.y41e.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.ejie.y41e.common.Y41eConstants;
import com.ejie.y41e.dao.rwmap.Y41eRelBloquePreguntaRowMapper;
import com.ejie.y41e.model.Y41eBloque;
import com.ejie.y41e.model.Y41eEncuesta;
import com.ejie.y41e.model.Y41ePregunta;
import com.ejie.y41e.model.Y41eRelBloquePregunta;
import com.ejie.y41e.utils.Y41eSqlUtils;

/**
 * Y41eRelBloquePreguntaDaoImpl
 *  
 */

@Repository
@Transactional
public class Y41eRelBloquePreguntaDaoImpl extends Y41eGenericoDaoImpl<Y41eRelBloquePregunta> implements Y41eRelBloquePreguntaDao {

    public static final String TABLA="Y41E05S01";
    public static final String TABLA_14="Y41E14S01";    
    public static final String ID_BLOQUE_005="ID_BLOQUE_005";
    public static final String ID_PREGUNTA_005="ID_PREGUNTA_005";
    public static final String ORDEN_PREG_005="ORDEN_PREG_005";
    public static final String TIPO_014="TIPO_014";

    protected static final String[] ORDER_BY_WHITE_LIST = new String[] { ID_BLOQUE_005, ID_PREGUNTA_005, ORDEN_PREG_005};

    /**
     * Y41eRelBloquePreguntaDaoImpl
     */
    public Y41eRelBloquePreguntaDaoImpl() {
        super(Y41eRelBloquePregunta.class);
    }

    /**
     * rwMapPK
     */
    private final RowMapper<Y41eRelBloquePregunta> rwMapPK = new RowMapper<Y41eRelBloquePregunta>() {
        @Override
        public Y41eRelBloquePregunta mapRow(ResultSet resultSet, int rowNum) throws SQLException {
            Y41eRelBloquePregunta relBloquePregunta = new Y41eRelBloquePregunta();
            relBloquePregunta.getBloque().setIdBloque(resultSet.getLong(ID_BLOQUE_005));
            relBloquePregunta.getPregunta().setIdPregunta(resultSet.getLong(ID_PREGUNTA_005));
            return relBloquePregunta; 
        }
    };

    /**
     * rwMapPregunta
     */
    private final RowMapper<Y41ePregunta> rwMapPregunta = new RowMapper<Y41ePregunta>() {
        @Override
        public Y41ePregunta mapRow(ResultSet resultSet, int rowNum) throws SQLException {
            Y41ePregunta pregunta = new Y41ePregunta();
            pregunta.setIdPregunta(resultSet.getLong(ID_PREGUNTA_005));
            pregunta.setDescPublEs(resultSet.getString("DESC_PUBL_ES_004"));
            pregunta.setDescPublEu(resultSet.getString("DESC_PUBL_EU_004"));
            pregunta.setObligatorio(resultSet.getString("OBLIGATORIO_004"));
            pregunta.getTipoPregunta().setIdTipoPregunta(resultSet.getLong("ID_TIPO_PREGUNTA_004"));
            pregunta.setAviso(resultSet.getString("AVISO_004"));
            pregunta.setIsEnlazada(resultSet.getString("IS_ENLAZADA"));
            pregunta.setIdPreguntaPadre(resultSet.getLong("ID_PREGUNTA_014"));
            return pregunta; 
        } 
    };


    /*
     * OPERACIONES CRUD
     */

    /**
     * Inserts a single row in the Y41eRelBloquePregunta table.
     *
     * @param relBloquePregunta Y41eRelBloquePregunta
     * @return Y41eRelBloquePregunta
     */
    @Override
    public Y41eRelBloquePregunta add(Y41eRelBloquePregunta relBloquePregunta) {
        StringBuilder insert = new StringBuilder(Y41eSqlUtils.INSERT)
                .append(TABLA).append(" (")
                .append(ID_BLOQUE_005).append(",")
                .append(ID_PREGUNTA_005).append(",")
                .append(ORDEN_PREG_005).append(")")
                .append("VALUES (?,?,?)");
        this.getJdbcTemplate().update(insert.toString(), relBloquePregunta.getBloque().getIdBloque(), relBloquePregunta.getPregunta().getIdPregunta(), 
                relBloquePregunta.getOrdenPreg());
        return relBloquePregunta;
    }

    /**
     * Updates a single row in the Y41eRelBloquePregunta table.
     *
     * @param relBloquePregunta Y41eRelBloquePregunta
     * @return Y41eRelBloquePregunta
     */
    @Override
    public Y41eRelBloquePregunta update(Y41eRelBloquePregunta relBloquePregunta) {
        StringBuilder update = new StringBuilder(Y41eSqlUtils.UPDATE)
                .append(TABLA).append(" SET ")
                .append(ORDEN_PREG_005).append("=? ")
                .append(Y41eSqlUtils.WHERE)
                .append(ID_BLOQUE_005).append("=?")
                .append(Y41eSqlUtils.AND)
                .append(ID_PREGUNTA_005).append("=?");
        this.getJdbcTemplate().update(update.toString(), relBloquePregunta.getOrdenPreg(), relBloquePregunta.getBloque().getIdBloque(), relBloquePregunta.getPregunta().getIdPregunta());
        return relBloquePregunta;
    }

    /**
     * Removes a single row in the Y41eRelBloquePregunta table.
     *
     * @param relBloquePregunta Y41eRelBloquePregunta
     * @return
     */
    @Override
    public void remove(Y41eRelBloquePregunta relBloquePregunta) {
        StringBuilder delete = new StringBuilder("DELETE ").append(Y41eSqlUtils.FROM).append(TABLA).append(Y41eSqlUtils.WHERE)
                .append(ID_BLOQUE_005).append("=?")
                .append(Y41eSqlUtils.AND)
                .append(ID_PREGUNTA_005).append("=?");
        this.getJdbcTemplate().update(delete.toString(), relBloquePregunta.getBloque().getIdBloque(), relBloquePregunta.getPregunta().getIdPregunta());
    }

    /* (non-Javadoc)
     * @see com.ejie.y41e.dao.Y41eGenericoDaoImpl#getSelect()
     */
    @Override
    protected String getSelect(Y41eRelBloquePregunta bean) {
        StringBuilder select = new StringBuilder(Y41eSqlUtils.SELECT)
                .append(ID_BLOQUE_005).append(",")
                .append(ID_PREGUNTA_005).append(",")
                .append(ORDEN_PREG_005).append(",")
                .append(" DESC_PUBL_ES_004, DESC_PUBL_EU_004, DESC_INT_ES_004, DESC_INT_EU_004, AVISO_004,")
                .append(" ID_TIPO_PREGUNTA_004, OBLIGATORIO_004, DESC_ES_008, DESC_EU_008");
        if(bean.getBloque().getIdEncuesta()!=null && bean.getBloque().getIdEncuesta()>0){
            select.append(", NVL2(HAS_ENLAZADA, 'S', 'N') HAS_ENLAZADA, NVL2(IS_ENLAZADA, 'S', 'N') IS_ENLAZADA, NVL2(IS_BLOQUE_ENLAZADA, 'S', 'N') IS_BLOQUE_ENLAZADA");
        }else{
            select.append(", NULL HAS_ENLAZADA, NULL IS_ENLAZADA, NULL IS_BLOQUE_ENLAZADA");
        }

        return select.toString();
    }

    /* (non-Javadoc)
     * @see com.ejie.y41e.dao.Y41eGenericoDaoImpl#getFrom()
     */
    @Override
    protected String getFrom(Y41eRelBloquePregunta bean, List<Object> params) {
        StringBuilder from = new StringBuilder(Y41eSqlUtils.FROM).append(TABLA);
        from.append(" JOIN Y41E04S01 ON ID_PREGUNTA_005=ID_PREGUNTA_004")
        .append(" JOIN Y41E08S01 ON ID_TIPO_PREGUNTA_008=ID_TIPO_PREGUNTA_004");
        if(bean.getBloque().getIdEncuesta()!=null && bean.getBloque().getIdEncuesta()>0){
            from.append(Y41eSqlUtils.LEFT_JOIN).append("(")
            .append(Y41eSqlUtils.SELECT_COUNT).append(" IS_ENLAZADA, ID_ENLAZADA_014, ID_BLOQUE_014, ID_ENCUESTA_014")
            .append(Y41eSqlUtils.FROM).append(TABLA_14)
            .append(Y41eSqlUtils.WHERE).append(TIPO_014).append("='").append(Y41eConstants.TIPO_PREGUNTA).append("'")
            .append(Y41eSqlUtils.GROUP_BY).append("ID_ENLAZADA_014, ID_BLOQUE_014, ID_ENCUESTA_014) T1 ON T1.ID_ENLAZADA_014=ID_PREGUNTA_004")
            .append(Y41eSqlUtils.AND).append("T1.ID_BLOQUE_014=").append(ID_BLOQUE_005)
            .append(Y41eSqlUtils.AND).append("T1.ID_ENCUESTA_014=").append(bean.getBloque().getIdEncuesta())
            .append(Y41eSqlUtils.LEFT_JOIN).append("(")
            .append(Y41eSqlUtils.SELECT_COUNT).append(" HAS_ENLAZADA, ID_PREGUNTA_014, ID_BLOQUE_014, ID_ENCUESTA_014")
            .append(Y41eSqlUtils.FROM).append(TABLA_14)
            .append(Y41eSqlUtils.GROUP_BY).append("ID_PREGUNTA_014, ID_BLOQUE_014, ID_ENCUESTA_014) T2 ON T2.ID_PREGUNTA_014=ID_PREGUNTA_004")
            .append(Y41eSqlUtils.AND).append("T2.ID_BLOQUE_014=").append(ID_BLOQUE_005)
            .append(Y41eSqlUtils.AND).append("T2.ID_ENCUESTA_014=").append(bean.getBloque().getIdEncuesta())
            .append(Y41eSqlUtils.LEFT_JOIN).append("(")
            .append(Y41eSqlUtils.SELECT_COUNT).append(" IS_BLOQUE_ENLAZADA, ID_ENLAZADA_014, ID_BLOQUE_014, ID_ENCUESTA_014")
            .append(Y41eSqlUtils.FROM).append(TABLA_14)
            .append(Y41eSqlUtils.WHERE).append(TIPO_014).append("='").append(Y41eConstants.TIPO_BLOQUE).append("'")
            .append(Y41eSqlUtils.GROUP_BY).append("ID_ENLAZADA_014, ID_BLOQUE_014, ID_ENCUESTA_014) T3 ON T3.ID_ENLAZADA_014=ID_BLOQUE_005")
            .append(Y41eSqlUtils.AND).append("T3.ID_ENCUESTA_014=").append(bean.getBloque().getIdEncuesta());
        }



        return from.toString();
    }

    /* (non-Javadoc)
     * @see com.ejie.y41e.dao.Y41eGenericoDaoImpl#getRwMap()
     */
    @Override
    protected RowMapper<Y41eRelBloquePregunta> getRwMap() {
        return new Y41eRelBloquePreguntaRowMapper();
    }

    /* (non-Javadoc)
     * @see com.ejie.y41e.dao.Y41eGenericoDaoImpl#getPK()
     */
    @Override
    protected String getPK() {
        StringBuilder selectPk = new StringBuilder(ID_BLOQUE_005).append(",").append(ID_PREGUNTA_005);
        return selectPk.toString();
    }

    /* (non-Javadoc)
     * @see com.ejie.y41e.dao.Y41eGenericoDaoImpl#getRwMapPK()
     */
    @Override
    protected RowMapper<Y41eRelBloquePregunta> getRwMapPK() {
        return this.rwMapPK;
    }

    /* (non-Javadoc)
     * @see com.ejie.y41e.dao.Y41eGenericoDaoImpl#getWherePK(java.lang.Object, java.util.List)
     */
    @Override
    protected String getWherePK(Y41eRelBloquePregunta bean, List<Object> params) {
        StringBuilder wherePK = new StringBuilder();
        wherePK.append(Y41eSqlUtils.WHERE)
        .append(ID_BLOQUE_005).append("=?")
        .append(Y41eSqlUtils.AND)
        .append(ID_PREGUNTA_005).append("=?");
        params.add(bean.getBloque().getIdBloque());
        params.add(bean.getPregunta().getIdPregunta());
        return wherePK.toString();

    }

    /* (non-Javadoc)
     * @see com.ejie.y41e.dao.Y41eGenericoDaoImpl#getWhere(java.lang.Object, java.util.List)
     */
    @Override
    protected String getWhere(Y41eRelBloquePregunta bean, List<Object> params) {
        StringBuilder where = new StringBuilder(Y41eRelBloquePreguntaDaoImpl.STRING_BUILDER_INIT);

        if (bean  != null){
            where.append(Y41eSqlUtils.generarWhereIgual(ID_BLOQUE_005, bean.getBloque().getIdBloque(), params));
            where.append(Y41eSqlUtils.generarWhereIgual(ID_PREGUNTA_005, bean.getPregunta().getIdPregunta(), params));
            where.append(Y41eSqlUtils.generarWhereIgual(ORDEN_PREG_005, bean.getOrdenPreg(), params));
        }

        return where.toString();
    }

    /* (non-Javadoc)
     * @see com.ejie.y41e.dao.Y41eGenericoDaoImpl#getWhereLike(java.lang.Object, java.lang.Boolean, java.util.List, java.lang.Boolean)
     */
    @Override
    protected String getWhereLike(Y41eRelBloquePregunta bean, Boolean startsWith, List<Object> params, Boolean search) {
        StringBuilder where = new StringBuilder(Y41eRelBloquePreguntaDaoImpl.STRING_BUILDER_INIT);

        if (bean  != null){
            where.append(Y41eSqlUtils.generarWhereIgual(ID_BLOQUE_005, bean.getBloque().getIdBloque(), params));
            where.append(Y41eSqlUtils.generarWhereIgual(ID_PREGUNTA_005, bean.getPregunta().getIdPregunta(), params));
            where.append(Y41eSqlUtils.generarWhereIgual(ORDEN_PREG_005, bean.getOrdenPreg(), params));
        }
        return where.toString();
    }

    /**
     * Copia las preguntas de un bloque a otro
     * @param idBloque Long
     * @param idBloqueCopiar Long
     */
    @Override
    public void copiarPreguntas(Long idBloque, Long idBloqueCopiar){
        StringBuilder sqlCopiar = new StringBuilder(Y41eRelBloquePreguntaDaoImpl.STRING_BUILDER_INIT);
        sqlCopiar.append(Y41eSqlUtils.INSERT).append(TABLA)
        .append(Y41eSqlUtils.SELECT).append(idBloque).append(", ")
        .append(ID_PREGUNTA_005).append(",")
        .append(ORDEN_PREG_005)
        .append(Y41eSqlUtils.FROM).append(TABLA)
        .append(Y41eSqlUtils.WHERE)
        .append(ID_BLOQUE_005).append("=?");

        this.getJdbcTemplate().update(sqlCopiar.toString(), idBloqueCopiar);
    }

    /**
     * Obtiene el siguiente orden 
     * @param idBloque Long
     * @return Long
     */
    @Override
    public Long getSigOrden(Long idBloque){
        StringBuilder sqlOrden = new StringBuilder(Y41eSqlUtils.SELECT)
                .append(" NVL(MAX(")
                .append(ORDEN_PREG_005)
                .append("), 0 )+1")
                .append(Y41eSqlUtils.FROM)
                .append(TABLA)
                .append(Y41eSqlUtils.WHERE)
                .append(ID_BLOQUE_005)
                .append("=?");
        return this.getJdbcTemplate().queryForObject(sqlOrden.toString(), Long.class, idBloque);
    }

    /**
     * Asocia las preguntas al bloque indicado
     * @param idBloque Long
     * @param listaPreguntasSeleccionadas List<Y41ePregunta>
     */
    @Override
    public void asosiarPreguntas(Long idBloque, List<Y41ePregunta> listaPreguntasSeleccionadas){
        //obtener el máximo orden
        Long orden = this.getSigOrden(idBloque);
        StringBuilder sqlInsert = new StringBuilder(Y41eRelBloquePreguntaDaoImpl.STRING_BUILDER_INIT);
        sqlInsert.append(Y41eSqlUtils.INSERT)
        .append(TABLA).append(" (")
        .append(ID_BLOQUE_005).append(",")
        .append(ID_PREGUNTA_005).append(",")
        .append(ORDEN_PREG_005).append(")")
        .append("VALUES (?,?,?)");

        final List<Object[]> paramsInsert = new ArrayList<Object[]>();
        List<Object> auxInsert = new ArrayList<Object>();
        for(Y41ePregunta pregunta:listaPreguntasSeleccionadas){
            auxInsert.clear();
            auxInsert.add(idBloque);
            auxInsert.add(pregunta.getIdPregunta());
            auxInsert.add(orden);
            paramsInsert.add(auxInsert.toArray().clone());
            orden++;
        }
        this.getJdbcTemplate().batchUpdate(sqlInsert.toString(), paramsInsert);
    }

    /**
     * Ordena las pregutnas según el orden pasado
     *
     * @param ordenIds String
     * @param idBloque String
     */
    @Override
    public void moverPregunta(String ordenIds, String idBloque){
        StringBuilder sqlOrden = new StringBuilder(Y41eRelBloquePreguntaDaoImpl.STRING_BUILDER_INIT);
        sqlOrden.append(Y41eSqlUtils.UPDATE)
        .append(TABLA).append(" SET ")
        .append(ORDEN_PREG_005).append("=? ")
        .append(Y41eSqlUtils.WHERE)
        .append(ID_BLOQUE_005).append("=?")
        .append(Y41eSqlUtils.AND)
        .append(ID_PREGUNTA_005).append("=?");

        final List<Object[]> paramsUpdate = new ArrayList<Object[]>();
        List<Object> auxUpdate = new ArrayList<Object>();

        //en el atributo orden están los ids de las preguntas
        //hay que separarlos por ; y luego obtener el id por ___
        String[] listaIds = ordenIds.split(";");
        int orden = 1;
        for (String id : listaIds){
            auxUpdate.clear();
            auxUpdate.add(orden);
            auxUpdate.add(idBloque);
            auxUpdate.add(id.substring(id.indexOf("-")+1).split(Y41eConstants.SEPARADOR_OPTION)[1]);
            paramsUpdate.add(auxUpdate.toArray().clone());
            orden++;
        }
        this.getJdbcTemplate().batchUpdate(sqlOrden.toString(), paramsUpdate);
    }

    /**
     * Obtiene los bloques de la encuesta en orden
     * @param bloque Y41eBloque
     * @param encuesta Y41eEncuesta
     * @return List<Y41eBloque>
     */
    @Override
    public List<Y41ePregunta> getPreguntasWeb(Y41eBloque bloque, Y41eEncuesta encuesta){
        StringBuilder sqlBloque = new StringBuilder(Y41eRelBloquePreguntaDaoImpl.STRING_BUILDER_INIT);
        sqlBloque.append(Y41eSqlUtils.SELECT)
        .append(ID_PREGUNTA_005).append(",")
        .append(" DESC_PUBL_ES_004, DESC_PUBL_EU_004, OBLIGATORIO_004, AVISO_004, ID_TIPO_PREGUNTA_004,")
        .append("NVL2(ID_PREGUNTA_014, 'S', 'N') IS_ENLAZADA, ID_PREGUNTA_014")
        .append(Y41eSqlUtils.FROM)
        .append(" Y41E04S01")
        .append(Y41eSqlUtils.JOIN).append(TABLA).append(" ON ")
        .append("ID_PREGUNTA_004=").append(ID_PREGUNTA_005)
        .append(Y41eSqlUtils.LEFT_JOIN).append(" Y41E14S01 ON ").append("ID_ENCUESTA_014").append("=?")
        .append(Y41eSqlUtils.AND).append(TIPO_014).append("='").append(Y41eConstants.TIPO_PREGUNTA).append("'")
        .append(Y41eSqlUtils.AND).append(ID_BLOQUE_005).append("=ID_BLOQUE_014")
        .append(Y41eSqlUtils.AND).append(ID_PREGUNTA_005).append("=ID_ENLAZADA_014")
        .append(Y41eSqlUtils.WHERE).append(ID_BLOQUE_005).append("=?")
        .append(Y41eSqlUtils.ORDER_BY).append(ORDEN_PREG_005).append(" ASC");

        return this.getJdbcTemplate().query(sqlBloque.toString(), this.rwMapPregunta, encuesta.getIdEncuesta() ,bloque.getIdBloque());
    }

    /* (non-Javadoc)
     * @see com.ejie.y41e.dao.Y41eGenericoDaoImpl#getOrderBy()
     */
    @Override
    protected String[] getOrderBy() {
        return Y41eRelBloquePreguntaDaoImpl.ORDER_BY_WHITE_LIST;
    }

    /**
     * StringBuilder initilization value
     */
    public static final int STRING_BUILDER_INIT = 4096;

    /* (non-Javadoc)
     * @see com.ejie.y41e.dao.Y41eGenericoDaoImpl#getFrom()
     */
    @Override
    protected String getFrom() {
        return null;
    }

    /* (non-Javadoc)
     * @see com.ejie.y41e.dao.Y41eGenericoDaoImpl#getSelect()
     */
    @Override
    protected String getSelect() {
        return null;
    }

}