package com.ejie.ab78.dao.denuncias;

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

import com.ejie.ab78.model.InfoEstablecimiento;
import com.ejie.x38.dto.TableManager;
import com.ejie.x38.dto.TableRequestDto;

/**
 * DenunciasDaoImpl  
 * 
 *  
 */

@Repository
@Transactional
public class InfoEstablecimientosDaoImpl implements InfoEstablecimientosDao {

	public static final String[] ORDER_BY_WHITE_LIST = new String[] { "IDESTABLECIMIENTO",
			"IDENTIFICADORESTABLECIMIENTO", "NOMBREESTABLECIMIENTO", "IDTERCERO", "NOMBRE", "APELLIDO1", "APELLIDO2",
			"DOCUMENTO" };

	private JdbcTemplate jdbcTemplate;

	/*
	 * ROW_MAPPERS
	 */
	private RowMapper<InfoEstablecimiento> rwMap = new RowMapper<InfoEstablecimiento>() {
		public InfoEstablecimiento mapRow(ResultSet resultSet, int rowNum) throws SQLException {
			return new InfoEstablecimiento(resultSet.getLong("IDESTABLECIMIENTO"),
					resultSet.getString("IDENTIFICADORESTABLECIMIENTO"), resultSet.getString("NOMBREESTABLECIMIENTO"),
					resultSet.getInt("IDTERCERO"), resultSet.getString("NOMBRE"), resultSet.getString("APELLIDO1"),
					resultSet.getString("APELLIDO2"), resultSet.getString("DOCUMENTO"));
		}
	};

	@Resource
	public void setDataSource(DataSource dataSource) {
		this.jdbcTemplate = new JdbcTemplate(dataSource);
	}

	@Transactional(readOnly = true)
	public InfoEstablecimiento find(InfoEstablecimiento infoEstablecimiento) {
		String query = "SELECT t6301.ID_ESTABLECIMIENTO IDESTABLECIMIENTO, t6301.NOMBRE_COMERCIAL NOMBREESTABLECIMIENTO, t6301.IDENTIFICADOR_ESTABLECIMIENTO IDENTIFICADORESTABLECIMIENTO, "
				+ " t6135.ID_TERCERO IDTERCERO, t6339.ID_TIPO_TERCERO TIPOTERCERO, t6135.NOMBRE NOMBRE, t6135.APELLIDO1 APELLIDO1, t6135.APELLIDO2 APELLIDO2, t6135.DOCUMENTO DOCUMENTO "
				+ " FROM ESTABLECIMIENTOS_REGISTRADOS t6301, REL_EST_TER t6339, DATOS_TERCERO t6135 "
				+ " WHERE t6301.ID_ESTABLECIMIENTO = t6339.ID_ESTABLECIMIENTO(+) AND t6339.ID_TERCERO = t6135.ID_TERCERO (+) "
				+ " AND t6339.ID_TIPO_TERCERO (+)= 9 AND t6301.tipo_registro = 'D' AND t6301.ID_ESTABLECIMIENTO = ? ";

		List<InfoEstablecimiento> infoEstablecimientoList = this.jdbcTemplate.query(query, this.rwMap,
				infoEstablecimiento.getIdEstablecimiento());
		return DataAccessUtils.uniqueResult(infoEstablecimientoList);
	}

	@Transactional(readOnly = true)
	public InfoEstablecimiento findByIdentificadorEstablecimiento(InfoEstablecimiento infoEstablecimiento) {
		String query = "SELECT t6301.ID_ESTABLECIMIENTO IDESTABLECIMIENTO, t6301.NOMBRE_COMERCIAL NOMBREESTABLECIMIENTO, t6301.IDENTIFICADOR_ESTABLECIMIENTO IDENTIFICADORESTABLECIMIENTO, "
				+ " t6135.ID_TERCERO IDTERCERO, t6339.ID_TIPO_TERCERO TIPOTERCERO, t6135.NOMBRE NOMBRE, t6135.APELLIDO1 APELLIDO1, t6135.APELLIDO2 APELLIDO2, t6135.DOCUMENTO DOCUMENTO "
				+ " FROM ESTABLECIMIENTOS_REGISTRADOS t6301, REL_EST_TER t6339, DATOS_TERCERO t6135 "
				+ " WHERE t6301.ID_ESTABLECIMIENTO = t6339.ID_ESTABLECIMIENTO(+) AND t6339.ID_TERCERO = t6135.ID_TERCERO (+) "
				+ " AND t6339.ID_TIPO_TERCERO (+)= 9 AND t6301.tipo_registro = 'D' AND t6301.IDENTIFICADOR_ESTABLECIMIENTO = ?";

		List<InfoEstablecimiento> infoEstablecimientoList = this.jdbcTemplate.query(query, this.rwMap,
				infoEstablecimiento.getIdentificadorEstablecimiento());
		if (infoEstablecimientoList.isEmpty()) {
			return infoEstablecimiento;
		}
		return DataAccessUtils.uniqueResult(infoEstablecimientoList);
	}

	@Transactional(readOnly = true)
	public List<InfoEstablecimiento> findAll(InfoEstablecimiento infoEstablecimiento, TableRequestDto tableRequestDto) {
		StringBuilder query = new StringBuilder(
				"SELECT t6301.ID_ESTABLECIMIENTO IDESTABLECIMIENTO, t6301.NOMBRE_COMERCIAL NOMBREESTABLECIMIENTO, t6301.IDENTIFICADOR_ESTABLECIMIENTO IDENTIFICADORESTABLECIMIENTO, "
				+ " t6135.ID_TERCERO IDTERCERO, t6339.ID_TIPO_TERCERO TIPOTERCERO, t6135.NOMBRE NOMBRE, t6135.APELLIDO1 APELLIDO1, t6135.APELLIDO2 APELLIDO2, t6135.DOCUMENTO DOCUMENTO ");
		query.append(" FROM ESTABLECIMIENTOS_REGISTRADOS t6301, REL_EST_TER t6339, DATOS_TERCERO t6135 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMap(infoEstablecimiento);
		StringBuilder where = new StringBuilder(
				" WHERE t6301.ID_ESTABLECIMIENTO = t6339.ID_ESTABLECIMIENTO(+) AND t6339.ID_TERCERO = t6135.ID_TERCERO (+) AND t6339.ID_TIPO_TERCERO (+)= 9  AND t6301.tipo_registro = 'D' ");
		where.append(mapaWhere.get("query"));
		query.append(where);

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

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

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

	@Transactional(readOnly = true)
	public List<InfoEstablecimiento> findAllLike(InfoEstablecimiento infoEstablecimiento,
			TableRequestDto tableRequestDto, Boolean startsWith) {
		StringBuilder query = new StringBuilder(
				"SELECT t6301.ID_ESTABLECIMIENTO IDESTABLECIMIENTO, t6301.NOMBRE_COMERCIAL NOMBREESTABLECIMIENTO, t6301.IDENTIFICADOR_ESTABLECIMIENTO IDENTIFICADORESTABLECIMIENTO, "
				+ " t6135.ID_TERCERO IDTERCERO, t6339.ID_TIPO_TERCERO TIPOTERCERO, t6135.NOMBRE NOMBRE, t6135.APELLIDO1 APELLIDO1, t6135.APELLIDO2 APELLIDO2, t6135.DOCUMENTO DOCUMENTO ");
		query.append(" FROM ESTABLECIMIENTOS_REGISTRADOS t6301, REL_EST_TER t6339, DATOS_TERCERO t6135 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereLikeMap(infoEstablecimiento, startsWith);
		StringBuilder where = new StringBuilder(
				" WHERE t6301.ID_ESTABLECIMIENTO = t6339.ID_ESTABLECIMIENTO(+) AND t6339.ID_TERCERO = t6135.ID_TERCERO (+) AND t6339.ID_TIPO_TERCERO (+)= 9 AND t6301.tipo_registro = 'D'");
		where.append(mapaWhere.get("query"));
		query.append(where);

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

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

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

	@Transactional(readOnly = true)
	public Long findAllCount(InfoEstablecimiento infoEstablecimiento) {
		StringBuilder query = new StringBuilder(
				"SELECT COUNT(1) FROM ESTABLECIMIENTOS_REGISTRADOS t6301, REL_EST_TER t6339, DATOS_TERCERO t6135 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMap(infoEstablecimiento);
		StringBuilder where = new StringBuilder(
				" WHERE t6301.ID_ESTABLECIMIENTO = t6339.ID_ESTABLECIMIENTO(+) AND t6339.ID_TERCERO = t6135.ID_TERCERO (+) AND t6339.ID_TIPO_TERCERO (+)= 9 AND t6301.tipo_registro = 'D' ");
		where.append(mapaWhere.get("query"));
		query.append(where);

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

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

	@Transactional(readOnly = true)
	public Long findAllLikeCount(InfoEstablecimiento infoEstablecimiento, Boolean startsWith) {
		StringBuilder query = new StringBuilder(
				"SELECT COUNT(1) FROM ESTABLECIMIENTOS_REGISTRADOS t6301, REL_EST_TER t6339, DATOS_TERCERO t6135 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereLikeMap(infoEstablecimiento, startsWith);
		StringBuilder where = new StringBuilder(
				" WHERE t6301.ID_ESTABLECIMIENTO = t6339.ID_ESTABLECIMIENTO(+) AND t6339.ID_TERCERO = t6135.ID_TERCERO (+) AND t6339.ID_TIPO_TERCERO (+)= 9 AND t6301.tipo_registro = 'D' ");
		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, ?> getWhereMap(InfoEstablecimiento infoEstablecimiento) {

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

		if (infoEstablecimiento != null && infoEstablecimiento.getIdEstablecimiento() != null) {
			where.append(" AND t6301.ID_ESTABLECIMIENTO = ?");
			params.add(infoEstablecimiento.getIdEstablecimiento());
		}
		if (infoEstablecimiento != null && infoEstablecimiento.getIdentificadorEstablecimiento() != null) {
			where.append(" AND t6301.IDENTIFICADOR_ESTABLECIMIENTO = ?");
			params.add(infoEstablecimiento.getIdentificadorEstablecimiento());
		}
		if (infoEstablecimiento != null && infoEstablecimiento.getNombreEstablecimiento() != null) {
			where.append(" AND t6301.NOMBRE_COMERCIAL = ?");
			params.add(infoEstablecimiento.getNombreEstablecimiento());
		}

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

		return mapWhere;
	}
	
	private Map<String, Object> getWhereLikeMap(InfoEstablecimiento infoEstablecimiento, Boolean startsWith) {

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

		if (infoEstablecimiento != null && infoEstablecimiento.getIdentificadorEstablecimiento() != null) {
			where.append(" AND UPPER(t6301.IDENTIFICADOR_ESTABLECIMIENTO) like ? ESCAPE  '\\'");
			if (startsWith) {
				params.add(infoEstablecimiento.getIdentificadorEstablecimiento() + "%");
			} else {
				params.add("%" + infoEstablecimiento.getIdentificadorEstablecimiento() + "%");
			}
			where.append(" AND t6301.IDENTIFICADOR_ESTABLECIMIENTO IS NOT NULL");
		}
		if (infoEstablecimiento != null && infoEstablecimiento.getNombreEstablecimiento() != null) {
			where.append(" AND UPPER(t6301.NOMBRE_COMERCIAL) like ? ESCAPE  '\\'");
			if (startsWith) {
				params.add(infoEstablecimiento.getNombreEstablecimiento().toUpperCase() + "%");
			} else {
				params.add("%" + infoEstablecimiento.getNombreEstablecimiento().toUpperCase() + "%");
			}
			where.append(" AND t6301.NOMBRE_COMERCIAL IS NOT NULL");
		}

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

		return mapWhere;
	}

	public static final int STRING_BUILDER_INIT = 4096;
}
