package com.rjconsultores.ventaboletos.relatorios.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.rjconsultores.ventaboletos.relatorios.utilitarios.Relatorio;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.beans.PesoOperacional;
import com.rjconsultores.ventaboletos.service.ConstanteService;
import com.rjconsultores.ventaboletos.web.utilerias.spring.AppContext;

public class RelatorioOrigemDestino extends Relatorio {

	private static Logger log = Logger.getLogger(RelatorioOrigemDestino.class);
	
	private static String CONSTANTE_GRATUIDADE_CRIANCA;

	public RelatorioOrigemDestino(Map<String, Object> parametros, Connection conexao) throws Exception {
		super(parametros, conexao);
	}

	@Override
	protected void processaParametros() throws Exception {

		CONSTANTE_GRATUIDADE_CRIANCA = buscarConstante("GRATUIDADE_CRIANCA");

		String corridasIds = (String) getParametros().get("CORRIDAS_SELECIONADAS");
		String empresaIds = (String) getParametros().get("EMPRESA_IDS");
		String dataDe = (String) getParametros().get("DATA_DE_WHERE");
		String dataAte = (String) getParametros().get("DATA_ATE_WHERE");
		Boolean bilhetesGratuitos = (Boolean) getParametros().get("BILHETES_GRATUITOS");
		Boolean trechosSemMovimento = (Boolean) getParametros().get("TRECHOS_SEM_MOVIMENTO");

		String sql = getSQL(empresaIds, corridasIds, dataDe, dataAte, bilhetesGratuitos, trechosSemMovimento);
		
		log.info(sql);

		List<PesoOperacional> lsPesoOperacionalRelatorio = getPesoOperacional(corridasIds, dataDe, dataAte, bilhetesGratuitos, empresaIds, trechosSemMovimento);
		getParametros().put("lsPesoOperacionalRelatorio", lsPesoOperacionalRelatorio);
		getParametros().put("SQL", sql);
	}

	private List<PesoOperacional> getPesoOperacional(String corridasIds, String dataDe, String dataAte,
			Boolean bilhetesGratuitos, String empresaIds, Boolean mostratTrechosSemMovimento) throws SQLException {
		StringBuilder sql = new StringBuilder();

		if (mostratTrechosSemMovimento) {
			sql.append("	SELECT TRAMOS.*, NVL(SOMA.RECEITA, 0) RECEITA,TRAMOS.SECO,TRAMOS.SECD ");
			sql.append("	FROM ");
			sql.append("	    ( ");
			sql.append("	     SELECT ");
			sql.append("	            CA.CORRIDA_ID CORRIDA_ID, ");
			sql.append("	            CA.FECCORRIDA FECCORRIDA, ");
			sql.append("	            O.CVEPARADA CVE_ORIGEM, ");
			sql.append("	            O.DESCPARADA ORIGEM, ");
			sql.append("	            D.CVEPARADA CVE_DESTINO, ");
			sql.append("	            D.DESCPARADA DESTINO, ");
			sql.append("	            SUM(CA.PRECIOPAGADO) RECEITA ");
			sql.append("	      FROM BOLETO CA ");
			sql.append("	      INNER JOIN PARADA O ON O.PARADA_ID = CA.ORIGEN_ID ");
			sql.append("	      INNER JOIN PARADA D ON D.PARADA_ID = CA.DESTINO_ID ");
			sql.append("	      WHERE CA.ACTIVO = 1 ");
			sql.append("	      AND CA.MOTIVOCANCELACION_ID IS NULL ");
			
			if(StringUtils.isNotBlank(CONSTANTE_GRATUIDADE_CRIANCA)) {
				sql.append("          AND CA.CATEGORIA_ID <> ").append(CONSTANTE_GRATUIDADE_CRIANCA);
			}
			
			sql.append("	      AND CA.PRECIOBASE IS NOT NULL ");
			if (bilhetesGratuitos) {
				sql.append("      AND CA.PRECIOBASE >= 0 ");
			} else {
				sql.append("      AND CA.PRECIOBASE > 0 ");
			}
			if (!corridasIds.equals("Todas")) {
				sql.append("      AND CA.CORRIDA_ID IN (").append(corridasIds).append(")");
			}
			sql.append("	      AND CA.FECCORRIDA BETWEEN TO_DATE('").append(dataDe).append("','DD/MM/YYYY HH24:MI:SS') AND TO_DATE('").append(dataAte).append("','DD/MM/YYYY HH24:MI:SS') ");
			sql.append("		  AND CA.EMPRESACORRIDA_ID IN (").append(empresaIds).append(") ");
			sql.append("	      GROUP BY ");
			sql.append("	           CA.CORRIDA_ID, ");
			sql.append("	           CA.FECCORRIDA, ");
			sql.append("	           O.CVEPARADA, ");
			sql.append("	           O.DESCPARADA, ");
			sql.append("	           D.CVEPARADA, ");
			sql.append("	           D.DESCPARADA ");
			sql.append("	) SOMA ");
			sql.append("	RIGHT JOIN ");
			sql.append("	    ( ");
			sql.append("	        SELECT ");
			sql.append("	            CO.CORRIDA_ID CORRIDA_ID, ");
			sql.append("	            CO.FECCORRIDA FECCORRIDA, ");
			sql.append("	            O.CVEPARADA CVE_ORIGEM, ");
			sql.append("	            O.DESCPARADA ORIGEM, ");
			sql.append("	            D.CVEPARADA CVE_DESTINO, ");
			sql.append("	            RS.NUMSECUENCIA SECO, ");
			sql.append("	            RSD.NUMSECUENCIA SECD, ");
			sql.append("	            D.DESCPARADA DESTINO ");
			sql.append("	      FROM CORRIDA CO ");
			sql.append("	      INNER JOIN RUTA R ON R.RUTA_ID=CO.RUTA_ID ");
			sql.append("	      INNER JOIN RUTA_COMBINACION RC ON RC.RUTA_ID=R.RUTA_ID ");
			sql.append("	      INNER JOIN TRAMO TR ON TR.TRAMO_ID=RC.TRAMO_ID ");
			sql.append("	      INNER JOIN PARADA O ON O.PARADA_ID = TR.ORIGEN_ID ");
			sql.append("	      INNER JOIN PARADA D ON D.PARADA_ID = TR.DESTINO_ID ");

			sql.append("          LEFT JOIN RUTA_SECUENCIA RS ON RS.RUTA_ID = CO.RUTA_ID ");
			sql.append("          INNER JOIN TRAMO T ON T.TRAMO_ID = RS.TRAMO_ID AND T.ORIGEN_ID = TR.ORIGEN_ID ");
			sql.append("          LEFT JOIN RUTA_SECUENCIA RSD ON RSD.RUTA_ID = CO.RUTA_ID ");
			sql.append("          INNER JOIN TRAMO TD ON TD.TRAMO_ID = RSD.TRAMO_ID AND TD.DESTINO_ID = TR.DESTINO_ID ");
			sql.append("	      WHERE R.ACTIVO = 1 AND RC.ACTIVO = 1 AND TR.ACTIVO = 1 AND RS.activo = 1 and rsd.activo = 1 ");
			sql.append("	      AND CO.ACTIVO = 1 ");

			if (!corridasIds.equals("Todas")) {
				sql.append("      AND CO.CORRIDA_ID IN (").append(corridasIds).append(")");
			}
			sql.append("	      AND CO.FECCORRIDA BETWEEN TO_DATE('").append(dataDe).append("','DD/MM/YYYY HH24:MI:SS') AND TO_DATE('").append(dataAte).append("','DD/MM/YYYY HH24:MI:SS') ");
			sql.append("		  AND CO.EMPRESACORRIDA_ID IN (").append(empresaIds).append(") ");
			sql.append("	)TRAMOS ");
			sql.append("	ON (TRAMOS.CORRIDA_ID=SOMA.CORRIDA_ID AND TRAMOS.FECCORRIDA=SOMA.FECCORRIDA AND TRAMOS.CVE_ORIGEM=SOMA.CVE_ORIGEM AND TRAMOS.CVE_DESTINO=SOMA.CVE_DESTINO) ");
			sql.append("	ORDER BY TRAMOS.CORRIDA_ID ");
		} else {
			sql.append("	SELECT ");
			sql.append("        CA.CORRIDA_ID CORRIDA_ID, ");
			sql.append("        CA.FECCORRIDA FECCORRIDA, ");
			sql.append("	    O.CVEPARADA CVE_ORIGEM, ");
			sql.append("	    O.DESCPARADA ORIGEM, ");
			sql.append("	    D.CVEPARADA CVE_DESTINO, ");
			sql.append("	    D.DESCPARADA DESTINO, ");
			sql.append("	    RS.NUMSECUENCIA SECO, ");
			sql.append("	    RSD.NUMSECUENCIA SECD, ");
			sql.append("	    SUM(CA.PRECIOPAGADO) RECEITA ");
			sql.append("	FROM BOLETO CA ");
			sql.append("        INNER JOIN PARADA O ON O.PARADA_ID = CA.ORIGEN_ID ");
			sql.append("	    INNER JOIN PARADA D ON D.PARADA_ID = CA.DESTINO_ID  ");
			sql.append("        LEFT JOIN CORRIDA CO ON CO.CORRIDA_ID = CA.CORRIDA_ID AND CO.FECCORRIDA = CA.FECCORRIDA  ");
			sql.append("        LEFT JOIN RUTA_SECUENCIA RS ON RS.RUTA_ID = CO.RUTA_ID ");
			sql.append("        INNER JOIN TRAMO T ON T.TRAMO_ID = RS.TRAMO_ID AND T.ORIGEN_ID = CA.ORIGEN_ID ");
			sql.append("        LEFT JOIN RUTA_SECUENCIA RSD ON RSD.RUTA_ID = CO.RUTA_ID ");
			sql.append("        INNER JOIN TRAMO TD ON TD.TRAMO_ID = RSD.TRAMO_ID AND TD.DESTINO_ID = CA.DESTINO_ID ");

			sql.append("	WHERE CA.ACTIVO = 1 ");
			sql.append("	        AND CO.ACTIVO = 1 ");
			sql.append("	        AND RS.ACTIVO = 1 ");
			sql.append("	        AND CA.MOTIVOCANCELACION_ID IS NULL ");
			
			if(StringUtils.isNotBlank(CONSTANTE_GRATUIDADE_CRIANCA)) {
				sql.append("            AND CA.CATEGORIA_ID <> ").append(CONSTANTE_GRATUIDADE_CRIANCA);
			}
			
			sql.append("	        AND CA.PRECIOBASE IS NOT NULL ");
			if (bilhetesGratuitos) {
				sql.append("        AND CA.PRECIOBASE >= 0 ");
			} else {
				sql.append("        AND CA.PRECIOBASE > 0 ");
			}
			if (!corridasIds.equals("Todas")) {
				sql.append("        AND CA.CORRIDA_ID IN (").append(corridasIds).append(")");
			}
			sql.append("	    AND CA.FECCORRIDA BETWEEN TO_DATE('").append(dataDe).append("','DD/MM/YYYY HH24:MI:SS') AND TO_DATE('").append(dataAte).append("','DD/MM/YYYY HH24:MI:SS') ");
			sql.append("		AND CA.EMPRESACORRIDA_ID IN (").append(empresaIds).append(") ");
			sql.append("	GROUP BY ");
			sql.append("       CA.CORRIDA_ID, ");
			sql.append("       CA.FECCORRIDA, ");
			sql.append("	   O.CVEPARADA, ");
			sql.append("	   O.DESCPARADA, ");
			sql.append("	   D.CVEPARADA, ");
			sql.append("	   RS.NUMSECUENCIA, ");
			sql.append("	   RSD.NUMSECUENCIA, ");
			sql.append("	   D.DESCPARADA ");

			sql.append("    ORDER BY CA.CORRIDA_ID,SECD ");
		}

		Connection conexao = getConexao();

		PreparedStatement stmt = null;
		stmt = conexao.prepareStatement(sql.toString());

		ResultSet rset = null;
		rset = stmt.executeQuery();

		Map<Integer, Map<ParadaRelatorioOD, BigDecimal>> mapPorCorridaReceitaSaida = new HashMap<Integer, Map<ParadaRelatorioOD, BigDecimal>>();
		Map<Integer, Map<ParadaRelatorioOD, BigDecimal>> mapPorCorridaReceitaChegada = new HashMap<Integer, Map<ParadaRelatorioOD, BigDecimal>>();
		Map<Integer, BigDecimal> mapTotalReceitaCorrida = new HashMap<Integer, BigDecimal>();
		List<Integer> lsCorridaIds = new ArrayList<Integer>();
		while (rset.next()) {
			Integer idCorrida = rset.getInt("CORRIDA_ID");

			if (!lsCorridaIds.contains(idCorrida)) {
				lsCorridaIds.add(idCorrida);
			}

			Map<ParadaRelatorioOD, BigDecimal> mapReceitaSaida = mapPorCorridaReceitaSaida.get(idCorrida);
			Map<ParadaRelatorioOD, BigDecimal> mapReceitaChegada = mapPorCorridaReceitaChegada.get(idCorrida);

			if (mapReceitaSaida == null) {
				mapReceitaSaida = new HashMap<ParadaRelatorioOD, BigDecimal>();
			}

			if (mapReceitaChegada == null) {
				mapReceitaChegada = new HashMap<ParadaRelatorioOD, BigDecimal>();
			}

			BigDecimal receita = rset.getBigDecimal("RECEITA");
			BigDecimal totalReceita = mapTotalReceitaCorrida.get(idCorrida);
			if (totalReceita == null) {
				totalReceita = BigDecimal.ZERO;
			}
			totalReceita = totalReceita.add(receita);
			mapTotalReceitaCorrida.put(idCorrida, totalReceita);

			ParadaRelatorioOD paradaOrigem = new ParadaRelatorioOD(rset.getString("ORIGEM"), rset.getString("CVE_ORIGEM"), rset.getInt("SECO"));
			ParadaRelatorioOD paradaDestino = new ParadaRelatorioOD(rset.getString("DESTINO"), rset.getString("CVE_DESTINO"), rset.getInt("SECD"));

			BigDecimal receitaSaida = mapReceitaSaida.get(paradaOrigem);
			if (receitaSaida != null) {
				mapReceitaSaida.put(paradaOrigem, receita.add(receitaSaida));
			} else {
				mapReceitaSaida.put(paradaOrigem, receita);
			}

			BigDecimal receitaChegada = mapReceitaChegada.get(paradaDestino);
			if (receitaChegada != null) {
				mapReceitaChegada.put(paradaDestino, receita.add(receitaChegada));
			} else {
				mapReceitaChegada.put(paradaDestino, receita);
			}

			mapPorCorridaReceitaSaida.put(idCorrida, mapReceitaSaida);
			mapPorCorridaReceitaChegada.put(idCorrida, mapReceitaChegada);
		}

		List<PesoOperacional> lsPesoOperacionalRelatorio = new ArrayList<PesoOperacional>();
		for (Integer idCorrida : lsCorridaIds) {
			Map<ParadaRelatorioOD, BigDecimal> mapReceitaSaida = mapPorCorridaReceitaSaida.get(idCorrida);
			Map<ParadaRelatorioOD, BigDecimal> mapReceitaChegada = mapPorCorridaReceitaChegada.get(idCorrida);

			List<ParadaRelatorioOD> lsTodasParadas = new ArrayList<ParadaRelatorioOD>();
			for (ParadaRelatorioOD parada : mapReceitaChegada.keySet()) {
				lsTodasParadas.add(parada);
			}
			for (ParadaRelatorioOD parada : mapReceitaSaida.keySet()) {
				if (!lsTodasParadas.contains(parada)) {
					lsTodasParadas.add(parada);
				}
			}

			BigDecimal totalReceita = mapTotalReceitaCorrida.get(idCorrida);
			for (ParadaRelatorioOD parada : lsTodasParadas) {
				BigDecimal receitaSaida = mapReceitaSaida.get(parada) == null ? BigDecimal.ZERO : mapReceitaSaida.get(parada);
				BigDecimal receitaChegada = mapReceitaChegada.get(parada) == null ? BigDecimal.ZERO : mapReceitaChegada.get(parada);
				BigDecimal soma = receitaSaida.add(receitaChegada);
				BigDecimal peso = totalReceita.equals(BigDecimal.ZERO) ? BigDecimal.ZERO : soma.divide(totalReceita, 2, RoundingMode.HALF_EVEN);

				PesoOperacional pesoOperacional = new PesoOperacional();
				pesoOperacional.setCorridaId(idCorrida);
				pesoOperacional.setLocalidade(parada.getCveParada() + " - " + parada.getDescParada());
				pesoOperacional.setSecuencia(parada.getNumSecuencia());
				pesoOperacional.setReceitaSaida(receitaSaida);
				pesoOperacional.setReceitaChegada(receitaChegada);
				pesoOperacional.setSoma(soma);
				pesoOperacional.setPeso(peso);

				lsPesoOperacionalRelatorio.add(pesoOperacional);
			}
		}

		Collections.sort(lsPesoOperacionalRelatorio);

		return lsPesoOperacionalRelatorio;
	}

	private String getSQL(String empresaIds, String corridasIds, String dataDe, String dataAte,
			Boolean bilhetesGratuitos, Boolean trechosSemMovimento) {

		StringBuilder sql = new StringBuilder();
		sql.append(" SELECT * ");
		sql.append(" FROM   (SELECT RESULTADO_2.nombempresa, ");
		sql.append("               RESULTADO_2.corrida_id CORRIDA_1, ");
		sql.append("               RESULTADO_2.fechorsalida, ");
		sql.append("               RESULTADO_2.origem, ");
		sql.append("               RESULTADO_2.destino, ");
		sql.append("               RESULTADO_2.km_tramo, ");
		sql.append("               RESULTADO_2.ruta_id, ");
		sql.append("               RESULTADO_2.descruta, ");
		sql.append("               RESULTADO_2.indsentidoida, ");
		sql.append("               RESULTADO_2.absolutos, ");
		sql.append("               RESULTADO_2.receita, ");
		sql.append("               RESULTADO_2.preciobase, ");
		sql.append("               RESULTADO_2.viagens, ");
		sql.append("               RESULTADO_2.km_corrida, ");
		sql.append("               RESULTADO_2.disponibilidade, ");
		sql.append("               RESULTADO_2.absoluto_total_corrida,");
		sql.append("               RESULTADO_2.importetaxaembarque, ");
		sql.append("               RESULTADO_2.importepedagio ");
		sql.append("        FROM   (SELECT RESULTADO.*, ");
		sql.append("                       (SELECT Count(*) ");
		sql.append("                        FROM   corrida CO ");
		sql.append("                        WHERE  CO.corrida_id = RESULTADO.corrida_id ");
		sql.append("		                   AND CO.FECCORRIDA BETWEEN to_date('" + dataDe + "','dd/mm/yyyy HH24:mi:ss') AND to_date('" + dataAte + "','dd/mm/yyyy HH24:mi:ss') ");
		sql.append("		                   AND CO.ACTIVO = 1 ");
		sql.append("                       ) VIAGENS, ");
		sql.append("                       TR.cantkmreal KM_CORRIDA, ");
		sql.append("                       (SELECT AVG(DA.cantasientos) ");
		sql.append("                        FROM   corrida CO ");
		sql.append("                               INNER JOIN rol_operativo ROL ON ROL.roloperativo_id = CO.roloperativo_id ");
		sql.append("                               INNER JOIN diagrama_autobus DA ON DA.diagramaautobus_id = ROL.diagramaautobus_id ");
		sql.append("                        WHERE  CO.corrida_id = RESULTADO.corrida_id ");
		sql.append("		                   AND CO.FECCORRIDA BETWEEN to_date('" + dataDe + "','dd/mm/yyyy HH24:mi:ss') AND to_date('" + dataAte + "','dd/mm/yyyy HH24:mi:ss') ");
		sql.append("                        GROUP  BY CO.corrida_id) ");
		sql.append("                               DISPONIBILIDADE, ");
		sql.append("                       (SELECT Count(*) ");
		sql.append("                        FROM   boleto CA ");
		sql.append("                               INNER JOIN corrida CO ON ( CO.corrida_id = CA.corrida_id AND CO.feccorrida = CA.feccorrida ) ");
		sql.append("                        WHERE  CA.activo = 1 ");
		sql.append(("		                       AND CO.EMPRESACORRIDA_ID IN (") + empresaIds + ") ");
		sql.append("                               AND CA.corrida_id = RESULTADO.corrida_id ");
		sql.append("		                       AND CA.FECCORRIDA BETWEEN to_date('" + dataDe + "','dd/mm/yyyy HH24:mi:ss') AND to_date('" + dataAte + "','dd/mm/yyyy HH24:mi:ss') ");
		sql.append("                               AND CA.motivocancelacion_id IS NULL ");
		
		if(StringUtils.isNotBlank(CONSTANTE_GRATUIDADE_CRIANCA)) {
			sql.append("                               AND CA.CATEGORIA_ID <> ").append(CONSTANTE_GRATUIDADE_CRIANCA);
		}
		
		sql.append("                               AND CA.preciobase IS NOT NULL ");
		sql.append((bilhetesGratuitos ? " AND CA.PRECIOBASE >= 0 ) " : " AND CA.PRECIOBASE > 0 ) "));
		sql.append("                               ABSOLUTO_TOTAL_CORRIDA ");
		sql.append("                FROM  (SELECT EM.nombempresa, ");
		sql.append("                              CO.corrida_id        CORRIDA_ID, ");
		sql.append("                              Max(CO.fechorsalida) FECHORSALIDA, ");
		sql.append("                              ORI.cveparada        ORIGEM, ");
		sql.append("                              CO.origen_id         ORIGEN_ID, ");
		sql.append("                              CO.destino_id        DESTINO_ID, ");
		sql.append("                              DES.cveparada        DESTINO, ");
		sql.append("                              CA.numkmviaje        KM_TRAMO, ");
		sql.append("                              RU.ruta_id, ");
		sql.append("                              RU.descruta, ");
		sql.append("                              RU.indsentidoida, ");
		sql.append("                              Count(*)             ABSOLUTOS, ");
		sql.append("                              Sum(CA.preciopagado) RECEITA, ");
		sql.append("                              CA.preciobase, ");
		sql.append("                              SUM(CA.IMPORTETAXAEMBARQUE) as importetaxaembarque, ");
		sql.append("                              SUM(CA.IMPORTEPEDAGIO) as importepedagio ");
		sql.append("                       FROM   boleto CA ");
		sql.append("                              INNER JOIN parada ORI ON ORI.parada_id = CA.origen_id ");
		sql.append("                              INNER JOIN parada DES ON DES.parada_id = CA.destino_id ");
		sql.append("                              INNER JOIN corrida CO ON ( CO.corrida_id = CA.corrida_id AND CO.feccorrida = CA.feccorrida ) ");
		sql.append("                              INNER JOIN empresa EM ON EM.empresa_id = CO.empresacorrida_id ");
		sql.append("                              INNER JOIN ruta RU ON RU.ruta_id = CO.ruta_id ");
		sql.append("                              INNER JOIN tarifa TF ON (TF.CLASESERVICIO_ID = CO.CLASESERVICIO_ID  ");
		sql.append("                                                        AND TF.DESTINO_ID = CO.DESTINO_ID  ");
		sql.append("                                                        AND TF.ORIGEN_ID = CO.ORIGEN_ID ");
		sql.append("                                                        AND TF.MARCA_ID = CO.MARCA_ID ");
		sql.append("                                                        AND TF.RUTA_ID = CO.RUTA_ID)");
		sql.append("INNER JOIN VIGENCIA_TARIFA VT ON (TF.VIGENCIATARIFA_ID=VT.VIGENCIATARIFA_ID)");
		sql.append("                       WHERE  CA.activo = 1 AND RU.activo = 1 AND EM.activo = 1 AND ORI.activo = 1 AND DES.activo = 1 ");
		sql.append("                              AND CO.activo = 1 ");
		sql.append((!corridasIds.equals("Todas") ? "	    AND CA.CORRIDA_ID IN (" + corridasIds + ") " : " "));
		sql.append(("		                      AND CO.EMPRESACORRIDA_ID IN (") + empresaIds + ") ");
		sql.append("		                      AND CA.FECCORRIDA BETWEEN to_date('" + dataDe + "','dd/mm/yyyy HH24:mi:ss') AND to_date('" + dataAte + "','dd/mm/yyyy HH24:mi:ss') ");
		sql.append("                              AND CA.motivocancelacion_id IS NULL ");
		
		if(StringUtils.isNotBlank(CONSTANTE_GRATUIDADE_CRIANCA)) {
			sql.append("                              AND CA.CATEGORIA_ID <> ").append(CONSTANTE_GRATUIDADE_CRIANCA);
		}
		
		sql.append("                              AND CA.preciobase IS NOT NULL ");
		sql.append((bilhetesGratuitos ? " AND CA.PRECIOBASE >= 0 " : " AND CA.PRECIOBASE > 0 "));
		sql.append(" AND CO.FECCORRIDA BETWEEN vt.FECINICIOVIGENCIA and vt.FECFINVIGENCIA");
		sql.append("                       GROUP  BY RU.ruta_id, ");
		sql.append("                                 EM.nombempresa, ");
		sql.append("                                 ORI.cveparada, ");
		sql.append("                                 DES.cveparada, ");
		sql.append("                                 CO.origen_id, ");
		sql.append("                                 CO.destino_id, ");
		sql.append("                                 CA.numkmviaje, ");
		sql.append("                                 CO.corrida_id, ");
		sql.append("                                 RU.descruta, ");
		sql.append("                                 RU.indsentidoida, ");
		sql.append("                                 CA.preciobase ) RESULTADO ");
		sql.append("                      INNER JOIN ruta_combinacion RS on RS.ruta_Id = RESULTADO.ruta_id ");
		sql.append("                      INNER JOIN tramo TR ON TR.tramo_id  = RS.tramo_id and (TR.origen_id = RESULTADO.ORIGEN_ID and TR.destino_id = RESULTADO.destino_id) ");
		sql.append("                WHERE  RS.activo = 1 AND TR.activo = 1 ");
		sql.append("                GROUP  BY RESULTADO.nombempresa, ");
		sql.append("                          RESULTADO.corrida_id, ");
		sql.append("                          RESULTADO.fechorsalida, ");
		sql.append("                          RESULTADO.origem, ");
		sql.append("                          RESULTADO.destino, ");
		sql.append("                          RESULTADO.origen_id, ");
		sql.append("                          RESULTADO.destino_id, ");
		sql.append("                          TR.cantkmreal, ");
		sql.append("                          RESULTADO.km_tramo, ");
		sql.append("                          RESULTADO.ruta_id, ");
		sql.append("                          RESULTADO.descruta, ");
		sql.append("                          RESULTADO.indsentidoida, 	");
		sql.append("                          RESULTADO.absolutos, ");
		sql.append("                          RESULTADO.receita, ");
		sql.append("                          RESULTADO.preciobase, ");
		sql.append("                          RESULTADO.IMPORTETAXAEMBARQUE,");
		sql.append("                          RESULTADO.IMPORTEPEDAGIO ) RESULTADO_2 ");
		sql.append("        GROUP  BY RESULTADO_2.nombempresa, ");
		sql.append("                  RESULTADO_2.corrida_id, ");
		sql.append("                  RESULTADO_2.fechorsalida, ");
		sql.append("                  RESULTADO_2.origem, ");
		sql.append("                  RESULTADO_2.destino, ");
		sql.append("                  RESULTADO_2.km_tramo, ");
		sql.append("                  RESULTADO_2.ruta_id, ");
		sql.append("                  RESULTADO_2.descruta, ");
		sql.append("                  RESULTADO_2.indsentidoida, ");
		sql.append("                  RESULTADO_2.absolutos, ");
		sql.append("                  RESULTADO_2.receita, ");
		sql.append("                  RESULTADO_2.preciobase, ");
		sql.append("                  RESULTADO_2.viagens, ");
		sql.append("                  RESULTADO_2.km_corrida, ");
		sql.append("                  RESULTADO_2.disponibilidade, ");
		sql.append("                  RESULTADO_2.absoluto_total_corrida, ");
		sql.append("                  RESULTADO_2.IMPORTETAXAEMBARQUE, ");
		sql.append("                  RESULTADO_2.IMPORTEPEDAGIO ");
		sql.append("        ORDER  BY RESULTADO_2.corrida_id) T1 ");
		sql.append("       INNER JOIN (SELECT RESULTADO_2.corrida_id CORRIDA_2, ");
		sql.append("                          Sum(RESULTADO_2.equivalente) EQUIVALENTE_TOTAL_CORRIDA ");
		sql.append("                   FROM  (SELECT RESULTADO.*, ");
		sql.append("                                 ( RESULTADO.km_tramo / Sum(TR.cantkmreal) ) * ( ");
		sql.append("                                 SELECT Count(*) ");
		sql.append("                                 FROM boleto CA ");
		sql.append("                                 INNER JOIN corrida CO ON ( CO.corrida_id = CA.corrida_id AND CO.feccorrida = CA.feccorrida ) ");
		sql.append("                                 INNER JOIN parada PO ON CA.origen_id = PO.parada_id ");
		sql.append("                                 INNER JOIN parada PD ON CA.destino_id = PD.parada_id ");
		sql.append("                                 WHERE CA.activo = 1 ");
		sql.append("                                 AND CO.activo = 1 ");
		sql.append(("		                         AND CO.EMPRESACORRIDA_ID IN (") + empresaIds + ") ");
		sql.append("                                 AND CA.corrida_id = RESULTADO.corrida_id ");
		sql.append("		                         AND CA.FECCORRIDA BETWEEN to_date('" + dataDe + "','dd/mm/yyyy HH24:mi:ss') AND to_date('" + dataAte + "','dd/mm/yyyy HH24:mi:ss') ");
		sql.append("                                 AND CA.motivocancelacion_id IS NULL ");
		
		if(StringUtils.isNotBlank(CONSTANTE_GRATUIDADE_CRIANCA)) {
			sql.append("                                 AND CA.CATEGORIA_ID <> ").append(CONSTANTE_GRATUIDADE_CRIANCA);
		}
		
		sql.append("                                 AND CA.preciobase IS NOT NULL ");
		sql.append("                                 AND CA.preciobase = RESULTADO.preciobase ");
		sql.append("                                 AND PO.cveparada = RESULTADO.origem ");
		sql.append("                                 AND PD.cveparada = RESULTADO.destino) ");
		sql.append("                                 EQUIVALENTE ");
		sql.append("                          FROM  (SELECT CO.corrida_id CORRIDA_ID, ");
		sql.append("                                        ORI.cveparada ORIGEM, ");
		sql.append("                                        DES.cveparada DESTINO, ");
		sql.append("                                        CA.numkmviaje KM_TRAMO, ");
		sql.append("                                        RU.ruta_id, ");
		sql.append("                                        CA.preciobase, ");
		sql.append("                                        CO.origen_id, ");
		sql.append("                                        CO.destino_id ");
		sql.append("                                 FROM   boleto CA ");
		sql.append("                                        INNER JOIN parada ORI ON ORI.parada_id = CA.origen_id ");
		sql.append("                                        INNER JOIN parada DES ON DES.parada_id = CA.destino_id ");
		sql.append("                                        INNER JOIN corrida CO ON ( CO.corrida_id = CA.corrida_id AND CO.feccorrida = CA.feccorrida ) ");
		sql.append("                                        INNER JOIN empresa EM ON EM.empresa_id = CO.empresacorrida_id ");
		sql.append("                                        INNER JOIN ruta RU ON RU.ruta_id = CO.ruta_id ");
		sql.append("                                 WHERE  CA.activo = 1 AND RU.activo = 1 AND EM.activo = 1 AND ORI.activo = 1 AND DES.activo = 1 ");
		sql.append("                                        AND CO.activo = 1 ");
		sql.append(("                                       AND CO.EMPRESACORRIDA_ID IN (") + empresaIds + ") ");
		sql.append("		                                AND CA.FECCORRIDA BETWEEN to_date('" + dataDe + "','dd/mm/yyyy HH24:mi:ss') AND to_date('" + dataAte + "','dd/mm/yyyy HH24:mi:ss') ");
		sql.append("                                        AND CA.motivocancelacion_id IS NULL ");
		
		if(StringUtils.isNotBlank(CONSTANTE_GRATUIDADE_CRIANCA)) {
			sql.append("                                        AND CA.CATEGORIA_ID <> ").append(CONSTANTE_GRATUIDADE_CRIANCA);
		}
		
		sql.append("                                        AND CA.preciobase IS NOT NULL ");
		sql.append((bilhetesGratuitos ? " AND CA.PRECIOBASE >= 0 " : " AND CA.PRECIOBASE > 0 "));
		sql.append("                                 GROUP  BY RU.ruta_id, ");
		sql.append("                                           EM.nombempresa, ");
		sql.append("                                           ORI.cveparada, ");
		sql.append("                                           DES.cveparada, ");
		sql.append("                                           CA.numkmviaje, ");
		sql.append("                                           CO.corrida_id, ");
		sql.append("                                           RU.descruta, ");
		sql.append("                                           RU.indsentidoida, ");
		sql.append("                                           CA.preciobase, ");
		sql.append("                                           CO.origen_id,");
		sql.append("                                           CO.destino_id ");
		sql.append("                                           ) RESULTADO ");
		sql.append("                                INNER JOIN ruta_combinacion RS on RS.ruta_Id = RESULTADO.ruta_id ");
		sql.append("                                INNER JOIN tramo TR ON TR.tramo_id  = RS.tramo_id and (TR.origen_id = RESULTADO.ORIGEN_ID and TR.destino_id = RESULTADO.destino_id) ");
		sql.append("                          WHERE  RS.activo = 1 AND TR.activo = 1 ");
		sql.append("                          GROUP  BY RESULTADO.corrida_id, ");
		sql.append("                                    RESULTADO.origem, ");
		sql.append("                                    RESULTADO.destino, ");
		sql.append("                                    RESULTADO.km_tramo, ");
		sql.append("                                    RESULTADO.ruta_id, ");
		sql.append("                                    RESULTADO.origen_id, ");
		sql.append("                                    RESULTADO.destino_id, ");
		sql.append("                                    RESULTADO.preciobase) RESULTADO_2 ");
		sql.append("                   GROUP  BY RESULTADO_2.corrida_id ");
		sql.append("                   ORDER  BY RESULTADO_2.corrida_id)T2 ");
		sql.append("               ON T1.corrida_1 = T2.corrida_2 ");

		return sql.toString();
	}

	public class ParadaRelatorioOD {
		private String descParada;
		private String cveParada;
		private Integer numSecuencia;

		public ParadaRelatorioOD(String descParada, String cveParada, Integer numSecuencia) {
			super();
			this.descParada = descParada;
			this.cveParada = cveParada;
			this.numSecuencia = numSecuencia;
		}

		public String getDescParada() {
			return descParada;
		}

		public void setDescParada(String descParada) {
			this.descParada = descParada;
		}

		public Integer getNumSecuencia() {
			return numSecuencia;
		}

		public void setNumSecuencia(Integer numSecuencia) {
			this.numSecuencia = numSecuencia;
		}

		public String getCveParada() {
			return cveParada;
		}

		public void setCveParada(String cveParada) {
			this.cveParada = cveParada;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + getOuterType().hashCode();
			result = prime * result + ((cveParada == null) ? 0 : cveParada.hashCode());
			result = prime * result + ((descParada == null) ? 0 : descParada.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			ParadaRelatorioOD other = (ParadaRelatorioOD) obj;
			if (!getOuterType().equals(other.getOuterType()))
				return false;
			if (cveParada == null) {
				if (other.cveParada != null)
					return false;
			} else if (!cveParada.equals(other.cveParada))
				return false;
			if (descParada == null) {
				if (other.descParada != null)
					return false;
			} else if (!descParada.equals(other.descParada))
				return false;
			return true;
		}

		private RelatorioOrigemDestino getOuterType() {
			return RelatorioOrigemDestino.this;
		}
	}

	private String buscarConstante(String nomeConstante) {
		ConstanteService constanteService = (ConstanteService) AppContext.getApplicationContext().getBean("constanteService");
		return constanteService.buscarPorNomeConstante(nomeConstante).getValorconstante();
	}
}
