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

import java.math.BigDecimal;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.rjconsultores.ventaboletos.dao.TarifaMinimaDAO;
import com.rjconsultores.ventaboletos.entidad.ClaseServicio;
import com.rjconsultores.ventaboletos.entidad.Marca;
import com.rjconsultores.ventaboletos.entidad.Moneda;
import com.rjconsultores.ventaboletos.entidad.Parada;
import com.rjconsultores.ventaboletos.entidad.Plaza;
import com.rjconsultores.ventaboletos.entidad.TarifaMinima;
import com.rjconsultores.ventaboletos.entidad.TarifaMinimaCategoria;
import com.rjconsultores.ventaboletos.entidad.VigenciaTarifa;

/**
 * 
 * @author rodrigo
 */
@SuppressWarnings("unchecked")
@Repository("tarifaMinimaDAO")
public class TarifaMinimaHibernateDAO extends GenericHibernateDAO<TarifaMinima, Integer>
		implements TarifaMinimaDAO {

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

	@Override
	public List<TarifaMinima> obtenerTodos() {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));

		return c.list();
	}

	public List<TarifaMinima> pesquisar(Marca marca, Parada origem, Parada destino,
			ClaseServicio claseServicio, Moneda moneda,VigenciaTarifa vigenciaTarifa) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));

		if (marca != null) {
			c.add(Restrictions.eq("marca", marca));
		}

		if (origem != null) {
			c.add(Restrictions.eq("origem", origem));
		}

		if (destino != null) {
			c.add(Restrictions.eq("destino", destino));
		}

		if (claseServicio != null) {
			c.add(Restrictions.eq("claseServicio", claseServicio));
		}

		if (vigenciaTarifa != null) {
			c.add(Restrictions.eq("vigenciaTarifa", vigenciaTarifa));
		}

		return c.list();
	}

	public List<TarifaMinima> pesquisarPlaza(Marca marca, Parada origem, Parada destino,
			ClaseServicio claseServicio, Plaza plaza) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));

		if (marca != null) {
			c.add(Restrictions.eq("marca", marca));
		}

		if (origem != null) {
			c.add(Restrictions.eq("origem", origem));
		}

		if (destino != null) {
			c.add(Restrictions.eq("destino", destino));
		}

		if (claseServicio != null) {
			c.add(Restrictions.eq("claseServicio", claseServicio));
		}

		if (plaza != null) {
			c.add(Restrictions.eq("plaza", plaza));
		}

		return c.list();
	}

	public List<TarifaMinima> buscarPorPlaza(Plaza plaza) {
		Criteria c = getSession().createCriteria(getPersistentClass());

		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.eq("plaza", plaza));

		return c.list();
	}

	public List<TarifaMinima> pesquisar(BigDecimal valor, Moneda moneda,
			Plaza plaza, Marca marca, Parada origem, Parada destino,
			ClaseServicio claseServicio) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));

		c.add(Restrictions.eq("importetarifa", valor));
		c.add(Restrictions.eq("moneda", moneda));
		c.add(Restrictions.eq("marca", marca));
		c.add(Restrictions.eq("origem", origem));
		c.add(Restrictions.eq("destino", destino));
		c.add(Restrictions.eq("claseServicio", claseServicio));
		c.add(Restrictions.eq("plaza", plaza));

		return c.list();
	}

	public List<TarifaMinima> pesquisar(TarifaMinima tarifaMinima) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));

		// c.add(Restrictions.eq("importetarifa", valor));
		c.add(Restrictions.eq("moneda", tarifaMinima.getMoneda()));
		c.add(Restrictions.eq("marca", tarifaMinima.getMarca()));
		c.add(Restrictions.eq("origem", tarifaMinima.getOrigem()));
		c.add(Restrictions.eq("destino", tarifaMinima.getDestino()));
		c.add(Restrictions.eq("claseServicio", tarifaMinima.getClaseServicio()));
		c.add(Restrictions.eq("plaza", tarifaMinima.getPlaza()));
		c.add(Restrictions.eq("orgaoConcedente", tarifaMinima.getOrgaoConcedente()));
		
		c.add(Restrictions.eq("vigenciaTarifa", tarifaMinima.getVigenciaTarifa()));
		
		if(tarifaMinima.getRuta() != null){
			c.add(Restrictions.eq("ruta", tarifaMinima.getRuta()));
		}
		if(tarifaMinima.getRegionMetropolitana() != null){
			c.add(Restrictions.eq("regionMetropolitana", tarifaMinima.getRegionMetropolitana()));
		}
		if(tarifaMinima.getCoeficienteTarifa() != null){
			c.add(Restrictions.eq("coeficienteTarifa", tarifaMinima.getCoeficienteTarifa()));
		}

		return c.list();
	}

	public List<TarifaMinima> pesquisarOrigemDestinoTodos(Marca marca, Parada origem, Parada destino, ClaseServicio claseServicio, Moneda moneda,VigenciaTarifa vigenciaTarifa) {

		Criteria criterioBusca = getSession().createCriteria(getPersistentClass());

		Disjunction disjunctionOrigem = Restrictions.disjunction();
		Criterion cOrigem = Restrictions.eq("origem", origem);
		Criterion cOrigemTodos = Restrictions.eq("origem.paradaId", Parada.ID_PARADA_TODOS);
		disjunctionOrigem.add(cOrigem);
		disjunctionOrigem.add(cOrigemTodos);
		criterioBusca.add(disjunctionOrigem);

		Disjunction disjunctionDestino = Restrictions.disjunction();
		Criterion cDestino = Restrictions.eq("destino", destino);
		Criterion cDestinoTodos = Restrictions.eq("destino.paradaId", Parada.ID_PARADA_TODOS);
		disjunctionDestino.add(cDestino);
		disjunctionDestino.add(cDestinoTodos);
		criterioBusca.add(disjunctionDestino);

		criterioBusca.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		criterioBusca.add(Restrictions.eq("moneda", moneda));
		criterioBusca.add(Restrictions.eq("vigenciaTarifa", vigenciaTarifa));
		

		criterioBusca.add(Restrictions.or(Restrictions.eq("marca", marca), Restrictions.eq("marca.marcaId", (short) -1)));
		criterioBusca.add(Restrictions.or(Restrictions.eq("claseServicio", claseServicio), Restrictions.eq("claseServicio.claseservicioId", -1)));

		return criterioBusca.list();
	}

	public List<TarifaMinima> buscarPorMarcaMoneda(Marca marca, Moneda moneda) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));

		c.add(Restrictions.eq("marca", marca));
		c.add(Restrictions.eq("moneda", moneda));

		return c.list();
	}

	public List<TarifaMinima> buscarPorClaseServicioMoneda(
			ClaseServicio claseServicio, Moneda moneda) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));

		c.add(Restrictions.eq("claseServicio", claseServicio));
		c.add(Restrictions.eq("moneda", moneda));

		return c.list();
	}

	public List<TarifaMinima> buscarPorPlazaMoneda(Plaza plaza, Moneda moneda) {
		Criteria c = getSession().createCriteria(getPersistentClass());

		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.eq("plaza", plaza));
		c.add(Restrictions.eq("moneda", moneda));

		return c.list();
	}

	@Override
	@Transactional
	public TarifaMinimaCategoria adicionarTarifaMinimaCategoria(TarifaMinimaCategoria tarifaMinimaCategoria) {
		getSession().save(tarifaMinimaCategoria);
		return tarifaMinimaCategoria;
	}

	@Override
	@Transactional
	public void removerTarifaMinimaCategoria(TarifaMinimaCategoria tarifaMinimaCategoria) {
		getSession().merge(tarifaMinimaCategoria);
	}
	
	@Override
	@Transactional
	public BigDecimal obtenerTarifaMinima(Integer claseServicioId, Integer marcaId, Integer origenConsultaId,
			Integer destinoConsultaId, Integer plazaId, Integer monedaId, Integer rutaId, Integer categoriaId ) {
		BigDecimal tarifaMinima = BigDecimal.ZERO;

		StringBuilder hql = new StringBuilder("select tm from TarifaMinima tm ")
				.append("left join tm.orgaoConcedente oc ")
				.append("left join tm.tarifaMinimaCategorias tmc ")
				.append("left join tm.vigenciaTarifa vige ")
				.append("left join tm.regionMetropolitana.paradaList ori ")
				.append("left join tm.regionMetropolitana.paradaList des ")
				.append("where tm.activo = 1 ")
				.append("and tm.plaza.plazaId in (:plazaId, -1) ")
				.append("and tm.claseServicio.claseservicioId in (:claseServId, -1) ")
				.append("and tm.marca.marcaId in (:marcaId, -1) ")
				.append("and (ori.paradaId in (:origenId, -1) or ori.paradaId is null  )  ")
				.append("and (des.paradaId in (:destinoId,-1) or des.paradaId is null  )  ")
				.append("and (tm.origem.paradaId in (:origenId, -1) or tm.origem.paradaId is null) ")
				.append("and (tm.destino.paradaId in (:destinoId, -1) or tm.destino.paradaId is null) ")
				.append("and (tm.ruta.rutaId is null or tm.ruta.rutaId in (:rutaId, -1)) ");

		if (categoriaId != null) {
			hql.append("and (tmc is null or tmc.categoria.categoriaId in (:categoriaId, -1)) ");
		}
		
			 hql.append(" and tm.moneda.monedaId = :monedaId ")
				.append(" and (oc is null or oc.orgaoConcedenteId = -1 or oc.orgaoConcedenteId = ")
				.append(" (select distinct r.orgaoConcedente.orgaoConcedenteId from Ruta r")
				.append(" left join r.rutaCombinacionList rc")
				.append(" left join rc.tramo tr")
				.append(" left join tr.lsOrgaoTramo ot")
				.append("	where rc.ruta.rutaId = :rutaId")
				.append(" and (tm.coeficienteTarifa.coeficienteId in ")
				.append(" (ot.coeficienteTarifa1.coeficienteId, ot.coeficienteTarifa2.coeficienteId, ot.coeficienteTarifa3.coeficienteId ) ")
				.append(" and tr.origem = :origenId ")
				.append(" and tr.destino = :destinoId ")
				.append(" or tm.coeficienteTarifa is null )  )) ")
				.append(" and sysdate between vige.feciniciovigencia and vige.fecfinvigencia ")
		
				.append(" order by tm.plaza.plazaId desc, tm.origem.paradaId desc, ")
				.append(" tm.destino.paradaId desc, tm.claseServicio.claseservicioId desc, ")
				.append(" tm.marca.marcaId desc");

		Query miQry = getSession().createQuery(hql.toString());
		miQry.setInteger("plazaId", plazaId);
		miQry.setInteger("claseServId", claseServicioId);
		miQry.setInteger("marcaId", marcaId);
		miQry.setInteger("origenId", origenConsultaId);
		miQry.setInteger("destinoId", destinoConsultaId);
		miQry.setInteger("monedaId", monedaId);
		miQry.setInteger("rutaId", rutaId);

		if (categoriaId != null) {
			miQry.setInteger("categoriaId", categoriaId);
		}

		List<TarifaMinima> listTarifaMinima = miQry.list();
		if (!listTarifaMinima.isEmpty()) {
			tarifaMinima = listTarifaMinima.get(0).getImportetarifa();
		}

		return tarifaMinima;
	}
}
