package com.ejie.m62fb.dao.registroVPP;

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

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.RowMapper;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.ejie.m62fb.dao.SQLGenericas;
import com.ejie.m62fb.model.AlojamientoDotacional;
import com.ejie.m62fb.model.ElementoAd;
import com.ejie.m62fb.model.tipos.TipoElemento;
import com.ejie.m62fb.utils.sql.Utilidades;
import com.ejie.m62fb.utils.sql.UtilsResulSet;

/**
 * ElementoAdDaoImpl.
 * 
XXXX
 */
@Repository
@Transactional
public class ElementoAdDaoImpl implements ElementoAdDao {

	private JdbcTemplate jdbcTemplate;

	/*
	 * ROW_MAPPERS
	 */
	private final RowMapper<ElementoAd> rwMap = new RowMapper<ElementoAd>() {
		@Override
		public ElementoAd mapRow(ResultSet resultSet, int rowNum)
				throws SQLException {

			ElementoAd elementoAd = new ElementoAd();

			// IdElemReg
			elementoAd.setIdElemReg(UtilsResulSet.getInteger(resultSet,
					"IDELEMREG"));

			// IdElemento
			elementoAd.setIdElemento(UtilsResulSet.getInteger(resultSet,
					"IDELEMENTO"));
			// CodElemento
			elementoAd.setCodElemento(resultSet.getString("CODELEMENTO"));
			// IdEmplazamiento
			elementoAd.setIdEmplazamiento(UtilsResulSet.getInteger(resultSet,
					"IDEMPLAZAMIENTO"));
			// CodVinculElem
			elementoAd.setCodVinculElem(resultSet.getString("CODVINCULELEM"));
			// NumExpediente
			elementoAd.setNumExpediente(resultSet.getString("NUMEXPEDIENTE"));

			// AlojamientoDotacional
			elementoAd.setAlojamientoDotacional(new AlojamientoDotacional(
					UtilsResulSet.getInteger(resultSet, "IDALOJREG")));
			// TipoElemento
			elementoAd.setTipoElemento(new TipoElemento(resultSet
					.getString("CODTIPOELEM")));

			// SupUtilElem
			elementoAd.setSupUtilElem(resultSet.getBigDecimal("SUPUTILELEM"));
			// NumFijoIbiElem
			elementoAd.setNumFijoIbiElem(resultSet.getString("NUMFIJOIBIELEM"));

			// FecIniGestion
			elementoAd
					.setFecIniGestion(resultSet.getTimestamp("FECINIGESTION"));
			// FecFinGestion
			elementoAd
					.setFecFinGestion(resultSet.getTimestamp("FECFINGESTION"));
			// NumOrganoGestor
			elementoAd.setNumOrganoGestor(UtilsResulSet.getInteger(resultSet,
					"NUMORGANOGESTOR"));
			// FecEnvOrgGestor
			elementoAd.setFecEnvOrgGestor(resultSet
					.getTimestamp("FECENVORGGESTOR"));

			// Direccion
			elementoAd.setDireccion(UtilsResulSet.getDireccionCompleta(
					resultSet, ElementoAdDaoSql.ALIAS_DIR));

			// AbstractM62FBModel
			UtilsResulSet.getAbstractClass(resultSet, elementoAd,
					ElementoAdDaoSql.ALIAS);

			return elementoAd;
		}
	};

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

	/**
	 * Finds a single row in the ElementoAd table.
	 * 
	 * @param elementoAd
	 *            ElementoAd
	 * @return ElementoAd
	 */
	@Override
	@Transactional(readOnly = true)
	public ElementoAd find(ElementoAd elementoAd) {
		String query = ElementoAdDaoSql.SQL_FIND;

		List<ElementoAd> elementospromocionadList = this.jdbcTemplate.query(
				query, this.rwMap, elementoAd.getIdElemReg());
		return DataAccessUtils.uniqueResult(elementospromocionadList);
	}

	/**
	 * Busca el elementoAd del alojamiento y el tipo dado. Si no se informa
	 * alguno de los dos datos no realiza la busqueda.
	 * 
	 * Solo deveria de devolver un unico registro, si no, falla
	 * 
	 * @param idAlojReg
	 *            Integer
	 * @param tipoElemento
	 *            String
	 * 
	 * @return ElementoAd
	 */
	@Override
	@Transactional(readOnly = true)
	public ElementoAd findByIdAlojRegAndTipoElemento(Integer idAlojReg,
			String tipoElemento) {
		ElementoAd elementoAd = null;
		// Si no se informan el idAlojReg y el tipoElemento, no buscar
		if (idAlojReg != null && !Utilidades.isEmpty(tipoElemento)) {
			String query = ElementoAdDaoSql.SQL_FIND_BY_ALOJ_AND_TIPO;
			List<ElementoAd> elementoAdList = this.jdbcTemplate.query(query,
					this.rwMap, idAlojReg, tipoElemento);
			elementoAd = DataAccessUtils.uniqueResult(elementoAdList);
		}

		return elementoAd;
	}

	/**
	 * Desvincula el elementoAd del TipoElemento dado para el Alojamiento
	 * 
	 * @param idAlojReg
	 *            Integer
	 * @param tipoElemento
	 *            String
	 */
	@Override
	public void desvincular(Integer idAlojReg, String tipoElemento) {
		// Si no se informan el idAlojReg y el tipoElemento, no desvincula nada
		if (idAlojReg != null && !Utilidades.isEmpty(tipoElemento)) {
			String query = ElementoAdDaoSql.SQL_DESVINCULAR;
			// Preparar Parametros
			List<Object> params = new ArrayList<Object>();
			// AbstractM62FBModel
			SQLGenericas.getParamsAbstractClass(params, null);
			// IdAlojReg
			params.add(idAlojReg);
			// TipoElemento
			params.add(tipoElemento);
			// Realizar Update
			this.jdbcTemplate.update(query, params.toArray());
		}
	}

	/**
	 * Vincula el elementoAd dado al Alojamiento
	 * 
	 * @param elementoAd
	 *            ElementoAd(idAlojReg)
	 * @param alojDot
	 *            AlojamientoDotacional(idAlojReg)
	 */
	@Override
	public void vincular(ElementoAd elementoAd, AlojamientoDotacional alojDot) {
		// Si no se informan el idElemReg y el idAlojReg, no vincula nada
		if (elementoAd != null && elementoAd.getIdElemReg() != null
				&& alojDot != null && alojDot.getIdAlojReg() != null) {
			String query = ElementoAdDaoSql.SQL_VINCULAR;
			// Preparar Parametros
			List<Object> params = new ArrayList<Object>();
			// IdAlojReg
			params.add(alojDot.getIdAlojReg());
			// AbstractM62FBModel
			SQLGenericas.getParamsAbstractClass(params, null);
			// TipoElemento
			params.add(elementoAd.getIdElemReg());
			// Realizar Update
			this.jdbcTemplate.update(query, params.toArray());
		}
	}
}