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

import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
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.EstacionDAO;
import com.rjconsultores.ventaboletos.entidad.Estacion;
import com.rjconsultores.ventaboletos.entidad.PuntoVenta;
import com.rjconsultores.ventaboletos.entidad.Usuario;

/**
 * 
 * @author Administrador
 */
@Repository("estacionDAO")
@SuppressWarnings({"unchecked", "rawtypes"})
public class EstacionHibernateDAO extends GenericHibernateDAO<Estacion, Integer> implements EstacionDAO {

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

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

		return c.list();
	}

	public List<Estacion> buscar(String descEstacion, String descMac, Long nunCaja, PuntoVenta pv) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));

		if(StringUtils.isNotBlank(descEstacion)) {
			c.add(Restrictions.like("descestacion", descEstacion, MatchMode.START));
		}
		if(StringUtils.isNotBlank(descMac)) {
			c.add(Restrictions.eq("descmac", descMac));
		}
		if(nunCaja != null) {
			c.add(Restrictions.eq("numcaja", nunCaja));
		}
		if(pv != null) {
			c.add(Restrictions.eq("puntoVenta", pv));
		}
		
		c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

		return c.list();
	}

	public List<Estacion> buscar(String descMac) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.eq("descmac", descMac));

		return c.list();
	}

	public Estacion buscarPorIMEI(String imei) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.eq("imei", imei));

		return (Estacion) c.uniqueResult();
	}

	@Override
	public List<Estacion> buscar(Long numCaja, PuntoVenta puntoVenta) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.eq("numcaja", numCaja));
		c.add(Restrictions.eq("puntoVenta", puntoVenta));
		c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

		return c.list();
	}

	public List<Estacion> buscarEstaciones(PuntoVenta puntoVenta) {

		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.eq("puntoVenta", puntoVenta));
		c.addOrder(Order.asc("numcaja"));
		c.addOrder(Order.asc("descestacion"));
		c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

		return c.list();
	}

	@Override
	public List<PuntoVenta> buscarPuntosVentaEstacionPorUsuario(Usuario usuario) {
		Criteria buscaPuntoVentasUsuario = getSession().createCriteria(getPersistentClass())
				.setProjection(Projections.distinct(Property.forName("puntoVenta")))
				.add(Restrictions.eq(ACTIVO, Boolean.TRUE))
				.add(Restrictions.eq("usuarioId", usuario.getUsuarioId()));

		return buscaPuntoVentasUsuario.list();
	}

	public Boolean temEstoque(PuntoVenta puntoVenta, Estacion estacion) {

		StringBuilder sb = new StringBuilder();
		sb.append("select dab.numseriepreimpresa as serie, ");
		sb.append("       dab.numfolioinicial    as folioinicial, ");
		sb.append("       dab.numfoliofinal      as foliofinal, ");
		sb.append("       pv.nombpuntoventa      as descpuntoventa, ");
		sb.append("       e.numcaja              as numcaja, ");
		sb.append("       e.descestacion         as descestacion, ");
		sb.append("       fp.foliopreimpreso     as folioatual, ");
		sb.append("       e.estacion_id          as estacionid, ");
		sb.append("       ab.articulo_id         as articuloid, ");
		sb.append("       a.descarticulo         as tipo, ");
		sb.append("       em.nombempresa         as nombempresa, ");
		sb.append("       em.empresa_id          as empresaid ");
		sb.append("from   det_abasto_boleto dab ");
		sb.append("       inner join abasto_boleto ab ");
		sb.append("               on dab.abastoboleto_id = ab.abastoboleto_id ");
		sb.append("       inner join punto_venta pv ");
		sb.append("               on ab.puntoventa_id = pv.puntoventa_id ");
		sb.append("       inner join estacion e ");
		sb.append("               on ab.estacion_id = e.estacion_id ");
		sb.append("       inner join folio_preimpreso fp ");
		sb.append("               on fp.estacion_id = ab.estacion_id ");
		sb.append("                  and fp.empresa_id = ab.empresa_id ");
		sb.append("                  and ( fp.numeserie = dab.numseriepreimpresa ");
		sb.append("                         or ( fp.numeserie is null ");
		sb.append("                              and dab.numseriepreimpresa is null ) ) ");
		sb.append("       left join articulo a ");
		sb.append("              on a.articulo_id = ab.articulo_id ");
		sb.append("       left join empresa em ");
		sb.append("              on em.empresa_id = ab.empresa_id ");
		sb.append("where  dab.statusoperacion = 1 ");
		sb.append("       and fp.activo = 1 ");
		sb.append("       and dab.activo = 1 ");
		sb.append("       and ab.puntoventa_id = :puntoventaId ");
		sb.append("       and e.estacion_id = :estacionId ");
		sb.append("union ");
		sb.append("select dab.numseriepreimpresa as serie, ");
		sb.append("       dab.numfolioinicial    as folioinicial, ");
		sb.append("       dab.numfoliofinal      as foliofinal, ");
		sb.append("       pv.nombpuntoventa      as descpuntoventa, ");
		sb.append("       e.numcaja              as numcaja, ");
		sb.append("       e.descestacion         as descestacion, ");
		sb.append("       dab.numfolioinicial    as folioatual, ");
		sb.append("       e.estacion_id          as estacionid, ");
		sb.append("       ab.articulo_id         as articuloid, ");
		sb.append("       a.descarticulo         as tipo, ");
		sb.append("       em.nombempresa         as nombempresa, ");
		sb.append("       em.empresa_id          as empresaid ");
		sb.append("from   det_abasto_boleto dab ");
		sb.append("       inner join abasto_boleto ab ");
		sb.append("               on dab.abastoboleto_id = ab.abastoboleto_id ");
		sb.append("       inner join punto_venta pv ");
		sb.append("               on ab.puntoventa_id = pv.puntoventa_id ");
		sb.append("       inner join estacion e ");
		sb.append("               on ab.estacion_id = e.estacion_id ");
		sb.append("       left join articulo a ");
		sb.append("              on a.articulo_id = ab.articulo_id ");
		sb.append("       left join empresa em ");
		sb.append("              on em.empresa_id = ab.empresa_id ");
		sb.append("where  dab.statusoperacion = 0 ");
		sb.append("       and dab.activo = 1 ");
		sb.append("       and ab.puntoventa_id = :puntoventaId ");
		sb.append("       and e.estacion_id = :estacionId ");

		SQLQuery query = getSession().createSQLQuery(sb.toString());
		query.setParameter("puntoventaId", puntoVenta.getPuntoventaId());
		query.setParameter("estacionId", estacion.getEstacionId());

		List list = query.list();
		if (list.size() > 0)
			return true;
		else
			return false;

	}

	@Override
	public List<Estacion> buscarEstaciones(List<PuntoVenta> lsPuntoVenta) {
		
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.in("puntoVenta", lsPuntoVenta));
		c.addOrder(Order.asc("numcaja"));
		c.addOrder(Order.asc("descestacion"));
		c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

		return c.list();
		
	}

	public List<Estacion> buscarEstacionesStockCentral(PuntoVenta puntoVenta) {

		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.eq("indStockCentral", Boolean.TRUE));
		c.add(Restrictions.eq("puntoVenta", puntoVenta));
		c.addOrder(Order.asc("descestacion"));
		c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

		return c.list();
	}

	public Estacion buscarEstacionDuplicadaPorMAC(String descMac, Integer estacionId) {
		StringBuilder sQuery = new StringBuilder();
		sQuery.append("SELECT e ")
			  .append("FROM Estacion e ")
			  .append("WHERE e.activo = 1")
			  .append("AND e.descmac = :descmac ");
		
		if(estacionId != null) {
			sQuery.append("AND e.estacionId <> :estacionId ");
		}
		
		Query qr = getSession().createQuery(sQuery.toString());
		qr.setParameter("descmac", descMac);
		
		if(estacionId != null) {
			qr.setParameter("estacionId", estacionId);
		}
		
		qr.setMaxResults(1);

		List<Estacion> lsEstacions = qr.list();
		
		if(lsEstacions != null && !lsEstacions.isEmpty()) {
			return lsEstacions.iterator().next();
		}

		return null;
	}

	public Estacion buscarEstacionDuplicadaPorIMEI(String imei, Integer estacionId) {
		StringBuilder sQuery = new StringBuilder();
		sQuery.append("SELECT e ")
			  .append("FROM Estacion e ")
			  .append("WHERE e.activo = 1")
			  .append("AND e.imei = :imei ");
		
		if(estacionId != null) {
			sQuery.append("AND e.estacionId <> :estacionId ");
		}
		
		Query qr = getSession().createQuery(sQuery.toString());
		qr.setParameter("imei", imei);
		
		if(estacionId != null) {
			qr.setParameter("estacionId", estacionId);
		}
		
		qr.setMaxResults(1);

		List<Estacion> lsEstacions = qr.list();
		
		if(lsEstacions != null && !lsEstacions.isEmpty()) {
			return lsEstacions.iterator().next();
		}

		return null;
	}
}
