package com.ejie.aa20b.dao;

import com.ejie.x38.dto.Pagination;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
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.aa20b.model.Direcciones;

/**
 * DireccionesDaoImpl generated by UDA, 28-nov-2014 11:32:16.
 * 
 * @author UDA
 */

@Repository
@Transactional
public class DireccionesDaoImpl implements DireccionesDao {
	private JdbcTemplate jdbcTemplate;
	private RowMapper<Direcciones> rwMap = new RowMapper<Direcciones>() {
		public Direcciones mapRow(ResultSet resultSet, int rowNum)
				throws SQLException {
			return new Direcciones(resultSet.getInt("IDDIR"),
					resultSet.getString("CDIR"), resultSet.getLong("IDDEPAR"),
					resultSet.getString("EDIR"),
					resultSet.getString("CODESTRUS"),
					resultSet.getString("BAJA"), resultSet.getDate("FEINI"),
					resultSet.getString("CIDIR"));
		}
	};

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

	/**
	 * Inserts a single row in the Direcciones table.
	 * 
	 * @param direcciones
	 *            Pagination
	 * @return Direcciones
	 */
	public Direcciones add(Direcciones direcciones) {

		final Integer nextId = this.jdbcTemplate
				.queryForInt("SELECT DIRECCION_SEQ.NEXTVAL FROM DUAL");

		direcciones.setIddir(nextId);

		String query = "INSERT INTO DIRECCIONES (IDDIR, CDIR, IDDEPAR, EDIR, CODESTR_US, BAJA, FEINI, CIDIR) VALUES (?,?,?,?,?,?,?,?)";
		String cdirecc = direcciones.getCdir();
		if (cdirecc.length() > 50) {
			cdirecc = cdirecc.substring(0, 49);
		}
		String edirecc = direcciones.getEdir();
		if (edirecc.length() > 50) {
			edirecc = edirecc.substring(0, 49);
		}

		this.jdbcTemplate.update(query, direcciones.getIddir(), cdirecc,
				direcciones.getIddepar(), edirecc, direcciones.getCodestrUs(),
				direcciones.getBaja() == null ? "0" : direcciones.getBaja(),
				direcciones.getFeini(), direcciones.getCidir());
		return direcciones;
	}

	/**
	 * Si no existe la Direccion la da de alta.
	 * 
	 * @param direccion
	 *            String
	 * @return Boolean
	 */
	@Transactional(readOnly = true)
	public Boolean altaExisteDireccion(Direcciones direccion) {

		boolean altaExisteDireccion = false;
		Direcciones direccionAux = new Direcciones();

		direccionAux.setCidir(direccion.getCidir());

		List<Direcciones> listaDirecciones = this.findAll(direccionAux, null);

		if (listaDirecciones.size() == 0) { // No existe el código de
											// Direccion
			// Darlo de alta en la tabla de Direcciones
			direccion.setFeini(new Date());
			direccion.setBaja("0");
			this.add(direccion);

		} else if (listaDirecciones.get(0).getBaja().equalsIgnoreCase("1")) {
			// la direccion está de baja. Se pone de alta
			this.updateAlta(direccion);
		}
		altaExisteDireccion = true;

		return altaExisteDireccion;
	}

	/**
	 * Poner la Direccion de alta.
	 * 
	 * @param direccion
	 *            Pagination
	 * @return Departamentos
	 */
	public Direcciones updateAlta(Direcciones direccion) {
		String query = "UPDATE DIRECCIONES SET BAJA='0' WHERE IDDIR=? ";
		this.jdbcTemplate.update(query, direccion.getIddepar());
		return direccion;
	}

	/**
	 * Updates a single row in the Direcciones table.
	 * 
	 * @param direcciones
	 *            Pagination
	 * @return Direcciones
	 */
	public Direcciones update(Direcciones direcciones) {
		String query = "UPDATE DIRECCIONES SET CDIR=?, IDDEPAR=?, EDIR=?, CODESTR_US=?, BAJA=?, FEINI=?, CIDIR=? WHERE IDDIR=?";
		this.jdbcTemplate.update(query, direcciones.getCdir(), direcciones
				.getIddepar(), direcciones.getEdir(), direcciones
				.getCodestrUs(), direcciones.getBaja() == null ? "0"
				: direcciones.getBaja(), direcciones.getFeini(), direcciones
				.getCidir(), direcciones.getIddir());
		return direcciones;
	}

	/**
	 * Dar de baja el dpto.
	 * 
	 * @param direcciones
	 *            Direcciones
	 * @return Direcciones
	 */
	public Direcciones darBajaDirecc(Direcciones direcciones) {
		String query = "UPDATE DIRECCIONES SET BAJA='1' WHERE IDDIR=?";
		this.jdbcTemplate.update(query, direcciones.getIddir());
		return direcciones;
	}

	/**
	 * Finds a single row in the Direcciones table.
	 * 
	 * @param direcciones
	 *            Pagination
	 * @return Direcciones
	 */
	@Transactional(readOnly = true)
	public Direcciones find(Direcciones direcciones) {
		String query = "SELECT t1.IDDIR IDDIR, t1.CDIR CDIR, t1.IDDEPAR IDDEPAR, t1.EDIR EDIR, t1.CODESTR_US CODESTRUS, t1.BAJA BAJA, t1.FEINI FEINI, t1.CIDIR CIDIR FROM DIRECCIONES t1  WHERE t1.IDDIR = ?  ";

		List<Direcciones> direccionesList = this.jdbcTemplate.query(query,
				this.rwMap, direcciones.getIddir());
		return (Direcciones) DataAccessUtils.uniqueResult(direccionesList);
	}

	/**
	 * Removes a single row in the Direcciones table.
	 * 
	 * @param direcciones
	 *            Pagination
	 * @return
	 */
	public void remove(Direcciones direcciones) {
		String query = "DELETE FROM DIRECCIONES WHERE IDDIR=?";
		this.jdbcTemplate.update(query, direcciones.getIddir());
	}

	/**
	 * Finds a List of rows in the Direcciones table.
	 * 
	 * @param direcciones
	 *            Direcciones
	 * @param pagination
	 *            Pagination
	 * @return List
	 */
	@Transactional(readOnly = true)
	public List<Direcciones> findAll(Direcciones direcciones,
			Pagination pagination) {
		StringBuilder query = new StringBuilder(
				"SELECT  t1.IDDIR IDDIR,t1.CDIR CDIR,t1.IDDEPAR IDDEPAR,t1.EDIR EDIR,t1.CODESTR_US CODESTRUS,t1.BAJA BAJA,t1.FEINI FEINI,t1.CIDIR CIDIR ");
		query.append("FROM DIRECCIONES t1 ");

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

		query.append(" ORDER BY t1.BAJA, CODESTR_US");

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

		if (pagination != null) {
			query = pagination.getPaginationQuery(query);
		}

		return (List<Direcciones>) this.jdbcTemplate.query(query.toString(),
				this.rwMap, params.toArray());
	}

	@Transactional(readOnly = true)
	public List<Direcciones> findAllCargaGmao(Direcciones direcciones,
			Pagination pagination) {
		StringBuilder query = new StringBuilder(
				"SELECT  t1.IDDIR IDDIR,t1.CDIR CDIR,t1.IDDEPAR IDDEPAR,t1.EDIR EDIR,t1.CODESTR_US CODESTRUS,t1.BAJA BAJA,t1.FEINI FEINI,t1.CIDIR CIDIR ");
		query.append("FROM DIRECCIONES t1 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMap(direcciones);
		StringBuilder where = new StringBuilder(
				" WHERE 1=1 AND FEINI > '25/11/2014' ");
		where.append(mapaWhere.get("query"));
		query.append(where);

		query.append(" ORDER BY t1.BAJA, CODESTR_US");

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

		if (pagination != null) {
			query = pagination.getPaginationQuery(query);
		}

		return (List<Direcciones>) this.jdbcTemplate.query(query.toString(),
				this.rwMap, params.toArray());
	}

	/**
	 * Obtener Direcciones asociadas a un Dpto (por cidepar).
	 * 
	 * @param cidepar
	 *            String
	 * @return List
	 */
	@Transactional(readOnly = true)
	public List<Direcciones> obtenerDireccionesDpto(String cidepar) {

		StringBuilder query = new StringBuilder(
				"SELECT t1.IDDIR IDDIR,  t1.CDIR CDIR,   t1.IDDEPAR IDDEPAR, t1.EDIR EDIR, t1.CODESTR_US CODESTRUS, t1.BAJA BAJA, t1.FEINI FEINI, t1.CIDIR CIDIR ");
		query.append(" FROM DIRECCIONES t1 WHERE t1.BAJA='0' AND t1.IDDEPAR in (select t2.iddepar from DEPARTAMENTOS t2 WHERE t2.cidepar=? AND t2.BAJA='0') ");

		return (List<Direcciones>) this.jdbcTemplate.query(query.toString(),
				this.rwMap, cidepar);
	}

	/**
	 * Finds a List of rows in the Direcciones table.
	 * 
	 * @param direcciones
	 *            Direcciones
	 * @param pagination
	 *            Pagination
	 * @return List
	 */
	@Transactional(readOnly = true)
	public List<Direcciones> findAllFormateado(Direcciones direcciones,
			Pagination pagination) {
		StringBuilder query = new StringBuilder("SELECT  t1.IDDIR IDDIR, ");
		query.append(" CASE WHEN SUBSTR(t1.CODESTR_US,1,2)||'000000' = t1.CODESTR_US THEN decode(baja, '1', '(baja) '||t1.CDIR,  t1.CDIR) ");
		query.append(" WHEN SUBSTR(t1.CODESTR_US,1,4)||'0000' = t1.CODESTR_US THEN '..'||decode(baja, '1', '(baja) '||t1.CDIR,  t1.CDIR) ELSE '......'||decode(baja, '1', '(baja) '||t1.CDIR,  t1.CDIR) END AS CDIR, ");
		query.append(" CASE WHEN SUBSTR(t1.CODESTR_US,1,2)||'000000' = t1.CODESTR_US THEN decode(baja, '1', '(baja) '||t1.EDIR,  t1.EDIR) ");
		query.append(" WHEN SUBSTR(t1.CODESTR_US,1,4)||'0000' = t1.CODESTR_US THEN '..'||decode(baja, '1', '(baja) '||t1.EDIR,  t1.EDIR) ELSE '......'||decode(baja, '1', '(baja) '||t1.EDIR,  t1.EDIR) END AS EDIR, ");
		query.append(" t1.IDDEPAR IDDEPAR,t1.CODESTR_US CODESTRUS,t1.BAJA BAJA,t1.FEINI FEINI,t1.CIDIR CIDIR ");
		query.append("FROM DIRECCIONES t1 ");

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

		query.append(" ORDER BY t1.BAJA, CODESTR_US");

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

		if (pagination != null) {
			query = pagination.getPaginationQuery(query);
		}

		return (List<Direcciones>) this.jdbcTemplate.query(query.toString(),
				this.rwMap, params.toArray());
	}

	/**
	 * Counts rows in the Direcciones table.
	 * 
	 * @param direcciones
	 *            Direcciones
	 * @return Long
	 */
	@Transactional(readOnly = true)
	public Long findAllCount(Direcciones direcciones) {
		StringBuilder query = new StringBuilder(
				"SELECT COUNT(1) FROM DIRECCIONES t1 ");

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

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

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

	/**
	 * Finds rows in the Direcciones table using like.
	 * 
	 * @param direcciones
	 *            Direcciones
	 * @param pagination
	 *            Pagination
	 * @param startsWith
	 *            Boolean
	 * @return List
	 */
	@Transactional(readOnly = true)
	public List<Direcciones> findAllLike(Direcciones direcciones,
			Pagination pagination, Boolean startsWith) {
		StringBuilder query = new StringBuilder(
				"SELECT  t1.IDDIR IDDIR,t1.CDIR CDIR,t1.IDDEPAR IDDEPAR,t1.EDIR EDIR,t1.CODESTR_US CODESTRUS,t1.BAJA BAJA,t1.FEINI FEINI,t1.CIDIR CIDIR ");
		query.append("FROM DIRECCIONES t1 ");

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

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

		if (pagination != null) {
			query = pagination.getPaginationQuery(query);
		}

		return (List<Direcciones>) this.jdbcTemplate.query(query.toString(),
				this.rwMap, params.toArray());
	}

	/**
	 * Counts rows in the Direcciones table using like.
	 * 
	 * @param direcciones
	 *            Direcciones
	 * @param startsWith
	 *            Boolean
	 * @return Long
	 */
	@Transactional(readOnly = true)
	public Long findAllLikeCount(Direcciones direcciones, Boolean startsWith) {
		StringBuilder query = new StringBuilder(
				"SELECT COUNT(1) FROM DIRECCIONES t1 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this
				.getWhereLikeMap(direcciones, 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.queryForLong(query.toString(),
				params.toArray());
	}

	/**
	 * Returns a map with the needed value to create the conditions to filter by
	 * the Direcciones entity
	 * 
	 * @param direcciones
	 *            Direcciones 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.
	 */
	// CHECKSTYLE:OFF CyclomaticComplexity - Generación de código de UDA
	private Map<String, ?> getWhereMap(Direcciones direcciones) {

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

		if (direcciones != null && direcciones.getIddir() != null) {
			where.append(" AND t1.IDDIR = ?");
			params.add(direcciones.getIddir());
		}
		if (direcciones != null && direcciones.getCdir() != null) {
			where.append(" AND t1.CDIR = ?");
			params.add(direcciones.getCdir());
		}
		if (direcciones != null && direcciones.getIddepar() != null) {
			where.append(" AND t1.IDDEPAR = ?");
			params.add(direcciones.getIddepar());
		}
		if (direcciones != null && direcciones.getEdir() != null) {
			where.append(" AND t1.EDIR = ?");
			params.add(direcciones.getEdir());
		}
		if (direcciones != null && direcciones.getCodestrUs() != null) {
			where.append(" AND t1.CODESTR_US = ?");
			params.add(direcciones.getCodestrUs());
		}
		if (direcciones != null && direcciones.getBaja() != null) {
			where.append(" AND t1.BAJA = ?");
			params.add(direcciones.getBaja());
		}
		if (direcciones != null && direcciones.getFeini() != null) {
			where.append(" AND t1.FEINI = ?");
			params.add(direcciones.getFeini());
		}
		if (direcciones != null && direcciones.getCidir() != null) {
			where.append(" AND t1.CIDIR = ?");
			params.add(direcciones.getCidir());
		}

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

		return mapWhere;
	}

	// CHECKSTYLE:ON CyclomaticComplexity - Generación de código de UDA

	/**
	 * Returns a map with the needed value to create the conditions to filter by
	 * the Direcciones entity
	 * 
	 * @param direcciones
	 *            Direcciones Bean with the criteria values to filter by.
	 * @param startsWith
	 *            Boolean
	 * @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.
	 */
	// CHECKSTYLE:OFF CyclomaticComplexity - Generación de código de UDA
	private Map<String, ?> getWhereLikeMap(Direcciones direcciones,
			Boolean startsWith) {

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

		if (direcciones != null && direcciones.getIddir() != null) {
			where.append(" AND t1.IDDIR = ?");
			params.add(direcciones.getIddir());
		}
		if (direcciones != null && direcciones.getCdir() != null) {
			where.append(" AND UPPER(t1.CDIR) like ? ESCAPE  '\\'");
			if (startsWith) {
				params.add(direcciones.getCdir().toUpperCase() + "%");
			} else {
				params.add("%" + direcciones.getCdir().toUpperCase() + "%");
			}
			where.append(" AND t1.CDIR IS NOT NULL");
		}
		if (direcciones != null && direcciones.getIddepar() != null) {
			where.append(" AND t1.IDDEPAR = ?");
			params.add(direcciones.getIddepar());
		}
		if (direcciones != null && direcciones.getEdir() != null) {
			where.append(" AND UPPER(t1.EDIR) like ? ESCAPE  '\\'");
			if (startsWith) {
				params.add(direcciones.getEdir().toUpperCase() + "%");
			} else {
				params.add("%" + direcciones.getEdir().toUpperCase() + "%");
			}
			where.append(" AND t1.EDIR IS NOT NULL");
		}
		if (direcciones != null && direcciones.getCodestrUs() != null) {
			where.append(" AND UPPER(t1.CODESTR_US) like ? ESCAPE  '\\'");
			if (startsWith) {
				params.add(direcciones.getCodestrUs().toUpperCase() + "%");
			} else {
				params.add("%" + direcciones.getCodestrUs().toUpperCase() + "%");
			}
			where.append(" AND t1.CODESTR_US IS NOT NULL");
		}
		if (direcciones != null && direcciones.getBaja() != null) {
			where.append(" AND UPPER(t1.BAJA) like ? ESCAPE  '\\'");
			if (startsWith) {
				params.add(direcciones.getBaja().toUpperCase() + "%");
			} else {
				params.add("%" + direcciones.getBaja().toUpperCase() + "%");
			}
			where.append(" AND t1.BAJA IS NOT NULL");
		}
		if (direcciones != null && direcciones.getFeini() != null) {
			where.append(" AND t1.FEINI = ?");
			params.add(direcciones.getFeini());
		}
		if (direcciones != null && direcciones.getCidir() != null) {
			where.append(" AND UPPER(t1.CIDIR) like ? ESCAPE  '\\'");
			if (startsWith) {
				params.add(direcciones.getCidir().toUpperCase() + "%");
			} else {
				params.add("%" + direcciones.getCidir().toUpperCase() + "%");
			}
			where.append(" AND t1.CIDIR IS NOT NULL");
		}

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

		return mapWhere;
	}

	// CHECKSTYLE:ON CyclomaticComplexity - Generación de código de UDA

	/**
	 * StringBuilder initilization value
	 */
	public static final int STRING_BUILDER_INIT = 4096;
}
