package com.rjconsultores.ventaboletos.dao.hibernate;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
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 com.rjconsultores.ventaboletos.dao.ConexionRutaTramoCtrlDAO;
import com.rjconsultores.ventaboletos.entidad.ConexionRutaCtrl;
import com.rjconsultores.ventaboletos.entidad.ConexionRutaTramoCtrl;
import com.rjconsultores.ventaboletos.entidad.Parada;
import com.rjconsultores.ventaboletos.entidad.Tramo;

@Repository("conexionRutaTramoCtrlDAO")
public class ConexionRutaTramoCtrlHibernateDAO extends GenericHibernateDAO<ConexionRutaTramoCtrl, Long> implements ConexionRutaTramoCtrlDAO {

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

	@Override
	public boolean validarConexioneRutasExistentes(Integer rutaOrigenId, Integer rutaDestinoId, Integer rutaDestinoCId, Integer paradaOrigenId, Integer paradaDestinoId,  Integer origemTrechoId, Integer destinoTrechoId) {
		
		
		StringBuilder sb = new StringBuilder();

		sb.append("SELECT *");
		sb.append("   FROM conexion_ruta_ctrl crt ");
		sb.append("			INNER JOIN conexion_ruta_tramo_ctrl crtl ON (crtl.conexionrutactrl_id = crt.conexionrutactrl_id) ");
		sb.append("			INNER JOIN conexion c ON (c.conexionrutatramoctrl_id = crtl.conexionrutatramoctrl_id) ");
		sb.append("			INNER JOIN conexion_ctrl cc ON (cc.conexionctrl_id = c.conexionctrl_id) ");
		sb.append("				WHERE crt.ruta_origen_id =  ").append(rutaOrigenId);
		sb.append("  				AND crt.ruta_destino_id = ").append(rutaDestinoId);
		sb.append("  				AND crt.ruta_destinoc_id = ").append(rutaDestinoCId);
		sb.append("  				AND crtl.origen_id = ").append(paradaOrigenId);
		sb.append("  				AND crtl.destino_id = ").append(paradaDestinoId);
		sb.append("  				AND cc.origen_id = ").append(origemTrechoId);
		sb.append("  				AND cc.destino_id = ").append(destinoTrechoId);
		sb.append(" and crt.activo = 1 and crtl.activo = 1  and c.activo =1 and cc.activo = 1");

		Query query = getSession().createSQLQuery(sb.toString());
		List<Object[]> list = query.list();
		
		return !list.isEmpty();
	}

	@Override
	public List<ConexionRutaTramoCtrl> buscarPorConexionRutaCtrl(ConexionRutaCtrl conexionRutaCtrl, Integer rutaId) {
		
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.eq("conexionRutaCtrl", conexionRutaCtrl));
		c.add(Restrictions.eq("ruta.rutaId", rutaId));
		
		return c.list();
	}

	@Override
	public List<Parada> buscarTodasLocalidadesOrigem(Integer conexionRutaConfId) {
		return carregarParadas(conexionRutaConfId, 'A');
	}

	@Override
	public List<Parada> buscarTodasLocalidadesDestino(Integer conexionRutaConfId) {
		return carregarParadas(conexionRutaConfId, 'B');
	}

	@Override
	public List<Parada> buscarTodasLocalidadesDestinoC(Integer conexionRutaConfId) {
		return carregarParadas(conexionRutaConfId, 'C');
	}
	
	@SuppressWarnings("unchecked")
	private List<Parada> carregarParadas(Integer conexionRutaConfId, char tipo) {
		StringBuilder sQuery = new StringBuilder();
		sQuery.append("SELECT DISTINCT t ")
			  .append("FROM ConexionRutaCtrl ctrl ");
		
		switch (tipo) {
		case 'A':
			sQuery.append("JOIN ctrl.rutaOrigen r ");
			break;
		case 'B':
			sQuery.append("JOIN ctrl.rutaDestino r ");
			break;
		case 'C':
			sQuery.append("JOIN ctrl.rutaDestinoC r ");
			break;
		}
			  
		sQuery.append("JOIN r.rutaCombinacionList rc ")
			  .append("JOIN rc.tramo t ")
			  .append("WHERE ctrl.activo = 1 ")
			  .append("AND rc.activo = 1 ")
			  .append("AND t.activo = 1 ")
			  .append("AND ctrl.conexionRutaConf.conexionRutaConfId = :conexionRutaConfId");
		
		Query qr = getSession().createQuery(sQuery.toString());
		qr.setParameter("conexionRutaConfId", conexionRutaConfId);
		List<Tramo> listTramos = qr.list();
		Set<Parada> paradas = new HashSet<Parada>();
		for (Tramo tramo : listTramos) {
			paradas.add(tramo.getOrigem());
			paradas.add(tramo.getDestino());
		}
		
		return new ArrayList<Parada>(paradas);
	}
	
	/**
	 *Busca localidades de acordo com o conexionRutaConfId e pelo eixo informado ('A', 'B', 'C')
	 */
	@Override
	@SuppressWarnings("unchecked")
	public List<Parada> buscarLocalidadesPorConexionRutaConfAndEixo(Integer conexionRutaConfId, char tipo) {
		
		String filtro = "";
		String join = "";
		
		switch (tipo) {
		case 'A':
			filtro = "AND ctrlt.ruta = ctrl.rutaOrigen ";
			join = "JOIN ctrlt.origen p ";
			break;
		case 'B':
			filtro = "AND ctrlt.ruta = ctrl.rutaDestino ";
			join = "JOIN ctrlt.destino p ";
			break;
		case 'C':
			filtro = "AND ctrlt.ruta = ctrl.rutaDestinoC ";
			join = "JOIN ctrlt.destino p ";
			break;
		}
		
		StringBuilder sQuery = new StringBuilder();
		sQuery.append("SELECT DISTINCT p ")
			  .append("FROM ConexionRutaTramoCtrl ctrlt ")
			  .append(join)
			  .append("JOIN ctrlt.conexionRutaCtrl ctrl ")
			  .append("WHERE ctrlt.activo = 1")
			  .append("AND ctrl.activo = 1")
			  .append("AND ctrl.conexionRutaConf.conexionRutaConfId = :conexionRutaConfId ")
			  .append(filtro);
		
		Query qr = getSession().createQuery(sQuery.toString());
		qr.setParameter("conexionRutaConfId", conexionRutaConfId);
		List<Parada> paradas = qr.list();
		
		return paradas;
		
	}

}
