package com.ejie.m62fb.dao.registroVPP;

import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.ejie.m62fb.utils.constants.IberErrorsMsgConstants;
import com.ejie.m62fb.utils.error.UFException;
import com.ejie.m62fb.dao.ComboP28Dao;
import com.ejie.m62fb.dao.PersonaDao;
import com.ejie.m62fb.dao.SQLGenericas;
import com.ejie.m62fb.dao.registroVPP.plsql.M62FuncionesPLSQL;
import com.ejie.m62fb.model.AlojamientoDotacional;
import com.ejie.m62fb.model.ContratoAlquilerad;
import com.ejie.m62fb.model.Inquilino;
import com.ejie.m62fb.model.InquilinoAd;
import com.ejie.m62fb.model.persona.Persona;
import com.ejie.m62fb.model.tipos.TipoSiNo;
import com.ejie.m62fb.utils.sql.BDUtils;
import com.ejie.m62fb.utils.sql.UtilsResulSet;
import com.ejie.x38.dao.RowNumResultSetExtractor;
import com.ejie.x38.dto.JQGridManager;
import com.ejie.x38.dto.JQGridRequestDto;
import com.ejie.x38.dto.TableRowDto;

/**
 * InquilinoAdDaoImpl generated by UDA, 08-oct-2015 9:02:54.
XXXX
 */
 
@Repository
@Transactional
public class InquilinoAdDaoImpl implements InquilinoAdDao {
    private JdbcTemplate jdbcTemplate;
    
    @SuppressWarnings("rawtypes")
	@Autowired
	private ComboP28Dao<TipoSiNo> comboP28Dao;
	@Autowired
	PersonaDao personaDao;
	@Autowired
	ContratoAlquileradDao contratoAlquileradDao;
	@Autowired
	AlojamientoDotacionalDao alojamientoDotacionalDao;
	
	
	/*
	 * ROW_MAPPERS
	 */
	private RowMapper<InquilinoAd> rwMap = new RowMapper<InquilinoAd>() {
		public InquilinoAd mapRow(ResultSet resultSet, int rowNum) throws SQLException {
			
			InquilinoAd inquilinoAd = new InquilinoAd(resultSet.getInt("IDINQUILINO"));
			
			
			
			//Numero de inquilinos
			inquilinoAd.setNumInquilino(
					UtilsResulSet.getLong(resultSet, "NUMINQUILINO"));
			
			// Persona
			Persona persona = new Persona(resultSet.getBigDecimal("IDPERSONA"));
			inquilinoAd.setPersona(personaDao.find(persona));
			
			// Contrato 
			ContratoAlquilerad contratoad = new ContratoAlquilerad(resultSet.getInt("IDCONTRATO"));
			inquilinoAd.setContratoAlquilerad(contratoAlquileradDao.find(contratoad));
			
			
			//Id alojamiento Registrado
			AlojamientoDotacional alojamientoDotacional = new AlojamientoDotacional(resultSet.getInt("IDALOJREG"));
			inquilinoAd.setAlojamientoDotacional(alojamientoDotacionalDao.find(alojamientoDotacional));
			
//			AlojamientoDotacional alojamientoDotacional = inquilinoAd.getContratoAlquilerad().getAlojamientoDotacional();
//			inquilinoAd.setAlojamientoDotacional(alojamientoDotacional);
			
			// Indicador Vivienda Adaptada
			TipoSiNo indAlojAdaptada = new TipoSiNo(
					resultSet.getString("INDALOJADAPTADA"));
			inquilinoAd.setIndAlojAdaptada((TipoSiNo) comboP28Dao
					.find(indAlojAdaptada));
			

			// Fecha Alta
			inquilinoAd.setFecAlta(resultSet.getTimestamp("FECALTA"));

			// Fecha/Hora Ultima Modificacion
			inquilinoAd.setFecHorUltimaModif(resultSet
					.getTimestamp("FEHULTMODIF"));

			// Codigo Usuario Ultima Moficacion
			inquilinoAd.setCodUsuarioUltimaModif(resultSet
					.getString("CODUSUULTMODIF"));
			
			return inquilinoAd;
		} 
	} ;
           
	private RowMapper<InquilinoAd> rwMapPK = new RowMapper<InquilinoAd>() {
		public InquilinoAd mapRow(ResultSet resultSet, int rowNum) throws SQLException {
			return new InquilinoAd(
				resultSet.getInt("IDINQUILINO")
           ); } } ;



	/**
     * Method use to set the datasource.
     *
     * @param dataSource DataSource
     * @return
     */
    @Resource
    public void setDataSource(DataSource dataSource) {
    	this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

	/*
	 * OPERACIONES CRUD
	 */

    /**
     * Inserts a single row in the InquilinoAd table.
     *
     * @param inquilinoad InquilinoAd
     * @return InquilinoAd
     */
	public InquilinoAd add(InquilinoAd inquilinoad) {
		
		String query = InquilinoadDaoSql.SQL_ADD;
		List<Object> params = new ArrayList<Object>();
		
		
		// Campos para la generación del inquilino
		if(inquilinoad!=null){
			
			
			// ID CONTRATO
			Integer getIdContratoAux = null;
			if (inquilinoad.getContratoAlquilerad() != null &&
					inquilinoad.getContratoAlquilerad().getIdContrato() != null ) {
				getIdContratoAux = inquilinoad.getContratoAlquilerad().getIdContrato() ;
			}
			
			//Id Alojamiento Dotacional registrado
			Integer getAlojRegAux = null;
			if (inquilinoad.getAlojamientoDotacional() != null &&
					inquilinoad.getAlojamientoDotacional() != null ) {
				getAlojRegAux = inquilinoad.getAlojamientoDotacional().getIdAlojReg() ;
			}
			
			
			//Id Número inquilino
			Long getNumInqAux = null;
			if (inquilinoad.getContratoAlquilerad() != null &&
					inquilinoad.getContratoAlquilerad().getIdContrato() != null ) {
				getNumInqAux = getNumInquilino(getIdContratoAux);
			}

			
			//Id Persona
			BigDecimal getIdPersonaAux = null;
			if (inquilinoad.getPersona()!= null  && inquilinoad.getPersona().getIdPersona()!=null ){
				getIdPersonaAux=inquilinoad.getPersona().getIdPersona();
			}
			
			//Indicador alojamiento adaptado
			String getIndAdaptado = null;
			if (inquilinoad.getIndAlojAdaptada() != null) {
				getIndAdaptado = inquilinoad.getIndAlojAdaptada().getCodTabla();
			}
			
			// Preparar Parametros
			
			// ID CONTRATO
			params.add(getIdContratoAux);
			
			//Id Alojamiento Registrado
			params.add(getAlojRegAux);
			
			//Id Número inquilino
			if(getNumInqAux==0){
				params.add(new Long(0));
			}else{
				getNumInqAux = getNumInqAux++;
				params.add(getNumInqAux);
			}
			
			//Id Persona
			params.add(getIdPersonaAux);
			
			//Ind alojamiento adaptado
			if (inquilinoad.getIndAlojAdaptada() != null) {
				params.add(getIndAdaptado);
			} else {
				params.add(BDUtils.FALSE);
			}
			
			
			// CodUsuario
			SQLGenericas.getParamsAbstractClass(params, inquilinoad);
		}

		this.jdbcTemplate.update(query, params.toArray());
		return inquilinoad;
	}

	/**
	 * Metodo que develve el numero de inquilino para ese Alojamiento Dotacional
	 * @param getIdContratoAux 
	 * @return
	 */
	private Long getNumInquilino(Integer getIdContratoAux) {
		
		String query = InquilinoadDaoSql.SQL_GET_NUMINQUILINO;
		
		return this.jdbcTemplate.queryForLong(query.toString(),
				getIdContratoAux);
	}

	/**
	 * Método que prepara los parametros para actualizar y los añade al array enviado. 
	 * @param params
	 * @param inquilinoad
	 * @param hasWhere 
	 * 			Parametro que indica si he de meter clausulas de condición el los paramatros
	 */
    private void prepareParams(List<Object> params, InquilinoAd inquilinoad, boolean hasWhere) {
    	// Campos para la generación del inquilino
		if(inquilinoad!=null){
			// Id Inquilino
			Integer getIdInquilinoAux = null;
			if (inquilinoad.getIdInquilino() != null ) {
				getIdInquilinoAux = inquilinoad.getIdInquilino() ;
			}
			
			// ID CONTRATO
			Integer getIdContratoAux = null;
			if (inquilinoad.getContratoAlquilerad() != null &&
					inquilinoad.getContratoAlquilerad().getIdContrato() != null ) {
				getIdContratoAux = inquilinoad.getContratoAlquilerad().getIdContrato() ;
			}
			
			//Id Alojamiento Registrado
			Integer getAlojRegAux = null;
			if (inquilinoad.getAlojamientoDotacional() != null  && 
					inquilinoad.getAlojamientoDotacional().getIdAlojReg() !=null) {
				getAlojRegAux = inquilinoad.getAlojamientoDotacional().getIdAlojReg() ;
			}
			
			//Id Número inquilino
			Long getNumInqAux = null;
			if (inquilinoad.getNumInquilino() != null ) {
				getNumInqAux = inquilinoad.getNumInquilino() ;
			}
			
			//Id Persona
			BigDecimal getIdPersonaAux = null;
			if (inquilinoad.getPersona()!= null  && inquilinoad.getPersona().getIdPersona()!=null ){
				getIdPersonaAux=inquilinoad.getPersona().getIdPersona();
			}
			//Indicador alojamiento adaptado
			String getIndAdaptado = null;
			if (inquilinoad.getIndAlojAdaptada() != null) {
				getIndAdaptado = inquilinoad.getIndAlojAdaptada().getCodTabla();
			}
			
			// Preparar Parametros
			
			// ID CONTRATO
			params.add(getIdContratoAux);
			//Id Alojamiento Registrado
			params.add(getAlojRegAux);
			//Id Número inquilino
			params.add(getNumInqAux);
			//Id Persona
			params.add(getIdPersonaAux);
			//Ind alojamiento adaptado
			params.add(getIndAdaptado);
			
			// CodUsuario
			SQLGenericas.getParamsAbstractClass(params, inquilinoad);
			
			// Campos WHERE
			if (hasWhere){
				// Id Inquilino
				params.add(getIdInquilinoAux);
			}
			
	   }
	}

	/**
     * Updates a single row in the InquilinoAd table.
     *
     * @param inquilinoad InquilinoAd
     * @return InquilinoAd
     */
    public InquilinoAd update(InquilinoAd inquilinoad) {
    	
    	String query = InquilinoadDaoSql.SQL_EDIT;
		List<Object> params = new ArrayList<Object>();
		
		this.prepareParams(params, inquilinoad, true);

		this.jdbcTemplate.update(query, params.toArray());
		return inquilinoad;
	}
    
	
	/**
	 * FindForUpdate
	 * 
	 * @param inquilinoad
	 *            InquilinoAd
	 * @return InquilinoAd
	 */
	@Override
	public InquilinoAd findForUpdate(InquilinoAd inquilinoad) {
		InquilinoAd inquilinoadBD;
		try {
			inquilinoadBD = this.jdbcTemplate.queryForObject(
					InquilinoadDaoSql.SQL_FIND_FOR_UPDATE, this.rwMap,
							inquilinoad.getFecHorUltimaModif(),
							inquilinoad.getIdInquilino());
		} catch (EmptyResultDataAccessException e) {
			throw new UFException(IberErrorsMsgConstants.CONCURRENCY_MSG);
		}
		if (inquilinoadBD == null) {
			throw new UFException(IberErrorsMsgConstants.CONCURRENCY_MSG);
		}
		return inquilinoadBD;
	}

    /**
     * Finds a single row in the InquilinoAd table.
     *
     * @param inquilinoad InquilinoAd
     * @return InquilinoAd
     */
    @Transactional (readOnly = true)
    public InquilinoAd find(InquilinoAd inquilinoad) {
    	
		String query = InquilinoadDaoSql.SQL_FIND;
		
		List<InquilinoAd> inquilinoadList = this.jdbcTemplate.query(query, this.rwMap, inquilinoad.getIdInquilino());
		return (InquilinoAd) DataAccessUtils.uniqueResult(inquilinoadList);
    }

    /**
     * Removes a single row in the InquilinoAd table.
     *
     * @param inquilinoad InquilinoAd
     * @return
     */
    public void remove(InquilinoAd inquilinoad) {
		/*****
		 * Llamada a function que implementa llamada a plsql
		 ****/
		M62FuncionesPLSQL m62FuncionesPLSQL = new M62FuncionesPLSQL(
				this.jdbcTemplate.getDataSource());
		
		m62FuncionesPLSQL.borrarInquilinoContratoAlojDotacional(inquilinoad.getIdInquilino());
    }
    
	
	/**
	 * Finds rows in the InquilinoAd table using like.
     * 
     * @param inquilinoad InquilinoAd
     * @param jqGridRequestDto JQGridRequestDto
     * @param startsWith Boolean
     * @return List<InquilinoAd>
     */
	@Transactional (readOnly = true)
    public List<InquilinoAd> findAllLike(InquilinoAd inquilinoad, JQGridRequestDto jqGridRequestDto, Boolean startsWith) {
		
		String query = InquilinoadDaoSql.SQL_FIND_ALL_LIKE;
		StringBuilder sbQuery = new StringBuilder(query);

		
		Map<String, ?> mapaWhere = this.getWhereLikeMap(inquilinoad, startsWith);
		StringBuilder where = new StringBuilder("");
		where.append(mapaWhere.get("query"));
		sbQuery.append(where);

		List<?> params = (List<?>) mapaWhere.get("params");
		

		if (jqGridRequestDto != null) {
			sbQuery = JQGridManager.getPaginationQuery(jqGridRequestDto, sbQuery);
		}
		
		return (List<InquilinoAd>) this.jdbcTemplate.query(sbQuery.toString(), this.rwMap, params.toArray());
	}

	/*
	 * OPERACIONES RUP_TABLE
	 */
	

	
	/**
	 * Counts rows in the InquilinoAd table using like.
     * 
     * @param inquilinoad InquilinoAd
     * @param startsWith Boolean
     * @return Long 
     */
	@Transactional (readOnly = true)
    public Long findAllLikeCount(InquilinoAd inquilinoad, Boolean startsWith) {
		String query = InquilinoadDaoSql.SQL_FIND_ALL_LIKE_COUNT;
		StringBuilder sbQuery = new StringBuilder(query);
		
		Map<String, ?> mapaWhere = this.getWhereLikeMap(inquilinoad, startsWith);
		StringBuilder where = new StringBuilder("");
		where.append(mapaWhere.get("query"));
		sbQuery.append(where);

		List<?> params = (List<?>) mapaWhere.get("params");

		return this.jdbcTemplate.queryForLong(sbQuery.toString(), params.toArray());
	}

	/**
	 * Reorder the data list of InquilinoAd selected for rup_table
     * 
     * @param inquilinoad InquilinoAd
     * @param jqGridRequestDto JQGridRequestDto
     * @param startsWith Boolean
     * @return List<TableRowDto<InquilinoAd>> 
     */
	@Override 
	public List<TableRowDto<InquilinoAd>> reorderSelection(InquilinoAd inquilinoad, JQGridRequestDto jqGridRequestDto, Boolean startsWith) {

		//Query base
		String query = InquilinoadDaoSql.SQL_FIND_ALL_LIKE;
		StringBuilder sbQuery = new StringBuilder(query);
		
		// FILTRADO
		Map<String, ?> mapaWhere = this.getWhereLikeMap(inquilinoad, startsWith);
		StringBuilder where = new StringBuilder("");
		where.append(mapaWhere.get("query"));
		sbQuery.append(where);

		// Parámetros de filtrado
		@SuppressWarnings("unchecked")
		List<Object> filterParamList = (List<Object>) mapaWhere.get("params");

		// SQL para la reordenación
		StringBuilder sbReorderSelectionSQL = JQGridManager.getReorderQuery(
				sbQuery, jqGridRequestDto, InquilinoAd.class, filterParamList,
				InquilinoadDaoSql.PK_INQUILINOAD);
		
		return this.jdbcTemplate.query(sbReorderSelectionSQL.toString(), new RowNumResultSetExtractor<InquilinoAd>(this.rwMapPK, jqGridRequestDto),  filterParamList.toArray());
	}


	/*
	 * MÉTODOS PRIVADOS
	 */
	 	
	// CHECKSTYLE:ON CyclomaticComplexity - Generación de código de UDA
	
	/**
	 * StringBuilder initilization value
	 */
	 public static final int STRING_BUILDER_INIT = 4096;


	/**
     * Devuelve si existen contratos de alojamiento dotacional y de Etxelaguntza para el inquilino recibido
     * en el contrato que estamos dando de alta
     * 
     * @param idPersona
     * 			Integer
     * @param idContrato
	 *            Integer
     * @return
     */
	public Boolean existsContract4Inquilino(Integer idPersona, Integer idContrato) {
		//Query que busca que no exista contrato en Etxelagunza con las condiciones definidas
		String query = InquilinoadDaoSql.SQL_COUNT_CONTRACTS;
		
		Integer count = this.jdbcTemplate.queryForInt(query, idPersona, idContrato);
		
		if(count==0)
			return false;
		else
			return true;
	}
	
	/**
	 * Returns a map with the needed value to create the conditions to filter by
	 * the Inquilinoad entity
	 * 
	 * @param inquilinoad
	 *            Inquilinad Bean with the criteria values to filter by.
	 * @param startsWith
	 *            Boolean
	 * @return Map created with two keys key query stores the sql query syntax
	 *         key params stores the parameter values to be used in the
	 *         condition sentence.
	 */
	// CHECKSTYLE:OFF CyclomaticComplexity - Generación de código de UDA
	private Map<String, Object> getWhereLikeMap(InquilinoAd inquilinoad,
			Boolean startsWith) {

		StringBuilder where = new StringBuilder(
				InquilinoDaoImpl.STRING_BUILDER_INIT);
		List<Object> params = new ArrayList<Object>();

		if (inquilinoad != null) {
			// NumInquilino
			if (inquilinoad.getNumInquilino() != null) {
				BDUtils.crearFiltroIgual(where, params, InquilinoadDaoSql.ALIAS_INQUILINOAD+".NUM_INQUILINO",
						inquilinoad.getNumInquilino());
			}
			// idContrato
			if (inquilinoad.getContratoAlquilerad() != null && 
					inquilinoad.getContratoAlquilerad().getIdContrato() != null) {
				BDUtils.crearFiltroIgual(where, params, InquilinoadDaoSql.ALIAS_INQUILINOAD+".ID_CONTRATO",
						inquilinoad.getContratoAlquilerad().getIdContrato());
			}
			
			if (inquilinoad.getPersona() != null) {
				// IdPersona
				if (inquilinoad.getPersona().getIdPersona() != null) {
					BDUtils.crearFiltroIgual(where, params, InquilinoadDaoSql.ALIAS_INQUILINOAD+".ID_PERSONA",
							inquilinoad.getPersona().getIdPersona());
				}
			}
		}

		Map<String, Object> mapWhere = new HashMap<String, Object>();
		mapWhere.put("query", where);
		mapWhere.put("params", params);

		return mapWhere;
	}
	

}

