package com.ejie.m62fb.dao.registroVPP;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
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.dao.support.DataAccessUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.ejie.m62fb.dao.registroVPP.plsql.M62FuncionesPLSQL;
import com.ejie.m62fb.model.AcuerdoVivienda;
import com.ejie.m62fb.model.SolicitudReserva;
import com.ejie.m62fb.util.UtilSeguridad;
import com.ejie.m62fb.utils.sql.BDUtils;
import com.ejie.m62fb.utils.sql.UtilsResulSet;
import com.ejie.x38.dto.JQGridManager;
import com.ejie.x38.dto.JQGridRequestDto;

/**
 * AcuerdoViviendaDaoImpl.
 * 
XXXX
 */
@Repository
@Transactional
public class AcuerdoViviendaDaoImpl implements AcuerdoViviendaDao {
	private JdbcTemplate jdbcTemplate;

	private final RowMapper<AcuerdoVivienda> rwMapVista = new RowMapper<AcuerdoVivienda>() {
		@Override
		public AcuerdoVivienda mapRow(ResultSet resultSet, int rowNum)
				throws SQLException {

			AcuerdoVivienda acuerdoVivienda = new AcuerdoVivienda();

			// IdM62r41t0
			acuerdoVivienda.setIdM62r41t0(UtilsResulSet.getInteger(resultSet,
					"IDM62R41T0"));

			// SolicitudReserva
			SolicitudReserva solicitudReserva = new SolicitudReserva();
			// IdM62r38t0
			solicitudReserva.setIdM62r38t0(UtilsResulSet.getInteger(resultSet,
					"IDM62R38T0"));
			// NumExpedientePlatea
			solicitudReserva.setNumExpedientePlatea(resultSet
					.getString("NUMEXPEDIENTEPLATEA"));
			// DesEntidadSolic
			solicitudReserva.setDesEntidadSolic(resultSet
					.getString("DESENTIDADSOLIC"));
			// DesDptoSolic
			solicitudReserva.setDesDptoSolic(resultSet
					.getString("DESDPTOSOLIC"));
			acuerdoVivienda.setSolicitudReserva(solicitudReserva);

			// FecAcuerdo
			acuerdoVivienda.setFecAcuerdo(resultSet.getTimestamp("FECACUERDO"));
			// DesEntidadRecep
			acuerdoVivienda.setDesEntidadRecep(resultSet
					.getString("DESENTIDADRECEP"));
			// DesDptoRecep
			acuerdoVivienda
					.setDesDptoRecep(resultSet.getString("DESDPTORECEP"));
			// IndModifSinDoc
			acuerdoVivienda.setIndModifSinDoc(UtilsResulSet.getIndicadorSN(
					resultSet, "INDMODIFSINDOC"));

			// NumVivReservadas
			acuerdoVivienda.setNumVivReservadas(UtilsResulSet.getInteger(
					resultSet, "NUMVIVRESERVADAS"));
			// ImcPvpTotal
			acuerdoVivienda.setImcPvpTotal(resultSet
					.getBigDecimal("IMCPVPTOTAL"));

			return acuerdoVivienda;
		}
	};

	/**
	 * 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 AcuerdoVivienda table.
	 * 
	 * @param acuerdoVivienda
	 *            AcuerdoVivienda
	 * @return AcuerdoVivienda
	 */
	@Override
	public AcuerdoVivienda add(final AcuerdoVivienda acuerdoVivienda) {

		KeyHolder keyHolder = new GeneratedKeyHolder();
		this.jdbcTemplate.update(new PreparedStatementCreator() {
			@Override
			public PreparedStatement createPreparedStatement(
					Connection connection) throws SQLException {
				// Sentencia SQL y array con ids que son primary key
				PreparedStatement ps = connection.prepareStatement(
						AcuerdoViviendaDaoSql.SQL_INSERT,
						new String[] { "ID_M62R41T0" });

				Object idM62r38t0Aux = acuerdoVivienda.getSolicitudReserva() != null ? acuerdoVivienda
						.getSolicitudReserva().getIdM62r38t0() : null;

				// SolicitudReserva
				ps.setObject(1, idM62r38t0Aux);

				// FecAcuerdo
				ps.setDate(2, new java.sql.Date(acuerdoVivienda.getFecAcuerdo()
						.getTime()));

				// DesEntidadRecep
				ps.setString(3, acuerdoVivienda.getDesEntidadRecep());
				// DesDptoRecep
				ps.setString(4, acuerdoVivienda.getDesDptoRecep());
				// IndModifSinDoc
				ps.setString(5, BDUtils.formatIndicadorToBD(acuerdoVivienda
						.getIndModifSinDoc()));

				// AbstractM62FBModel (UsuarioConectado)
				ps.setString(6, UtilSeguridad.getNombreUsuarioConectado());

				return ps;
			}
		}, keyHolder);

		// Obtener Pk generada por el trigger
		acuerdoVivienda.setIdM62r41t0(Integer.valueOf(keyHolder.getKeys()
				.get("ID_M62R41T0").toString()));

		return acuerdoVivienda;
	}

	/**
	 * Finds a single row in the AcuerdoVivienda table.
	 * 
	 * @param acuerdoVivienda
	 *            AcuerdoVivienda
	 * @return AcuerdoVivienda
	 */
	@Override
	@Transactional(readOnly = true)
	public AcuerdoVivienda find(AcuerdoVivienda acuerdoVivienda) {
		String query = AcuerdoViviendaDaoSql.SQL_FIND;
		List<AcuerdoVivienda> acuerdoViviendaList = this.jdbcTemplate.query(
				query, this.rwMapVista, acuerdoVivienda.getIdM62r41t0());
		return DataAccessUtils.uniqueResult(acuerdoViviendaList);
	}

	/**
	 * Recupera un acuerdo por el idM62r38t0 de la solicitud
	 * 
	 * @param solicitudReserva
	 *            SolicitudReserva
	 * @return SolicitudReserva
	 */
	@Override
	public AcuerdoVivienda findBySolicitud(SolicitudReserva solicitudReserva) {
		String query = AcuerdoViviendaDaoSql.SQL_FIND_BY_SOLICITUD;
		List<AcuerdoVivienda> acuerdoViviendaList = this.jdbcTemplate.query(
				query, this.rwMapVista, solicitudReserva.getIdM62r38t0());
		return DataAccessUtils.uniqueResult(acuerdoViviendaList);
	}

	/**
	 * Removes a single row in the AcuerdoVivienda table.
	 * 
	 * @param acuerdoVivienda
	 *            AcuerdoVivienda
	 * @return
	 */
	@Override
	public void remove(AcuerdoVivienda acuerdoVivienda) {
		/*****
		 * Llamada a function que implementa llamada a plsql
		 ****/
		M62FuncionesPLSQL m62FuncionesPLSQL = new M62FuncionesPLSQL(
				this.jdbcTemplate.getDataSource());
		m62FuncionesPLSQL.borrarAcuerdoReserva(acuerdoVivienda.getIdM62r41t0());
	}

	/**
	 * Finds a list of rows in the AcuerdoVivienda table.
	 * 
	 * @param acuerdoVivienda
	 *            AcuerdoVivienda
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @return List<AcuerdoVivienda>
	 */
	@Override
	@Transactional(readOnly = true)
	public List<AcuerdoVivienda> findAll(AcuerdoVivienda acuerdoVivienda,
			JQGridRequestDto jqGridRequestDto) {

		StringBuilder query = new StringBuilder(
				AcuerdoViviendaDaoSql.SQL_FIND_ALL);

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMap(acuerdoVivienda);
		StringBuilder where = new StringBuilder(
				AcuerdoViviendaDaoSql.SQL_WHERE_ALL);
		where.append(mapaWhere.get("query"));
		query.append(where);

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

		if (jqGridRequestDto != null) {
			query = JQGridManager.getPaginationQuery(jqGridRequestDto, query);
		}

		return this.jdbcTemplate.query(query.toString(), this.rwMapVista,
				params.toArray());
	}
	
	@Override
	@Transactional(readOnly = true)
	public Long hayVivSolicitadasSinVivReservadas(BigDecimal idM62R38T0) {
		StringBuilder query = new StringBuilder(
				AcuerdoViviendaDaoSql.SQL_TODAS_VIVIENDAS_SOLICITADAS_TIENEN_VIVIENDAS_RESERVADAS);
		return this.jdbcTemplate.queryForLong(query.toString(),idM62R38T0);
	}
	/*
	 * OPERACIONES RUP_TABLE
	 */

	/**
	 * Counts rows in the AcuerdoVivienda table.
	 * 
	 * @param acuerdoVivienda
	 *            AcuerdoVivienda
	 * @return Long
	 */
	@Override
	@Transactional(readOnly = true)
	public Long findAllCount(AcuerdoVivienda acuerdoVivienda) {
		StringBuilder query = new StringBuilder(
				AcuerdoViviendaDaoSql.SQL_FIND_ALL_COUNT);

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMap(acuerdoVivienda);
		StringBuilder where = new StringBuilder(
				AcuerdoViviendaDaoSql.SQL_WHERE_ALL);
		where.append(mapaWhere.get("query"));
		query.append(where);

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

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

	/*
	 * MÉTODOS PRIVADOS
	 */

	/**
	 * Returns a map with the needed value to create the conditions to filter by
	 * the AcuerdoVivienda entity
	 * 
	 * @param acuerdoVivienda
	 *            AcuerdoVivienda Bean with the criteria values to filter by.
	 * @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.
	 */
	private Map<String, ?> getWhereMap(AcuerdoVivienda acuerdoVivienda) {

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

		if (acuerdoVivienda != null) {
			if (acuerdoVivienda.getIdM62r41t0() != null) {
				BDUtils.crearFiltroIgual(where, params, "ACU.ID_M62R41T0",
						acuerdoVivienda.getIdM62r41t0());
			}
			if (acuerdoVivienda.getSolicitudReserva() != null
					&& acuerdoVivienda.getSolicitudReserva().getIdM62r38t0() != null) {
				BDUtils.crearFiltroIgual(where, params, "ACU.ID_M62R38T0",
						acuerdoVivienda.getSolicitudReserva().getIdM62r38t0());
			}
			if (acuerdoVivienda.getFecAcuerdo() != null) {
				BDUtils.crearFiltroIgual(where, params, "ACU.FEC_ACUERDO",
						acuerdoVivienda.getFecAcuerdo());
			}
			if (acuerdoVivienda.getDesEntidadRecep() != null) {
				BDUtils.crearFiltroIgual(where, params,
						"ACU.DES_ENTIDAD_RECEP",
						acuerdoVivienda.getDesEntidadRecep());
			}
			if (acuerdoVivienda.getDesDptoRecep() != null) {
				BDUtils.crearFiltroIgual(where, params, "ACU.DES_DPTO_RECEP",
						acuerdoVivienda.getDesDptoRecep());
			}
			if (acuerdoVivienda.getIndModifSinDoc() != null) {
				BDUtils.crearFiltroIgual(where, params,
						"ACU.IND_MODIF_SIN_DOC",
						acuerdoVivienda.getIndModifSinDoc());
			}
		}

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

		return mapWhere;
	}
}