package com.ejie.ab78.dao.terceros;

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.comun.Constantes;
import com.ejie.ab78.model.terceros.TiposTercero;
import com.ejie.x38.dto.TableManager;
import com.ejie.x38.dto.TableRequestDto;

/**
 * TiposTerceroDaoImpl  
 * 
 *  
 */

@Repository
@Transactional
public class TiposTerceroDaoImpl implements TiposTerceroDao {

	public static final String[] ORDER_BY_WHITE_LIST = new String[] { "IDTIPOTERCERO", "DESCRIPCIONCASTELLANO",
			"DESCRIPCIONEUSKERA", "FECHAREGISTRO", "USUARIOREGISTRO", "ROLE" };

	private JdbcTemplate jdbcTemplate;

	private RowMapper<TiposTercero> rwMap = new RowMapper<TiposTercero>() {
		public TiposTercero mapRow(ResultSet resultSet, int rowNum) throws SQLException {
			return new TiposTercero(resultSet.getLong("IDTIPOTERCERO"), resultSet.getString("DESCRIPCIONCASTELLANO"),
					resultSet.getString("DESCRIPCIONEUSKERA"), resultSet.getDate("FECHAREGISTRO"),
					resultSet.getString("USUARIOREGISTRO"), resultSet.getString("ROLE"));
		}
	};

	private RowMapper<TiposTercero> rwMapPK = new RowMapper<TiposTercero>() {
		public TiposTercero mapRow(ResultSet resultSet, int rowNum) throws SQLException {
			return new TiposTercero(resultSet.getLong("IDTIPOTERCERO"));
		}
	};

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


	public TiposTercero add(TiposTercero tipostercero) {
		String query = "INSERT INTO AB78.TIPOS_TERCERO (ID_TIPO_TERCERO, DESCRIPCION_CASTELLANO, DESCRIPCION_EUSKERA, FECHA_REGISTRO, USUARIO_REGISTRO) VALUES (?,?,?,?,?)";
		this.jdbcTemplate.update(query, tipostercero.getIdTipoTercero(), tipostercero.getDescripcionCastellano(),
				tipostercero.getDescripcionEuskera(), tipostercero.getFechaRegistro(),
				tipostercero.getUsuarioRegistro());
		return tipostercero;
	}

	public TiposTercero update(TiposTercero tipostercero) {
		String query = "UPDATE AB78.TIPOS_TERCERO SET DESCRIPCION_CASTELLANO=?, DESCRIPCION_EUSKERA=?, FECHA_REGISTRO=?, USUARIO_REGISTRO=? WHERE ID_TIPO_TERCERO=?";
		this.jdbcTemplate.update(query, tipostercero.getDescripcionCastellano(), tipostercero.getDescripcionEuskera(),
				tipostercero.getFechaRegistro(), tipostercero.getUsuarioRegistro(), tipostercero.getIdTipoTercero());
		return tipostercero;
	}

	@Transactional(readOnly = true)
	public TiposTercero find(TiposTercero tipostercero) {
		String query = "SELECT t1.ID_TIPO_TERCERO IDTIPOTERCERO, t1.DESCRIPCION_CASTELLANO DESCRIPCIONCASTELLANO, t1.DESCRIPCION_EUSKERA DESCRIPCIONEUSKERA, t1.FECHA_REGISTRO FECHAREGISTRO, t1.USUARIO_REGISTRO USUARIOREGISTRO FROM AB78.TIPOS_TERCERO t1  WHERE t1.ID_TIPO_TERCERO = ?  ";

		List<TiposTercero> tiposterceroList = this.jdbcTemplate.query(query, this.rwMap,
				tipostercero.getIdTipoTercero());
		return DataAccessUtils.uniqueResult(tiposterceroList);
	}

	@Transactional(readOnly = true)
	public TiposTercero findIdTipoTercero(String role) {
		String query = "SELECT t1.ID_TIPO_TERCERO IDTIPOTERCERO FROM AB78.TIPOS_TERCERO t1  WHERE t1.ROLE = ?  ";

		List<TiposTercero> tiposterceroList = this.jdbcTemplate.query(query, this.rwMapPK, role);
		return DataAccessUtils.uniqueResult(tiposterceroList);
	}

	public void remove(TiposTercero tipostercero) {
		String query = "DELETE FROM AB78.TIPOS_TERCERO WHERE ID_TIPO_TERCERO=?";
		this.jdbcTemplate.update(query, tipostercero.getIdTipoTercero());
	}

	@Transactional(readOnly = true)
	public List<TiposTercero> findAll(TiposTercero tipostercero, TableRequestDto TableRequestDto) {
		StringBuilder query = new StringBuilder(
				"SELECT  t1.ID_TIPO_TERCERO IDTIPOTERCERO,t1.DESCRIPCION_CASTELLANO DESCRIPCIONCASTELLANO,t1.DESCRIPCION_EUSKERA DESCRIPCIONEUSKERA,t1.FECHA_REGISTRO FECHAREGISTRO,t1.USUARIO_REGISTRO USUARIOREGISTRO, t1.ROLE ROLE ");
		query.append("FROM AB78.TIPOS_TERCERO t1 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMap(tipostercero);
		StringBuilder where = new StringBuilder(" WHERE 1=1 AND t1.ID_TIPO_TERCERO IN (");
		where.append(Constantes.ID_TIPO_TERCERO_SOLICITANTE).append(", ");
		where.append(Constantes.ID_TIPO_TERCERO_AFECTADO).append(", ");
		where.append(Constantes.ID_TIPO_TERCERO_DENUNCIADO).append(") ");
		where.append(mapaWhere.get("query"));
		query.append(where);

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

		if (TableRequestDto != null) {
			query = TableManager.getPaginationQuery(TableRequestDto, query, TiposTerceroDaoImpl.ORDER_BY_WHITE_LIST);
		}

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

	@Transactional(readOnly = true)
	public List<TiposTercero> findAllLike(TiposTercero tipostercero, TableRequestDto TableRequestDto,
			Boolean startsWith) {
		StringBuilder query = new StringBuilder(
				"SELECT  t1.ID_TIPO_TERCERO IDTIPOTERCERO,t1.DESCRIPCION_CASTELLANO DESCRIPCIONCASTELLANO,t1.DESCRIPCION_EUSKERA DESCRIPCIONEUSKERA,t1.FECHA_REGISTRO FECHAREGISTRO,t1.USUARIO_REGISTRO USUARIOREGISTRO ");
		query.append("FROM AB78.TIPOS_TERCERO t1 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereLikeMap(tipostercero, startsWith);
		StringBuilder where = new StringBuilder(" WHERE 1=1 ");
		where.append(mapaWhere.get("query"));
		query.append(where);

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

		if (TableRequestDto != null) {
			query = TableManager.getPaginationQuery(TableRequestDto, query, TiposTerceroDaoImpl.ORDER_BY_WHITE_LIST);
		}

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

	@Transactional(readOnly = true)
	public Long findAllCount(TiposTercero tipostercero) {
		StringBuilder query = new StringBuilder("SELECT COUNT(1) FROM AB78.TIPOS_TERCERO t1 ");

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

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

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

	@Transactional(readOnly = true)
	public Long findAllLikeCount(TiposTercero tipostercero, Boolean startsWith) {
		StringBuilder query = new StringBuilder("SELECT COUNT(1) FROM AB78.TIPOS_TERCERO t1 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereLikeMap(tipostercero, startsWith);
		StringBuilder where = new StringBuilder(" WHERE 1=1 ");
		where.append(mapaWhere.get("query"));
		query.append(where);

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

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

	private Map<String, ?> getWhereMap(TiposTercero tipostercero) {

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

		if (tipostercero != null && tipostercero.getIdTipoTercero() != null) {
			where.append(" AND t1.ID_TIPO_TERCERO = ?");
			params.add(tipostercero.getIdTipoTercero());
		}
		if (tipostercero != null && tipostercero.getDescripcionCastellano() != null) {
			where.append(" AND t1.DESCRIPCION_CASTELLANO = ?");
			params.add(tipostercero.getDescripcionCastellano());
		}
		if (tipostercero != null && tipostercero.getDescripcionEuskera() != null) {
			where.append(" AND t1.DESCRIPCION_EUSKERA = ?");
			params.add(tipostercero.getDescripcionEuskera());
		}
		if (tipostercero != null && tipostercero.getFechaRegistro() != null) {
			where.append(" AND t1.FECHA_REGISTRO = ?");
			params.add(tipostercero.getFechaRegistro());
		}
		if (tipostercero != null && tipostercero.getUsuarioRegistro() != null) {
			where.append(" AND t1.USUARIO_REGISTRO = ?");
			params.add(tipostercero.getUsuarioRegistro());
		}

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

		return mapWhere;
	}

	private Map<String, Object> getWhereLikeMap(TiposTercero tipostercero, Boolean startsWith) {

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

		if (tipostercero != null && tipostercero.getIdTipoTercero() != null) {
			where.append(" AND t1.ID_TIPO_TERCERO = ?");
			params.add(tipostercero.getIdTipoTercero());
		}
		if (tipostercero != null && tipostercero.getDescripcionCastellano() != null) {
			where.append(" AND UPPER(t1.DESCRIPCION_CASTELLANO) like ? ESCAPE  '\\'");
			if (startsWith) {
				params.add(tipostercero.getDescripcionCastellano().toUpperCase() + "%");
			} else {
				params.add("%" + tipostercero.getDescripcionCastellano().toUpperCase() + "%");
			}
			where.append(" AND t1.DESCRIPCION_CASTELLANO IS NOT NULL");
		}
		if (tipostercero != null && tipostercero.getDescripcionEuskera() != null) {
			where.append(" AND UPPER(t1.DESCRIPCION_EUSKERA) like ? ESCAPE  '\\'");
			if (startsWith) {
				params.add(tipostercero.getDescripcionEuskera().toUpperCase() + "%");
			} else {
				params.add("%" + tipostercero.getDescripcionEuskera().toUpperCase() + "%");
			}
			where.append(" AND t1.DESCRIPCION_EUSKERA IS NOT NULL");
		}
		if (tipostercero != null && tipostercero.getFechaRegistro() != null) {
			where.append(" AND t1.FECHA_REGISTRO = ?");
			params.add(tipostercero.getFechaRegistro());
		}
		if (tipostercero != null && tipostercero.getUsuarioRegistro() != null) {
			where.append(" AND UPPER(t1.USUARIO_REGISTRO) like ? ESCAPE  '\\'");
			if (startsWith) {
				params.add(tipostercero.getUsuarioRegistro().toUpperCase() + "%");
			} else {
				params.add("%" + tipostercero.getUsuarioRegistro().toUpperCase() + "%");
			}
			where.append(" AND t1.USUARIO_REGISTRO 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;

	@Override
	public List<TiposTercero> getSubtiposAll(TiposTercero tiposTercero) {
		StringBuilder query = new StringBuilder(
				"SELECT T1.ID_SUBTIPO_TERCERO IDTIPOTERCERO, T1.DESCRIPCION_CASTELLANO DESCRIPCIONCASTELLANO, T1.DESCRIPCION_EUSKERA DESCRIPCIONEUSKERA, T1.FECHA_REGISTRO FECHAREGISTRO, T1.USUARIO_REGISTRO USUARIOREGISTRO, NULL ROLE FROM AB78.SUBTIPOS_TERCERO T1 ");
		return (List<TiposTercero>) this.jdbcTemplate.query(query.toString(), this.rwMap);
	}
}
