package com.rjconsultores.ventaboletos.relatorios.impl;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.comparators.ComparatorChain;
import org.zkoss.util.resource.Labels;

import com.rjconsultores.ventaboletos.entidad.Empleado;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.DataSource;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.Relatorio;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.RelatorioTripulacaoBean;
import com.rjconsultores.ventaboletos.web.utilerias.NamedParameterStatement;

public class RelatorioTripulacao extends Relatorio {
	private static final short CONDUCTOR = 0;
	private static final short GUARDIA = 1;

	private Connection conexaoRelatorio;
	private List<RelatorioTripulacaoBean> lsDadosRelatorio;

	public RelatorioTripulacao(Map<String, Object> parametros, Connection conexao) throws Exception {
		super(parametros, conexao);
		this.parametros = parametros;
		this.lsDadosRelatorio = new ArrayList<RelatorioTripulacaoBean>();
		this.conexaoRelatorio = conexao;

		final String tipoEmpleado = (String) parametros.get("tipoEmpleado");

		this.setCustomDataSource(new DataSource(this) {
			@Override
			public void initDados() throws Exception {
				if (tipoEmpleado == null ||
						tipoEmpleado.isEmpty() ||
						tipoEmpleado.equals(Labels.getLabel("relatorioTripulacao.conductor"))) {
					lsDadosRelatorio.addAll(executeStatement(CONDUCTOR));
				}

				if (tipoEmpleado == null ||
						tipoEmpleado.isEmpty() ||
						tipoEmpleado.equals(Labels.getLabel("relatorioTripulacao.guardia"))) {
					lsDadosRelatorio.addAll(executeStatement(GUARDIA));

				}
				ordenar();
				setDadosRelatorio(lsDadosRelatorio);
			}
		});
	}
	private void ordenar(){
		ComparatorChain cc = new ComparatorChain();
		cc.addComparator(new BeanComparator("tipoEmpleadoTramo"));
		cc.addComparator(new BeanComparator("nomeEmpleado"));
		cc.addComparator(new BeanComparator("idEmpleado"));
		cc.addComparator(new BeanComparator("fecha"));
		cc.addComparator(new BeanComparator("hora"));
		
		Collections.sort(lsDadosRelatorio,cc);
	}

	private List<RelatorioTripulacaoBean> executeStatement(Short tipoTripulacao) throws SQLException, ParseException {
		String tipoEmpleadoTramo;

		Map<String, Object> parametros = this.getParametros();
		Empresa empresa = (Empresa) parametros.get("empresa");
		Empleado empleado = (Empleado) parametros.get("empleado");

		Date fecInicio = (Date) parametros.get("fecInicio");
		Date fecFinal = (Date) parametros.get("fecFinal");

		StringBuilder sql = new StringBuilder(getSelectClause());

		switch (tipoTripulacao) {
		case CONDUCTOR:
			sql.append(getSqlConductor1());
			sql.append(getWhereClause());
			sql.append(" UNION ");
			sql.append(getSelectClause());
			sql.append(getSqlConductor2());
			tipoEmpleadoTramo = Labels.getLabel("relatorioTripulacao.conductor");
			break;
		default:
			sql.append(getSqlGuardian1());
			sql.append(getWhereClause());
			sql.append(" UNION ");
			sql.append(getSelectClause());
			sql.append(getSqlGuardian2());
			tipoEmpleadoTramo = Labels.getLabel("relatorioTripulacao.guardia");
			break;
		}
		sql.append(getWhereClause());
		sql.append(getOrderBy());

		System.out.println(sql.toString());

		NamedParameterStatement stmt = new NamedParameterStatement(conexaoRelatorio, sql.toString());
		stmt.setDate("fecInicio", new java.sql.Date(fecInicio.getTime()));
		stmt.setDate("fecFinal", new java.sql.Date(fecFinal.getTime()));

		stmt.setLong("empleadoId", empleado != null ? empleado.getEmpleadoId() : 0);
		stmt.setLong("empresaId", empresa != null ? empresa.getEmpresaId() : 0);

		System.out.println(sql.toString());

		return getDataFromResultSet(stmt.executeQuery(), tipoEmpleadoTramo);
	}

	private List<RelatorioTripulacaoBean> getDataFromResultSet(ResultSet result, String tipoEmpleadoTramo) throws SQLException {
		List<RelatorioTripulacaoBean> lsDadosRelatorio = new ArrayList<RelatorioTripulacaoBean>();
		RelatorioTripulacaoBean relatorioTripulacaoBean = null;
		RelatorioTripulacaoBean relatorioTripulacaoBeanAnterior = null;

		while (result.next()) {

			if (relatorioTripulacaoBeanAnterior != null
					&& relatorioTripulacaoBeanAnterior.getIdEmpleado().equals(result.getLong("empleadoId"))
					&& relatorioTripulacaoBeanAnterior.getCorridaId().equals(result.getLong("corridaId"))
					&& relatorioTripulacaoBeanAnterior.getFecha().equals(result.getDate("fecha"))) {

				Double distancia = relatorioTripulacaoBean.getDistanciaKm();
				distancia += result.getDouble("distanciaKm");
				relatorioTripulacaoBean.setDistanciaKm(distancia);
				relatorioTripulacaoBean.setNomeDestino(result.getString("nomeDestino"));

			} else {
				relatorioTripulacaoBean = new RelatorioTripulacaoBean();
				relatorioTripulacaoBean.setTipoEmpleadoTramo(tipoEmpleadoTramo);
				relatorioTripulacaoBean.setIdEmpleado(result.getLong("empleadoId"));
				relatorioTripulacaoBean.setCorridaId(result.getLong("corridaId"));
				relatorioTripulacaoBean.setNomeEmpleado(result.getString("nomeEmpleado"));
				relatorioTripulacaoBean.setNomeMaterno(result.getString("nomeMaterno"));
				relatorioTripulacaoBean.setNomePaterno(result.getString("nomePaterno"));
				relatorioTripulacaoBean.setFecha(result.getDate("fecha"));
				relatorioTripulacaoBean.setNomeOrigem(result.getString("nomeOrigem"));
				relatorioTripulacaoBean.setNomeDestino(result.getString("nomeDestino"));
				relatorioTripulacaoBean.setDistanciaKm(result.getDouble("distanciaKm"));
				relatorioTripulacaoBean.setNumSequencia(result.getLong("numSequencia"));
				relatorioTripulacaoBean.setIdCorridaTramo(result.getLong("idCorridaTramo"));
				relatorioTripulacaoBean.setHora(result.getString("hora"));

				relatorioTripulacaoBeanAnterior = relatorioTripulacaoBean;
				lsDadosRelatorio.add(relatorioTripulacaoBean);
			}
		}
		return lsDadosRelatorio;
	}

	private void setDadosRelatorio(Collection collection) {
		this.setCollectionDataSource(new JRBeanCollectionDataSource(collection));
	}

	@Override
	protected void processaParametros() throws Exception {
	}

	private String getSelectClause() {
		return " SELECT"
				+ " emp.EMPLEADO_ID                          empleadoId, "
				+ " emp.NOMBEMPLEADO                         nomeEmpleado, "
				+ " emp.NOMBMATERNO                          nomeMaterno, "
				+ " emp.NOMBPATERNO                          nomePaterno, "
				+ " corrida.corrida_Id                       corridaId, "
				+ " corrida.feccorrida                       fecha, "
				+ " origem.cveparada                         nomeOrigem, "
				+ " destino.cveparada                        nomeDestino, "
				+ " to_char(corridaTramo.fechorsalida, 'HH24:MI') hora, "
				+ " corridaTramo.FECCORRIDA                  fecCorrida, "
				+ " tramo.cantkmreal                         distanciaKm, "
				+ " corridaTramo.numsecuencia                numSequencia, "
				+ " corridaTramo.CORRIDATRAMO_ID             idCorridaTramo "
				+ " FROM corrida corrida ";
	}

	private String getWhereClause() {
		return " WHERE corrida.activo = 1"
				+ " AND corrida.FECCORRIDA BETWEEN :fecInicio and :fecFinal"
				+ " AND(:empleadoId =0 or emp.EMPLEADO_ID=:empleadoId)"
				+ " AND (:empresaId =0 OR (emp.EMPRESA_ID IS NULL OR emp.EMPRESA_ID =:empresaId)) ";
	}

	private String getOrderBy() {
		return " ORDER BY nomeEmpleado,nomeMaterno,nomePaterno, corridaId, fecCorrida, numSequencia ";
	}

	private String getSqlConductor1() {
		return " INNER JOIN corrida_tramo corridaTramo"
				+ " ON corridaTramo.corrida_id = corrida.corrida_id AND corrida.feccorrida = corridaTramo.feccorrida"
				+ " INNER JOIN tramo tramo ON tramo.tramo_id = corridaTramo.tramo_id"
				+ " INNER JOIN parada origem ON origem.parada_id = corridaTramo.origen_id"
				+ " INNER JOIN parada destino ON destino.parada_id = corridaTramo.destino_id"
				+ " INNER JOIN CONDUCTOR cond ON cond.CONDUCTOR_ID = corridaTramo.CONDUCTOR1_ID"
				+ " INNER JOIN EMPLEADO emp ON emp.EMPLEADO_ID = cond.EMPLEADO_ID ";
	}

	private String getSqlConductor2() {
		return " INNER JOIN corrida_tramo corridaTramo"
				+ " ON corridaTramo.corrida_id = corrida.corrida_id AND corrida.feccorrida = corridaTramo.feccorrida"
				+ " INNER JOIN tramo tramo ON tramo.tramo_id = corridaTramo.tramo_id"
				+ " INNER JOIN parada origem ON origem.parada_id = corridaTramo.origen_id"
				+ " INNER JOIN parada destino ON destino.parada_id = corridaTramo.destino_id"
				+ " INNER JOIN CONDUCTOR cond ON cond.CONDUCTOR_ID = corridaTramo.CONDUCTOR2_ID"
				+ " INNER JOIN EMPLEADO emp ON emp.EMPLEADO_ID = cond.EMPLEADO_ID ";
	}

	private String getSqlGuardian1() {
		return " INNER JOIN corrida_tramo corridaTramo"
				+ " ON corridaTramo.corrida_id = corrida.corrida_id AND corrida.feccorrida = corridaTramo.feccorrida"
				+ " INNER JOIN tramo tramo ON tramo.tramo_id = corridaTramo.tramo_id"
				+ " INNER JOIN parada origem ON origem.parada_id = corridaTramo.origen_id"
				+ " INNER JOIN parada destino ON destino.parada_id = corridaTramo.destino_id"
				+ " INNER JOIN EMPLEADO emp ON emp.EMPLEADO_ID = corridaTramo.GUARDIA_ID ";
	}

	private String getSqlGuardian2() {
		return " INNER JOIN corrida_tramo corridaTramo"
				+ " ON corridaTramo.corrida_id = corrida.corrida_id AND corrida.feccorrida = corridaTramo.feccorrida"
				+ " INNER JOIN tramo tramo ON tramo.tramo_id = corridaTramo.tramo_id"
				+ " INNER JOIN parada origem ON origem.parada_id = corridaTramo.origen_id"
				+ " INNER JOIN parada destino ON destino.parada_id = corridaTramo.destino_id"
				+ " INNER JOIN EMPLEADO emp ON emp.EMPLEADO_ID = corridaTramo.GUARDIA2_ID ";
	}

}
