package com.rjconsultores.ventaboletos.relatorios.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

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

import org.apache.log4j.Logger;

import com.rjconsultores.ventaboletos.entidad.Corrida;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.GrupoRuta;
import com.rjconsultores.ventaboletos.entidad.Ruta;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.DataSource;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.Relatorio;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.RelatorioLinhasHorarioBean;
import com.rjconsultores.ventaboletos.service.ConstanteService;
import com.rjconsultores.ventaboletos.web.utilerias.NamedParameterStatement;
import com.rjconsultores.ventaboletos.web.utilerias.spring.AppContext;

public class RelatorioLinhasHorario extends Relatorio {

	private static Logger log = Logger.getLogger(RelatorioLinhasHorario.class);
	private List<RelatorioLinhasHorarioBean> lsDadosRelatorio;
	private static String CONSTANTE_GRATUIDADE_CRIANCA;

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

		this.setCustomDataSource(new DataSource(this) {
			@Override
			public void initDados() throws Exception {

				CONSTANTE_GRATUIDADE_CRIANCA = buscarConstante("GRATUIDADE_CRIANCA");

				Connection conexao = this.relatorio.getConexao();

				Map<String, Object> parametros = this.relatorio.getParametros();

				@SuppressWarnings("unchecked")
				ArrayList<Ruta> lsNumLinha = (ArrayList<Ruta>) parametros.get("lsNumLinha");
				@SuppressWarnings("unchecked")
				ArrayList<Corrida> lsNumServico = (ArrayList<Corrida>) parametros.get("lsNumServico");

				String servicoFiltro = "";
				if (lsNumServico.size() > 0) {
					for (Corrida corrida : lsNumServico) {
						if (lsNumServico.indexOf(corrida) == 0) {
							servicoFiltro = "" + corrida.getId().getCorridaId();
						} else {
							servicoFiltro += ", " + corrida.getId().getCorridaId();
						}
					}
				} else {
					servicoFiltro = "TODOS";
				}
				parametros.put("SERVICO_FILTRO", servicoFiltro);

				String linhaFiltro = "";
				if (lsNumLinha.size() > 0) {
					for (Ruta ruta : lsNumLinha) {
						if (lsNumLinha.indexOf(ruta) == 0) {
							linhaFiltro = "" + ruta.getRutaId();
						} else {
							linhaFiltro += ", " + ruta.getRutaId();
						}
					}
				} else {
					linhaFiltro = "TODOS";
				}
				parametros.put("LINHA_FILTRO", linhaFiltro);

				Empresa empresa = (Empresa) parametros.get("EMPRESA");

				GrupoRuta grupoRuta = (GrupoRuta) parametros.get("GRUPORUTA");

				Integer tipoServico = (Integer) parametros.get("TIPOSERVICIO_ID");
				String sql = getSql(lsNumLinha, lsNumServico, empresa, tipoServico, grupoRuta);

				NamedParameterStatement stmt = new NamedParameterStatement(conexao, sql);
				ResultSet rset = null;

				stmt.setTimestamp("DATA_INICIO", (Timestamp) parametros.get("DATA_INICIO"));
				stmt.setTimestamp("DATA_FINAL", (Timestamp) parametros.get("DATA_FINAL"));

				rset = stmt.executeQuery();

				lsDadosRelatorio = new ArrayList<RelatorioLinhasHorarioBean>();

				BigDecimal totalPassagens = BigDecimal.ZERO;
				BigDecimal totalSeguro = BigDecimal.ZERO;
				BigDecimal totalBagagens = BigDecimal.ZERO;
				BigDecimal totalSeuroOpcional = BigDecimal.ZERO;
				BigDecimal totalTotal = BigDecimal.ZERO;
				BigDecimal totalOrdinario = BigDecimal.ZERO;
				BigDecimal totalExtra = BigDecimal.ZERO;
				BigDecimal totalViagem = BigDecimal.ZERO;
				BigDecimal totalKmRodado = BigDecimal.ZERO;
				BigDecimal totalAbsoluto = BigDecimal.ZERO;
				BigDecimal totalEquivalente = BigDecimal.ZERO;
				BigDecimal mediaMPA = BigDecimal.ZERO;
				BigDecimal mediaMPE = BigDecimal.ZERO;
				BigDecimal mediaRsPorKm = BigDecimal.ZERO;
				BigDecimal totalEQ = BigDecimal.ZERO;
				BigDecimal mediaRSPorViagem = BigDecimal.ZERO;
				BigDecimal totalPaxKMOfertado = BigDecimal.ZERO;
				BigDecimal totalPaxKMTransportado = BigDecimal.ZERO;
				BigDecimal totalIAP = BigDecimal.ZERO;

				BigDecimal totalTxEmbarque = BigDecimal.ZERO;
				BigDecimal totalPedagio = BigDecimal.ZERO;

				String group = null;
				while (rset.next()) {
					RelatorioLinhasHorarioBean horarioBean = new RelatorioLinhasHorarioBean();

					group = ((String) rset.getObject("GRUPO_RUTA"));
					horarioBean.setGrupoRuta(group);
					horarioBean.setTipoLinha((String) rset.getObject("TIPO_LINHA"));
					horarioBean.setHora((String) rset.getObject("HORA"));
					horarioBean.setServico((BigDecimal) rset.getObject("SERVICO"));

					if (rset.getObject("SENTIDO") != null) {
						horarioBean.convetSentido((BigDecimal) rset.getObject("SENTIDO"));
					} else {
						horarioBean.convetSentido(null);
					}

					horarioBean.setLot((BigDecimal) rset.getObject("LOT"));
					horarioBean.setCla((String) rset.getObject("CLA"));
					horarioBean.setExtensao((BigDecimal) rset.getObject("EXTENSAO"));
					horarioBean.setTarifa((BigDecimal) rset.getObject("TARIFA"));
					horarioBean.setPassagens((BigDecimal) rset.getObject("PASSAGENS"));
					horarioBean.setSeguro((BigDecimal) rset.getObject("SEGURO"));
					horarioBean.setBagagens((BigDecimal) rset.getObject("BAGAGENS"));

					horarioBean.setTxEmbarque((BigDecimal) rset.getObject("TX_EMBARQUE"));
					horarioBean.setPedagio((BigDecimal) rset.getObject("PEDAGIO"));

					// Substituir a coluna Seg. Opcional por Tx. Embarque
					horarioBean.setSegOpc(horarioBean.getTxEmbarque());

					horarioBean.setOrd((BigDecimal) rset.getObject("ORD"));
					horarioBean.setExtra((BigDecimal) rset.getObject("EXTRA"));
					horarioBean.setAbsol((BigDecimal) rset.getObject("ABSOL"));

					horarioBean.setOrigem((String) rset.getObject("ORIGEM"));
					horarioBean.setDestino((String) rset.getObject("DESTINO"));
					horarioBean.setSomaExtensaoTrecho((BigDecimal) rset.getObject("EXTENSAO_TRECHO"));
					horarioBean.setPaxKmTransportado((BigDecimal) rset.getObject("KM_REAL"));
					horarioBean = trecho(horarioBean);

					horarioBean = calcTotal(horarioBean);
					horarioBean = calcMediaReceitaTotal(horarioBean);

					horarioBean = calcTotalViagem(horarioBean);
					horarioBean = calcKmRodado(horarioBean);
					horarioBean = calcEquivalente(horarioBean);
					horarioBean = calcMpa(horarioBean);
					horarioBean = calcMpe(horarioBean);
					horarioBean = calcRsKm(horarioBean);
					horarioBean = calcEq(horarioBean);
					horarioBean = calcRsViagem(horarioBean);
					horarioBean = calcPaxKmOfertado(horarioBean);
					horarioBean = calcIap(horarioBean);

					lsDadosRelatorio.add(horarioBean);

					totalPassagens = totalPassagens.add(horarioBean.getPassagens() != null ? horarioBean.getPassagens() : BigDecimal.ZERO);
					totalSeguro = totalSeguro.add(horarioBean.getSeguro() != null ? horarioBean.getSeguro() : BigDecimal.ZERO);
					totalBagagens = totalBagagens.add(horarioBean.getBagagens() != null ? horarioBean.getBagagens() : BigDecimal.ZERO);
					totalSeuroOpcional = totalSeuroOpcional.add(horarioBean.getSegOpc() != null ? horarioBean.getSegOpc() : BigDecimal.ZERO);
					totalTotal = totalTotal.add(horarioBean.getTotal() != null ? horarioBean.getTotal() : BigDecimal.ZERO);
					totalOrdinario = totalOrdinario.add(horarioBean.getOrd() != null ? horarioBean.getOrd() : BigDecimal.ZERO);
					totalExtra = totalExtra.add(horarioBean.getExtra() != null ? horarioBean.getExtra() : BigDecimal.ZERO);
					totalViagem = totalViagem.add(horarioBean.getTotalViagem() != null ? horarioBean.getTotalViagem() : BigDecimal.ZERO);
					totalKmRodado = totalKmRodado.add(horarioBean.getKmRodado() != null ? horarioBean.getKmRodado() : BigDecimal.ZERO);
					totalAbsoluto = totalAbsoluto.add(horarioBean.getAbsol() != null ? horarioBean.getAbsol() : BigDecimal.ZERO);
					totalEquivalente = totalEquivalente.add(horarioBean.getEquivalente() != null ? horarioBean.getEquivalente() : BigDecimal.ZERO);

					totalTxEmbarque = totalTxEmbarque.add(horarioBean.getTxEmbarque() != null ? horarioBean.getTxEmbarque() : BigDecimal.ZERO);
					totalPedagio = totalPedagio.add(horarioBean.getPedagio() != null ? horarioBean.getPedagio() : BigDecimal.ZERO);

					mediaMPA = mediaMPA.add(horarioBean.getMpa() != null ? horarioBean.getMpa() : BigDecimal.ZERO);
					mediaMPE = mediaMPE.add(horarioBean.getMpe() != null ? horarioBean.getMpe() : BigDecimal.ZERO);

					mediaRsPorKm = mediaRsPorKm.add(horarioBean.getRsKm() != null ? horarioBean.getRsKm() : BigDecimal.ZERO);

					totalEQ = totalEQ.add(horarioBean.getEq() != null ? horarioBean.getEq() : BigDecimal.ZERO);

					mediaRSPorViagem = mediaRSPorViagem.add(horarioBean.getRsViagem() != null ? horarioBean.getRsViagem() : BigDecimal.ZERO);

					totalPaxKMOfertado = totalPaxKMOfertado.add(horarioBean.getPaxKmOfertado() != null ? horarioBean.getPaxKmOfertado() : BigDecimal.ZERO);
					totalPaxKMTransportado = totalPaxKMTransportado.add(horarioBean.getPaxKmTransportado() != null ? horarioBean.getPaxKmTransportado() : BigDecimal.ZERO);

					totalIAP = calcTotalIap(totalPaxKMTransportado, totalPaxKMOfertado);

				}

				BigDecimal qtdeRegistros = new BigDecimal(lsDadosRelatorio.size());

				if (lsDadosRelatorio.size() > 0) {

					setLsDadosRelatorio(lsDadosRelatorio);
					parametros.put("TOTAL_PASSAGENS", totalPassagens);
					parametros.put("TOTAL_SEGURO", totalSeguro);
					parametros.put("TOTAL_BAGAGENS", totalBagagens);
					parametros.put("TOTAL_SEURO_OPCIONAL", totalSeuroOpcional);
					parametros.put("TOTAL_TOTAL", totalTotal);
					parametros.put("TOTAL_ORDINARIO", totalOrdinario);
					parametros.put("TOTAL_EXTRA", totalExtra);
					parametros.put("TOTAL_VIAGEM", totalViagem);
					parametros.put("TOTAL_KM_RODADO", totalKmRodado);
					parametros.put("TOTAL_ABSOLUTO", totalAbsoluto);
					parametros.put("TOTAL_EQUIVALENTE", totalEquivalente);
					parametros.put("MEDIA_MPA", mediaMPA.divide(qtdeRegistros, 2, 4));
					parametros.put("MEDIA_MPE", mediaMPE.divide(qtdeRegistros, 2, 4));
					parametros.put("MEDIA_RS_POR_KM", mediaRsPorKm.divide(qtdeRegistros, 2, 4));
					parametros.put("TOTAL_EQ", totalEQ);
					parametros.put("TOTAL_TX_EMBARQUE", totalTxEmbarque);
					parametros.put("TOTAL_PEDAGIO", totalPedagio);
					parametros.put("MEDIA_RS_POR_VIAGEM", mediaRSPorViagem.divide(qtdeRegistros, 2, 4));
					parametros.put("TOTAL_PAX_KM_OFERTADO", totalPaxKMOfertado);
					parametros.put("TOTAL_PAX_KM_TRANSPORTADO", totalPaxKMTransportado);
					parametros.put("TOTAL_IAP", totalIAP);

				}
			}
		});

	}

	public List<RelatorioLinhasHorarioBean> getLsDadosRelatorio() {

		return lsDadosRelatorio;
	}

	public void setLsDadosRelatorio(List<RelatorioLinhasHorarioBean> lsDadosRelatorio) {
		this.setCollectionDataSource(new JRBeanCollectionDataSource(lsDadosRelatorio));
		this.lsDadosRelatorio = lsDadosRelatorio;
	}

	private RelatorioLinhasHorarioBean trecho(RelatorioLinhasHorarioBean horarioBean) {
		horarioBean.setTrecho(horarioBean.getOrigem() + " - " + horarioBean.getDestino());
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcTotal(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal total = horarioBean.getPassagens();
		total = total.add(horarioBean.getBagagens());
		total = total.add(horarioBean.getSeguro());
		total = total.add(horarioBean.getPedagio());
		total = total.add(horarioBean.getTxEmbarque());
		horarioBean.setTotal(total);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcMediaReceitaTotal(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal mediaTotal = horarioBean.getPassagens();
		horarioBean.setMediaReceitaViagem(mediaTotal);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcTotalViagem(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal totalViagem = horarioBean.getOrd().add(horarioBean.getExtra());
		horarioBean.setTotalViagem(totalViagem);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcKmRodado(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal kmRodado = horarioBean.getTotalViagem().multiply(horarioBean.getExtensao());
		horarioBean.setKmRodado(kmRodado);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcEquivalente(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal equivalente = new BigDecimal(0);
		try {
			equivalente = horarioBean.getSomaExtensaoTrecho().divide(horarioBean.getExtensao(), 2, RoundingMode.HALF_UP);
		} catch (ArithmeticException e) {
			equivalente = BigDecimal.ZERO;
		} catch (NullPointerException nex) {
			equivalente = BigDecimal.ZERO;
		} catch (Exception ex) {
			log.error("", ex);
		}
		horarioBean.setEquivalente(equivalente);

		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcMpa(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal mpa = new BigDecimal(0);
		try {
			mpa = horarioBean.getAbsol().divide(horarioBean.getTotalViagem(), 2, 4);
		} catch (ArithmeticException e) {
			mpa = BigDecimal.ZERO;
		} catch (NullPointerException nex) {
			mpa = BigDecimal.ZERO;
		} catch (Exception ex) {
			log.error("", ex);
		}
		horarioBean.setMpa(mpa);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcMpe(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal mpe = horarioBean.getEquivalente().divide(horarioBean.getTotalViagem(), 2, 4);
		horarioBean.setMpe(mpe);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcRsKm(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal rsKm = horarioBean.getPassagens().divide(horarioBean.getKmRodado(), 2, 4);
		horarioBean.setRsKm(rsKm);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcEq(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal eq = null;
		try {
			eq = horarioBean.getMediaReceitaViagem().divide(horarioBean.getTarifa(), 2, 4);
		} catch (ArithmeticException e) {
			eq = BigDecimal.ZERO;
		} catch (NullPointerException nex) {
			eq = BigDecimal.ZERO;
		} catch (Exception ex) {
			log.error("", ex);
		}
		horarioBean.setEq(eq);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcRsViagem(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal RSViagem = horarioBean.getPassagens().divide(horarioBean.getTotalViagem(), 2, 4);
		horarioBean.setRsViagem(RSViagem);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcPaxKmOfertado(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal paxKmOfertado = horarioBean.getLot().multiply(horarioBean.getTotalViagem());
		paxKmOfertado = paxKmOfertado.multiply(horarioBean.getExtensao());
		horarioBean.setPaxKmOfertado(paxKmOfertado);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcIap(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal iap = null;
		BigDecimal CENTO = BigDecimal.TEN.multiply(BigDecimal.TEN);
		try {
			iap = (horarioBean.getPaxKmTransportado().multiply(CENTO)).divide(horarioBean.getPaxKmOfertado(), 2, 4);
		} catch (ArithmeticException e) {
			iap = BigDecimal.ZERO;
		} catch (NullPointerException nex) {
			iap = BigDecimal.ZERO;
		} catch (Exception ex) {
			log.error("", ex);
		}
		horarioBean.setIap(iap);
		return horarioBean;
	}

	private BigDecimal calcTotalIap(BigDecimal totalPaxKMTransportado, BigDecimal totalPaxKMOfertado) {
		BigDecimal iap = null;
		BigDecimal CENTO = BigDecimal.TEN.multiply(BigDecimal.TEN);
		try {
			iap = (totalPaxKMTransportado.multiply(CENTO)).divide(totalPaxKMOfertado, 2, 4);
		} catch (ArithmeticException e) {
			iap = BigDecimal.ZERO;
		} catch (NullPointerException nex) {
			iap = BigDecimal.ZERO;
		} catch (Exception ex) {
			log.error("", ex);
		}
		return iap;
	}

	@Override
	protected void processaParametros() throws Exception {
	}

	private String getSql(ArrayList<Ruta> lsNumLinha, ArrayList<Corrida> lsNumServico, Empresa empresa, Integer tipoServico, GrupoRuta grupoRuta) {

		StringBuffer sql = new StringBuffer();
		sql.append("SELECT ");
		sql.append("RUTA_ID, GRUPO_RUTA, HORA, SERVICO, SENTIDO , LOT, CLA, TARIFA, ORIGEM, DESTINO, ");
		sql.append("EXTENSAO, COALESCE(SUM(EQUIVALENTE * EXTENSAO) ,0) AS EXTENSAO_TRECHO, ");
		sql.append("COALESCE(BAGAGENS, 0) AS BAGAGENS, COALESCE(SUM(SEGURO), 0) AS SEGURO, ");
		sql.append("COALESCE(SUM(TX_EMBARQUE), 0) AS TX_EMBARQUE, ");
		sql.append("COALESCE(SUM(PEDAGIO), 0) AS PEDAGIO, ");
		sql.append("COALESCE(SUM(PASSAGENS), 0) AS PASSAGENS, ");
		sql.append("ORD, EXTRA, TIPO_LINHA, ABSOL, ");
		sql.append("COALESCE(SUM(KM_REAL), 0) AS KM_REAL ");
		sql.append("FROM ");
		sql.append("(SELECT ");
		sql.append("    R.RUTA_ID, ");
		sql.append("    NVL(GR.DESCGRUPO, 'Não Definido')  AS GRUPO_RUTA, ");
		sql.append("    TO_CHAR(C.FECHORSALIDA, 'HH24:MI') AS HORA, ");
		sql.append("    C.CORRIDA_ID                       AS SERVICO, ");
		sql.append("    R.INDSENTIDOIDA                    AS SENTIDO, ");
		sql.append("    DA.CANTASIENTOS                    AS LOT, ");
		sql.append("    NVL(CS.DESCCLASE, '')              AS CLA, ");
		sql.append("    MAX(NVL(TF.PRECIOORIGINAL, 0))     AS TARIFA, ");
		sql.append("    ORIGEM.CVEPARADA                   AS ORIGEM, ");
		sql.append("    DESTINO.CVEPARADA                  AS DESTINO, ");
		sql.append("    EXTENSAO                           AS EXTENSAO, ");
		sql.append("    CJ.EQUIVALENTE                     AS EQUIVALENTE, ");
		sql.append("    SUM(EE.IMPINGRESO)                 AS BAGAGENS, ");
		sql.append("    CJ.IMPORTESEGURO                   AS SEGURO, ");
		sql.append("    CJ.IMPORTETAXAEMBARQUE             AS TX_EMBARQUE, ");
		sql.append("    CJ.IMPORTEPEDAGIO                  AS PEDAGIO, ");
		sql.append("    CJ.PRECIOPAGADO                    AS PASSAGENS, ");
		sql.append("    CJ.BOLETO_ID, ");
		sql.append("    TB2.ORD, ");
		sql.append("    TB2.EXTRA, ");
		sql.append("    CASE WHEN CO.ESTADO_ID <> CD.ESTADO_ID THEN 'INTERESTADUAL' ELSE 'INTERMUNICIPAL' END TIPO_LINHA, ");
		sql.append("    ABSOL, ");
		sql.append("    CJ.KM_REAL AS KM_REAL ");
		sql.append("FROM ");
		sql.append("    (SELECT C.CORRIDA_ID, C.ROLOPERATIVO_ID, TO_CHAR(C.FECHORSALIDA, 'HH24:MI') AS HORASALIDA, ");
		sql.append("            COUNT(CASE WHEN C.TIPOSERVICIO_ID = 1 THEN 1 ELSE NULL END) AS ORD, ");
		sql.append("            COUNT(CASE WHEN C.TIPOSERVICIO_ID = 2 THEN 1 ELSE NULL END) AS EXTRA ");
		sql.append("        FROM CORRIDA C ");
		sql.append("        WHERE C.ACTIVO = 1");
		sql.append("        AND C.FECCORRIDA BETWEEN :DATA_INICIO AND :DATA_FINAL ");
		sql.append(empresa == null ? "" : "    AND C.MARCA_ID = " + empresa.getEmpresaId());
		sql.append("        GROUP BY C.CORRIDA_ID, C.ROLOPERATIVO_ID, TO_CHAR(C.FECHORSALIDA, 'HH24:MI')) TB2, ");
		sql.append("    (SELECT C.CORRIDA_ID, C.ROLOPERATIVO_ID, TO_CHAR(C.FECHORSALIDA, 'HH24:MI') AS HORASALIDA, ");
		sql.append("            COUNT(B.BOLETO_ID) AS ABSOL ");
		sql.append("        FROM CORRIDA C ");
		sql.append("        LEFT JOIN BOLETO B ON (B.CORRIDA_ID = C.CORRIDA_ID AND B.FECCORRIDA = C.FECCORRIDA ");
		sql.append("                  AND B.MOTIVOCANCELACION_ID IS NULL ");
		sql.append("                  AND B.CATEGORIA_ID <> ").append(CONSTANTE_GRATUIDADE_CRIANCA).append(") ");
		sql.append("        WHERE C.ACTIVO = 1 ");
		sql.append("        AND C.FECCORRIDA BETWEEN :DATA_INICIO AND :DATA_FINAL ");
		sql.append(empresa == null ? "" : "   AND C.MARCA_ID = " + empresa.getEmpresaId());
		sql.append("        GROUP BY C.CORRIDA_ID, C.ROLOPERATIVO_ID, TO_CHAR(C.FECHORSALIDA, 'HH24:MI')) TB4, ");
		sql.append("    CORRIDA C ");
		sql.append("LEFT JOIN ");
		sql.append("    (SELECT CO.FECCORRIDA, ");
		sql.append("    CO.CORRIDA_ID, ");
		sql.append("    CO.ROLOPERATIVO_ID, ");
		sql.append("    CO.RUTA_ID, ");
		sql.append("    CO.EMPRESACORRIDA_ID, ");
		sql.append("    BO.BOLETO_ID, ");
		sql.append("    BO.NUMKMVIAJE * COUNT(1) AS KM_REAL, ");
		sql.append("    ROUND(BO.NUMKMVIAJE * COUNT(1) / T.CANTKMREAL, 3) EQUIVALENTE, ");
		sql.append("    SUM(NVL(BO.IMPORTESEGURO, 0)) AS IMPORTESEGURO, ");
		sql.append("    SUM(NVL(BO.IMPORTETAXAEMBARQUE, 0)) AS IMPORTETAXAEMBARQUE, ");
		sql.append("    SUM(NVL(BO.IMPORTEPEDAGIO, 0)) AS IMPORTEPEDAGIO, ");
		sql.append("    SUM(NVL(BO.PRECIOPAGADO, 0)) AS PRECIOPAGADO ");
		sql.append("        FROM CORRIDA CO ");
		sql.append("        INNER JOIN BOLETO BO ON CO.CORRIDA_ID = BO.CORRIDA_ID AND CO.FECCORRIDA = BO.FECCORRIDA ");
		sql.append("		INNER JOIN RUTA_COMBINACION RC ON RC.RUTA_ID = CO.RUTA_ID ");
		sql.append("		INNER JOIN TRAMO T ON RC.TRAMO_ID = T.TRAMO_ID AND T.ORIGEN_ID = BO.ORIGEN_ID AND T.DESTINO_ID = BO.DESTINO_ID ");
		sql.append("        WHERE CO.ACTIVO = 1 ");
		sql.append("		AND RC.ACTIVO = 1");
		sql.append("		AND T.ACTIVO = 1");
		sql.append(empresa == null ? "" : "   AND CO.MARCA_ID = " + empresa.getEmpresaId());
		sql.append("        AND BO.INDSTATUSBOLETO != 'S' AND BO.MOTIVOCANCELACION_ID IS NULL ");
		sql.append("        AND BO.CATEGORIA_ID <> ").append(CONSTANTE_GRATUIDADE_CRIANCA);
		sql.append("        AND BO.FECCORRIDA BETWEEN :DATA_INICIO AND :DATA_FINAL ");

		if (lsNumServico.size() > 0) {
			for (Corrida corrida : lsNumServico) {
				if (lsNumServico.indexOf(corrida) == 0) {
					sql.append("   AND BO.CORRIDA_ID IN     (   " + corrida.getId().getCorridaId());
				} else {
					sql.append("   ,  " + corrida.getId().getCorridaId() + "   ");
				}
			}
			sql.append("    )    ");
		}

		sql.append("        GROUP BY CO.FECCORRIDA, CO.CORRIDA_ID, CO.ROLOPERATIVO_ID, CO.RUTA_ID, CO.EMPRESACORRIDA_ID, BO.NUMKMVIAJE, BO.BOLETO_ID, T.CANTKMREAL) CJ ");
		sql.append("            ON (CJ.CORRIDA_ID = C.CORRIDA_ID AND CJ.FECCORRIDA = C.FECCORRIDA AND CJ.ROLOPERATIVO_ID = C.ROLOPERATIVO_ID ");
		sql.append("            AND CJ.RUTA_ID = C.RUTA_ID AND CJ.EMPRESACORRIDA_ID = C.EMPRESACORRIDA_ID) ");
		sql.append("INNER JOIN PARADA ORIGEM ON (C.ORIGEN_ID = ORIGEM.PARADA_ID ) ");
		sql.append("INNER JOIN PARADA DESTINO ON ( C.DESTINO_ID = DESTINO.PARADA_ID ) ");
		sql.append("INNER JOIN CIUDAD CO ON (CO.CIUDAD_ID = ORIGEM.CIUDAD_ID ) ");
		sql.append("INNER JOIN CIUDAD CD ON (CD.CIUDAD_ID = DESTINO.CIUDAD_ID ) ");
		sql.append("INNER JOIN RUTA R ON (C.RUTA_ID = R.RUTA_ID ) ");
		sql.append("LEFT JOIN GRUPO_RUTA GR ON (R.GRUPORUTA_ID = GR.GRUPORUTA_ID ) ");
		sql.append("LEFT JOIN ROL_OPERATIVO RO ON (C.ROLOPERATIVO_ID = RO.ROLOPERATIVO_ID ) ");
		sql.append("LEFT JOIN DIAGRAMA_AUTOBUS DA ON (DA.DIAGRAMAAUTOBUS_ID = RO.DIAGRAMAAUTOBUS_ID ) ");
		sql.append("LEFT JOIN CLASE_SERVICIO CS ON (CS.CLASESERVICIO_ID = C.CLASESERVICIO_ID ) ");
		sql.append("LEFT JOIN EVENTO_EXTRA EE ON (EE.CORRIDA_ID = C.CORRIDA_ID AND EE.FECCORRIDA = C.FECCORRIDA AND EE.TIPOEVENTOEXTRA_ID = 1 ) ");
		sql.append("LEFT JOIN TARIFA TF ON (TF.CLASESERVICIO_ID = C.CLASESERVICIO_ID AND TF.DESTINO_ID = C.DESTINO_ID AND TF.ORIGEN_ID = C.ORIGEN_ID AND TF.MARCA_ID = C.MARCA_ID AND TF.RUTA_ID = C.RUTA_ID ) ");
		sql.append("LEFT JOIN VIGENCIA_TARIFA VTF ON (TF.VIGENCIATARIFA_ID = VTF.VIGENCIATARIFA_ID AND C.FECCORRIDA BETWEEN VTF.FECINICIOVIGENCIA AND VTF.FECFINVIGENCIA ) ");
		sql.append("INNER JOIN ");
		sql.append("( ");
		sql.append("SELECT RC.RUTA_ID, T.ORIGEN_ID, T.DESTINO_ID, NVL(T.CANTKMREAL,0) AS EXTENSAO ");
		sql.append("FROM RUTA_COMBINACION RC ");
		sql.append("INNER JOIN TRAMO T ON RC.TRAMO_ID = T.TRAMO_ID ");
		sql.append("WHERE RC.ACTIVO = 1 ");
		sql.append(") TB5 ON TB5.RUTA_ID = C.RUTA_ID ");
		sql.append("AND TB5.ORIGEN_ID = ORIGEM.PARADA_ID ");
		sql.append("AND TB5.DESTINO_ID = DESTINO.PARADA_ID ");
		sql.append("WHERE TB2.CORRIDA_ID = C.CORRIDA_ID ");
		sql.append("AND TB2.ROLOPERATIVO_ID = C.ROLOPERATIVO_ID ");
		sql.append("AND TB2.HORASALIDA = TO_CHAR(C.FECHORSALIDA, 'HH24:MI') ");
		sql.append("AND TB4.CORRIDA_ID = C.CORRIDA_ID ");
		sql.append("AND TB4.ROLOPERATIVO_ID = C.ROLOPERATIVO_ID ");
		sql.append("AND TB4.HORASALIDA = TO_CHAR(C.FECHORSALIDA, 'HH24:MI') ");
		sql.append("AND C.FECCORRIDA BETWEEN :DATA_INICIO AND :DATA_FINAL ");
		sql.append(empresa == null ? "" : "   AND C.MARCA_ID = " + empresa.getEmpresaId());

		if (lsNumServico.size() > 0) {
			for (Corrida corrida : lsNumServico) {
				if (lsNumServico.indexOf(corrida) == 0) {
					sql.append("   AND   C.CORRIDA_ID IN     (   " + corrida.getId().getCorridaId());
				} else {
					sql.append("   ,  " + corrida.getId().getCorridaId() + "   ");
				}
			}
			sql.append("    )    ");
		}

		sql.append(grupoRuta == null ? "" : "   AND    R.GRUPORUTA_ID IN (   " + grupoRuta.getGrupoRutaId() + "   )     ");

		if (lsNumLinha.size() > 0) {
			for (Ruta ruta : lsNumLinha) {
				if (lsNumLinha.indexOf(ruta) == 0) {
					sql.append("  AND   R.RUTA_ID  IN  (   " + ruta.getRutaId());
				} else {
					sql.append("   ,  " + ruta.getRutaId() + "    ");
				}
			}
			sql.append("    )    ");
		}

		sql.append(tipoServico > 0 ? "  AND   C.TIPOSERVICIO_ID =  " + tipoServico + "   " : "");

		sql.append(" AND C.ACTIVO <> 0 AND ORIGEM.ACTIVO = 1 AND DESTINO.ACTIVO = 1 ");
		sql.append("AND R.ACTIVO = 1 AND RO.ACTIVO = 1 AND DA.ACTIVO = 1 AND CS.ACTIVO = 1 ");
		sql.append("GROUP BY R.RUTA_ID, NVL(GR.DESCGRUPO, 'Não Definido'), TO_CHAR(C.FECHORSALIDA, 'HH24:MI'), C.CORRIDA_ID, R.INDSENTIDOIDA, ");
		sql.append("    DA.CANTASIENTOS, CS.DESCCLASE,  TB5.EXTENSAO, TB2.ORD, TB2.EXTRA, ABSOL, ");
		sql.append("    CO.ESTADO_ID, CD.ESTADO_ID, ORIGEM.CVEPARADA, DESTINO.CVEPARADA, CJ.PRECIOPAGADO, ");
		sql.append("    CJ.IMPORTESEGURO, CJ.IMPORTETAXAEMBARQUE, CJ.IMPORTEPEDAGIO, ");
		sql.append("    CJ.EQUIVALENTE, CJ.KM_REAL , CJ.BOLETO_ID ) ");
		sql.append("GROUP BY RUTA_ID, GRUPO_RUTA, HORA, SERVICO, SENTIDO, LOT, CLA, TARIFA, ORIGEM, DESTINO, ");
		sql.append("    EXTENSAO, BAGAGENS, ORD, EXTRA, TIPO_LINHA, ABSOL  ");
		sql.append("ORDER BY TIPO_LINHA, GRUPO_RUTA, SERVICO, ORIGEM, DESTINO ");

		return sql.toString();
	}

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