package com.ejie.ab78.dao.establecimientos;

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

import com.ejie.ab78.model.establecimientos.Establecimiento;
import com.ejie.ab78.model.terceros.DatosDirecciones;
import com.ejie.ab78.model.terceros.DatosTerceros;
import com.ejie.ab78.model.terceros.Sexo;
import com.ejie.ab78.model.terceros.TiposDocumento;
import com.ejie.x38.dto.TableManager;
import com.ejie.x38.dto.TableRequestDto;

/**
 * Ab6301s00DaoImpl  
 * 
 *  
 */

@Repository
@Transactional
public class EstablecimientoDaoImpl implements EstablecimientoDao {

	public static final String[] ORDER_BY_WHITE_LIST = new String[] { 
			"IDESTABLECIMIENTO", "IDENTIFICADORESTABLECIMIENTO", "DESCNOMBRE", "TELEFONO", 
			"IDTERCERO", "NIFINTERESADO", "NOMBREINTERESADO", "APELLIDO1INTERESADO", "APELLIDO2INTERESADO",
			"DIRECCION", "NUMERO", "ESCALERA", "PISO", "LETRA", "CODIGO_POSTAL", "IDPAIS", "IDPROVINCIA", 
			"IDMUNICIPIO", "IDLOCALIDAD", "DESCRIPCIONPROVINCIAEXTR", "DESCRIPCIONCIUDADEXTR", "DIRIDENTESTABLECIMIENTO", 
			"MUNICIPIODSO" };

	public static final int STRING_BUILDER_INIT = 4096;
	private JdbcTemplate jdbcTemplate;

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

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

			Establecimiento establecimiento = new Establecimiento();

			establecimiento.setTelefono(resultSet.getString("TELEFONO"));
			establecimiento.setIdEstablecimiento(resultSet.getInt("IDESTABLECIMIENTO"));
			establecimiento.setIdentificadorEstablecimiento(resultSet.getString("IDENTIFICADORESTABLECIMIENTO"));
			establecimiento.setDescrNombre(resultSet.getString("DESCNOMBRE"));
			
			TiposDocumento tipoDoc = new TiposDocumento();
			tipoDoc.setIdTipoDocumento(resultSet.getLong("IDTIPODOCUMENTO"));
			
			Sexo sexo = new Sexo();
			sexo.setIdSexo(resultSet.getLong("IDSEXO"));

			DatosTerceros datosTerceros = new DatosTerceros(resultSet.getInt("IDTERCERO"),
					resultSet.getString("NIFINTERESADO"), tipoDoc, resultSet.getString("NOMBREINTERESADO"),
					resultSet.getString("APELLIDO1INTERESADO"), resultSet.getString("APELLIDO2INTERESADO"), sexo, null, null, null, null);

			DatosDirecciones datosDirecciones = new DatosDirecciones(null, null, resultSet.getString("DIRECCION"),
					resultSet.getString("NUMERO"), resultSet.getString("ESCALERA"), resultSet.getString("PISO"),
					resultSet.getString("LETRA"), resultSet.getString("CODIGO_POSTAL"), resultSet.getLong("IDPAIS"),
					resultSet.getLong("IDPROVINCIA"), resultSet.getLong("IDMUNICIPIO"),
					resultSet.getLong("IDLOCALIDAD"), resultSet.getString("DESCRIPCIONPROVINCIAEXTR"),
					resultSet.getString("DESCRIPCIONCIUDADEXTR"), resultSet.getString("DIRIDENTESTABLECIMIENTO"), null, null,
					resultSet.getString("MUNICIPIODSO"));

			establecimiento.setDatosTerceros(datosTerceros);
			establecimiento.setDatosDirecciones(datosDirecciones);

			return establecimiento;
		}
	};

	@Override
	public List<Establecimiento> findAllLike(Establecimiento ab6301s00, TableRequestDto tableRequestDto, Boolean startsWith) {
		StringBuilder query = new StringBuilder(
				"SELECT t6301.ID_ESTABLECIMIENTO IDESTABLECIMIENTO, t6301.TELEFONO, t6301.IDENTIFICADOR_ESTABLECIMIENTO IDENTIFICADORESTABLECIMIENTO, t6301.NOMBRE_COMERCIAL DESCNOMBRE, "
				+ " VS10.DOCUMENTO NIFINTERESADO, VS10.NOMBRE NOMBREINTERESADO, VS10.APELLIDO1 APELLIDO1INTERESADO, VS10.APELLIDO2 APELLIDO2INTERESADO, VS10.ID_TERCERO IDTERCERO, VS10.ID_TIPO_DOCUMENTO IDTIPODOCUMENTO, VS10.ID_SEXO IDSEXO, "
				+ " T36.DIRECCION, T36.NUMERO, T36.ESCALERA, T36.PISO, T36.LETRA, T36.CODIGO_POSTAL, T36.MUNICIPIODSO, T36.ID_PROVINCIA IDPROVINCIA, "
				+ " T36.ID_MUNICIPIO IDMUNICIPIO, T36.ID_LOCALIDAD IDLOCALIDAD, T36.IDPAIS IDPAIS, T36.DESCRIPCIONPROVINCIAEXTR, T36.DESCRIPCIONCIUDADEXTR, T36.IDENTIFICADORESTABLECIMIENTO DIRIDENTESTABLECIMIENTO ");
		query.append(
				" FROM ESTABLECIMIENTOS_REGISTRADOS t6301, TIPOS_ESTABLECIMIENTO t6311, "
				+ " ( SELECT t6339.ID_ESTABLECIMIENTO, VS35.* FROM (  SELECT t6339.ID_ESTABLECIMIENTO, t6339.ID_TIPO_TERCERO ID_TIPO_TERCERO, MAX(t6339.ID_TERCERO) ID_TERCERO FROM REL_EST_TER t6339 WHERE t6339.ID_TIPO_TERCERO = 9 AND t6339.BAJA = 0 GROUP BY t6339.ID_ESTABLECIMIENTO, ID_TIPO_TERCERO ) t6339, AB78.DATOS_TERCERO VS35 WHERE t6339.ID_TERCERO = VS35.ID_TERCERO AND t6339.ID_TIPO_TERCERO = 9 ) VS10, "
				+ " ( SELECT t6346.ID_ESTABLECIMIENTO, DIR.ID_DIRECCION, DIR.ID_TERCERO, DIR.ID_PROVINCIA, DIR.ID_MUNICIPIO, DIR.ID_LOCALIDAD, DIR.DIRECCION, DIR.NUMERO, DIR.ESCALERA, DIR.PISO, DIR.LETRA, DIR.CODIGO_POSTAL, DIR.ID_PAIS IDPAIS, DIR.DESCRIPCION_PROVINCIA DESCRIPCIONPROVINCIAEXTR, DIR.DESCRIPCION_CIUDAD DESCRIPCIONCIUDADEXTR, DIR.IDENTIFICADOR_ESTABLECIMIENTO IDENTIFICADORESTABLECIMIENTO, T17.DS_O MUNICIPIODSO FROM AB78.DATOS_DIRECCIONES DIR, AB78.MUNICIPIOS T17, REL_EST_DIR t6346 WHERE DIR.ID_TIPO_DIRECCION = 2 AND DIR.ID_PROVINCIA = T17.PROVINCIA_ID (+) AND DIR.ID_MUNICIPIO = T17.ID (+) AND DIR.ID_DIRECCION = t6346.ID_DIRECCION ) T36 ");
		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereLikeMap(ab6301s00, startsWith);

		StringBuilder where = new StringBuilder(
				" WHERE 1 = 1 AND t6301.ID_ESTABLECIMIENTO = T36.ID_ESTABLECIMIENTO (+) AND t6301.ID_TIPO_ESTABLECIMIENTO = T6311.ID_TIPO_ESTABLECIMIENTO AND t6301.ID_ESTABLECIMIENTO = VS10.ID_ESTABLECIMIENTO (+) ");
		where.append(mapaWhere.get("query"));
		query.append(where);

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

		if (tableRequestDto != null) {
			query = TableManager.getPaginationQuery(tableRequestDto, query, EstablecimientoDaoImpl.ORDER_BY_WHITE_LIST);
		}

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

	@Override
	public Long findAllLikeCount(Establecimiento ab6301s00, Boolean startsWith) {
		StringBuilder query = new StringBuilder(
				"SELECT COUNT(1) FROM ESTABLECIMIENTOS_REGISTRADOS t6301, TIPOS_ESTABLECIMIENTO t6311, "
				+ " ( SELECT t6339.ID_ESTABLECIMIENTO, VS35.* FROM (  SELECT t6339.ID_ESTABLECIMIENTO, t6339.ID_TIPO_TERCERO ID_TIPO_TERCERO, MAX(t6339.ID_TERCERO) ID_TERCERO FROM REL_EST_TER t6339 WHERE t6339.ID_TIPO_TERCERO = 9 AND t6339.BAJA = 0 GROUP BY t6339.ID_ESTABLECIMIENTO, ID_TIPO_TERCERO ) t6339, AB78.DATOS_TERCERO VS35 WHERE t6339.ID_TERCERO = VS35.ID_TERCERO AND t6339.ID_TIPO_TERCERO = 9 ) VS10, "
				+ " ( SELECT t6346.ID_ESTABLECIMIENTO, DIR.ID_DIRECCION, DIR.ID_TERCERO, DIR.ID_PROVINCIA, DIR.ID_MUNICIPIO, DIR.ID_LOCALIDAD, DIR.DIRECCION, DIR.NUMERO, DIR.ESCALERA, DIR.PISO, DIR.LETRA, DIR.CODIGO_POSTAL, DIR.ID_PAIS IDPAIS, DIR.DESCRIPCION_PROVINCIA DESCRIPCIONPROVINCIAEXTR, DIR.DESCRIPCION_CIUDAD DESCRIPCIONCIUDADEXTR, DIR.IDENTIFICADOR_ESTABLECIMIENTO IDENTIFICADORESTABLECIMIENTO, T17.DS_O MUNICIPIODSO FROM AB78.DATOS_DIRECCIONES DIR, AB78.MUNICIPIOS T17, REL_EST_DIR t6346 WHERE DIR.ID_TIPO_DIRECCION = 2 AND DIR.ID_PROVINCIA = T17.PROVINCIA_ID (+) AND DIR.ID_MUNICIPIO = T17.ID (+) AND DIR.ID_DIRECCION = t6346.ID_DIRECCION ) T36 ");

		Map<String, ?> mapaWhere = this.getWhereLikeMap(ab6301s00, startsWith);
		StringBuilder where = new StringBuilder(
				" WHERE 1 = 1 AND t6301.ID_ESTABLECIMIENTO = T36.ID_ESTABLECIMIENTO (+) AND t6301.ID_TIPO_ESTABLECIMIENTO = T6311.ID_TIPO_ESTABLECIMIENTO AND t6301.ID_ESTABLECIMIENTO = VS10.ID_ESTABLECIMIENTO (+) ");
		where.append(mapaWhere.get("query"));
		query.append(where);

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

		return this.jdbcTemplate.queryForObject(query.toString(), Long.class, params.toArray());
	}

	private Map<String, Object> getWhereLikeMap(Establecimiento ab6301s00, Boolean startsWith) {

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

		if (ab6301s00 != null && ab6301s00.getTipoEstablecimiento() != null) {
			where.append(" AND T6311.ID_TIPO_ESTABLECIMIENTO = ?");
			params.add(ab6301s00.getTipoEstablecimiento().getIdTipoEstablecimiento());
		}
		if (ab6301s00 != null && ab6301s00.getDescrNombre() != null) {
			where.append(" AND UPPER(t6301.NOMBRE_COMERCIAL) like ? ESCAPE  '\\'");
			if (startsWith) {
				params.add(ab6301s00.getDescrNombre().toUpperCase() + "%");
			} else {
				params.add("%" + ab6301s00.getDescrNombre().toUpperCase() + "%");
			}
			where.append(" AND t6301.NOMBRE_COMERCIAL IS NOT NULL");
		}
		if (ab6301s00 != null && ab6301s00.getDatosTerceros() != null
				&& ab6301s00.getDatosTerceros().getNombre() != null) {

			where.append(
					" AND UPPER(vs10.NOMBRE || ' ' || vs10.APELLIDO1 || ' ' || vs10.APELLIDO2) LIKE UPPER(?) ESCAPE  '\\'");
			if (startsWith) {
				params.add(ab6301s00.getDatosTerceros().getNombre().toUpperCase() + "%");
			} else {
				params.add("%" + ab6301s00.getDatosTerceros().getNombre().toUpperCase() + "%");
			}
		}
		if (ab6301s00 != null && ab6301s00.getAutocompleteEstablecimiento() != null) {
			where.append(
					" AND UPPER(t6301.IDENTIFICADOR_ESTABLECIMIENTO||' - '||t6301.NOMBRE_COMERCIAL) like UPPER(?) ESCAPE  '\\'");
			if (startsWith) {
				params.add(ab6301s00.getAutocompleteEstablecimiento() + "%");
			} else {
				params.add("%" + ab6301s00.getAutocompleteEstablecimiento() + "%");
			}
			where.append(" AND t6301.IDENTIFICADOR_ESTABLECIMIENTO IS NOT NULL");
		}
		if (ab6301s00 != null && ab6301s00.getDatosDirecciones() != null
				&& ab6301s00.getDatosDirecciones().getIdProvincia() != null) {
			where.append(" AND   t36.ID_PROVINCIA = ?");
			params.add(ab6301s00.getDatosDirecciones().getIdProvincia());
		}

		if (ab6301s00 != null && ab6301s00.getDatosDirecciones() != null
				&& ab6301s00.getDatosDirecciones().getIdMunicipio() != null) {
			where.append(" AND   t36.ID_MUNICIPIO = ?");
			params.add(ab6301s00.getDatosDirecciones().getIdMunicipio());
		}

		if (ab6301s00 != null && ab6301s00.getDatosDirecciones() != null
				&& ab6301s00.getDatosDirecciones().getIdLocalidad() != null) {
			where.append(" AND   t36.ID_LOCALIDAD = ?");
			params.add(ab6301s00.getDatosDirecciones().getIdLocalidad());
		}

		if (ab6301s00 != null && ab6301s00.getDatosDirecciones() != null
				&& ab6301s00.getDatosDirecciones().getNumero() != null) {
			where.append(" AND   t36.NUMERO = ?");
			params.add(ab6301s00.getDatosDirecciones().getNumero());
		}

		if (ab6301s00 != null && ab6301s00.getDatosDirecciones() != null
				&& ab6301s00.getDatosDirecciones().getDireccion() != null) {

			where.append(" AND UPPER(t36.DIRECCION) like UPPER(?) ESCAPE  '\\'");
			if (startsWith) {
				params.add(ab6301s00.getDatosDirecciones().getDireccion().toUpperCase() + "%");
			} else {
				params.add("%" + ab6301s00.getDatosDirecciones().getDireccion().toUpperCase() + "%");
			}
			where.append(" AND t36.DIRECCION IS NOT NULL");

		}
		if (ab6301s00 != null && ab6301s00.getDatosDirecciones() != null
				&& ab6301s00.getDatosDirecciones().getEscalera() != null) {
			where.append(" AND   t36.ESCALERA = ?");
			params.add(ab6301s00.getDatosDirecciones().getEscalera());
		}
		if (ab6301s00 != null && ab6301s00.getDatosDirecciones() != null
				&& ab6301s00.getDatosDirecciones().getPiso() != null) {
			where.append(" AND   t36.PISO = ?");
			params.add(ab6301s00.getDatosDirecciones().getPiso());
		}
		if (ab6301s00 != null && ab6301s00.getDatosDirecciones() != null
				&& ab6301s00.getDatosDirecciones().getLetra() != null) {
			where.append(" AND   t36.LETRA = ?");
			params.add(ab6301s00.getDatosDirecciones().getLetra());
		}
		if (ab6301s00 != null && ab6301s00.getDatosDirecciones() != null
				&& ab6301s00.getDatosDirecciones().getCodigoPostal() != null) {
			where.append(" AND   t36.CODIGO_POSTAL = ?");
			params.add(ab6301s00.getDatosDirecciones().getCodigoPostal());
		}
		if (ab6301s00 != null && ab6301s00.getTipoRegistro() != null) {
			where.append(" AND t6301.TIPO_REGISTRO = ?");
			params.add(ab6301s00.getTipoRegistro());
		}
		if (ab6301s00 != null && ab6301s00.getIdentificadorEstablecimiento() != null) {
			where.append(" AND UPPER(t6301.IDENTIFICADOR_ESTABLECIMIENTO) like UPPER(?)");
			params.add(ab6301s00.getIdentificadorEstablecimiento());
		}

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

		return mapWhere;
	}

}
