/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.rjconsultores.ventaboletos.dao.hibernate;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.hibernate.type.DateType;
import org.hibernate.type.IntegerType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;

import com.rjconsultores.ventaboletos.dao.EstadoDAO;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.Estado;
import com.rjconsultores.ventaboletos.entidad.Pais;

/**
 * 
 * @author MCosso
 */
@Repository("estadoDAO")
public class EstadoHibernateDAO extends GenericHibernateDAO<Estado, Integer>
		implements EstadoDAO {
	
	private static Logger log = LogManager.getLogger(EstadoHibernateDAO.class);

	@Autowired
	public EstadoHibernateDAO(@Qualifier("sessionFactory") SessionFactory factory) {
		setSessionFactory(factory);
	}

	@Override
	public List<Estado> obtenerTodos() {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.addOrder(Order.asc("nombestado"));

		return c.list();
	}

	public List<Estado> buscar(String nombestado, Pais pais) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.eq("nombestado", nombestado));
		c.add(Restrictions.eq("pais", pais));

		return c.list();
	}

	public List<Estado> buscarNotInEmpresaImposto(Empresa empresa) {
		StringBuilder sb = new StringBuilder();

		sb.append(" select es 				");
		sb.append(" from Estado es 			");
		sb.append(" where es.activo = 1  	");
		sb.append(" 	and es.estadoId not in ( ");
		sb.append(" 		select ei.estado.estadoId from EmpresaImposto ei ");
		sb.append(" 		where ei.activo = 1 and ei.empresa.empresaId =:empresaId  ");
		sb.append("			)");
		sb.append(" order by es.nombestado");

		Query query = getSession().createQuery(sb.toString());
		query.setParameter("empresaId", empresa.getEmpresaId());

		List<Estado> lsEstado = query.list();

		return lsEstado;
	}

	@Override
	public List<Estado> buscarCveEstado(String cveEstado) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.eq("cveestado", cveEstado));
		return c.list();
	}

	@Override
	public Map<String, Integer> getConfiguracoesFusoVeraoParada(Integer paradaId, Date data) {
		return getConfiguracoesFusoVerao(null, paradaId, data);
	}

	@Override
	public Map<String, Integer> getConfiguracoesFusoVeraoPuntoventa(Integer puntoventaId, Date data) {
		return getConfiguracoesFusoVerao(puntoventaId, null, data);
	}
	
	@SuppressWarnings("unchecked")
	private Map<String, Integer> getConfiguracoesFusoVerao(final Integer puntoventaId, final Integer paradaId, final Date data) {
		Map<String, Integer> retorno = new HashMap<String, Integer>();
		
		if(puntoventaId == null && paradaId == null) {
			return retorno;
		}
		
		Calendar dataServidorFuso = new GregorianCalendar();
		dataServidorFuso.setTime(data);
		
		final StringBuilder sql = new StringBuilder();
		sql.append(" select e.tiempohorhuso as tiempoHorHuso, e.tiempohorverano as tiempoHorVerano, ");
		sql.append(" e.feciniciohorverano as fecInicioHorVerano, e.fecfinohorverano as fecFinoHorVerano ");
		sql.append(" from estado e");
		sql.append(" join ciudad c on c.estado_id = e.estado_id");

		if (puntoventaId != null) {
			sql.append(" join colonia o on o.ciudad_id = c.ciudad_id");
			sql.append(" join punto_venta p on p.colonia_id = o.colonia_id");
		}
		
		if(paradaId != null) {
			sql.append(" join parada p on c.ciudad_id = p.ciudad_id");
		}
		
		sql.append(" where e.activo = 1");
		if (puntoventaId != null) {
			sql.append(" and p.puntoventa_id = :puntoventaId");
		}
		
		if(paradaId != null) {
			sql.append(" and p.parada_id = :paradaId");
		}

		try {
			Query qr = getSession().createSQLQuery(sql.toString())
								   .addScalar("tiempoHorHuso", IntegerType.INSTANCE)
								   .addScalar("tiempoHorVerano", IntegerType.INSTANCE)
								   .addScalar("fecInicioHorVerano", DateType.INSTANCE)
								   .addScalar("fecFinoHorVerano", DateType.INSTANCE)
								   .setResultTransformer(new AliasToBeanResultTransformer(Estado.class));
			if (puntoventaId != null) {
				qr.setParameter("puntoventaId", puntoventaId);
			}
			if(paradaId != null) {
				qr.setParameter("paradaId", paradaId);
			}
			
			List<Estado> resultado = qr.list();
			for (Estado estado : resultado) {
				Integer tiempohorhuso = estado.getTiempoHorHuso();
				Integer tiempohorverano = estado.getTiempoHorVerano();
				Date feciniciohorverano = estado.getFecInicioHorVerano();
				Date fecfinohorverano = estado.getFecFinoHorVerano();

				if (tiempohorhuso != null) {
					retorno.put("tiempohorhuso", tiempohorhuso);
				}

				if (fecfinohorverano != null && feciniciohorverano != null) {
					if ((dataServidorFuso.getTime().equals(feciniciohorverano)
							|| dataServidorFuso.getTime().after(feciniciohorverano))
							&& dataServidorFuso.getTime().before(fecfinohorverano)) {
						retorno.put("tiempohorverano", tiempohorverano);
					}
				}
				
				break;
			}
			
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}

		return retorno;
	}
}
