/**
 * 
 */
package com.rjconsultores.ventaboletos.relatorios.impl;

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

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

import com.rjconsultores.ventaboletos.relatorios.utilitarios.AproveitamentoBean;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.DataSource;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.Relatorio;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.RelatorioAproveitamentoBean;
import com.rjconsultores.ventaboletos.service.ConstanteService;
import com.rjconsultores.ventaboletos.web.utilerias.CurrencyUtil;
import com.rjconsultores.ventaboletos.web.utilerias.NamedParameterStatement;
import com.rjconsultores.ventaboletos.web.utilerias.spring.AppContext;

/**
 * @author Bruno H. G. Gouvêa <bruno@rjconsultores.com.br>
 * 
 */
public class RelatorioAproveitamento extends Relatorio {

	private List<RelatorioAproveitamentoBean> lsDadosRelatorio;

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

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

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

				List<AproveitamentoBean> aproveitamentoList = new ArrayList<AproveitamentoBean>();

				NamedParameterStatement stmt = new NamedParameterStatement(conexao, getSql());
				stmt.setInt("CORRIDA_ID", Integer.valueOf((String) parametros.get("CORRIDA_ID")));
				stmt.setDate("FECCORRIDA", (java.sql.Date) parametros.get("FECCORRIDA"));

				ResultSet rset = stmt.executeQuery();
				while (rset.next()) {

					AproveitamentoBean ab = new AproveitamentoBean();
					ab.setTrechoArrecadado((BigDecimal) rset.getObject("TOTAL_ARRECADADO"));
					ab.setTotalAsientos((BigDecimal) rset.getObject("TOTAL_ASIENTOS"));
					ab.setOrigenId((BigDecimal) rset.getObject("ORIGEN_ID") == null ? null : ((BigDecimal) rset.getObject("ORIGEN_ID")).intValue());
					ab.setDestinoId((BigDecimal) rset.getObject("DESTINO_ID") == null ? null : ((BigDecimal) rset.getObject("DESTINO_ID")).intValue());
					ab.setKmNominal((BigDecimal) rset.getObject("KM_NOMINAL"));
					ab.setTotalOcupados((String) rset.getObject("TOTAL_OCUPADOS") == null ? null : new BigDecimal((String) rset.getObject("TOTAL_OCUPADOS")));
					ab.setKmCorrida((BigDecimal) rset.getObject("KM_CORRIDA"));
					ab.setTarifa((BigDecimal) rset.getObject("TARIFA"));

					BigDecimal gratuido = (BigDecimal) rset.getObject("GRATUITO") == null ? null : ((BigDecimal) rset.getObject("GRATUITO"));
					ab.setGratuito(gratuido == BigDecimal.ZERO ? false : true);
					BigDecimal vendidos = (BigDecimal) rset.getObject("VENDIDOS") == null ? null : ((BigDecimal) rset.getObject("VENDIDOS"));
					ab.setVendidos(vendidos == BigDecimal.ZERO ? false : true);

					aproveitamentoList.add(ab);
				}

				BigDecimal totalArrecadado = BigDecimal.ZERO;
				BigDecimal totalNominal = BigDecimal.ZERO;
				BigDecimal kmCorrida = BigDecimal.ZERO;
				BigDecimal totalOcupados = BigDecimal.ZERO;

				BigDecimal ocupacao = BigDecimal.ONE;
				BigDecimal ocupacaoArrecadacao = BigDecimal.ONE;
				BigDecimal ocupacaoSemArrecadacao = BigDecimal.ONE;
				BigDecimal tarifa = BigDecimal.ONE;

				for (AproveitamentoBean ab : aproveitamentoList) {

					totalOcupados = ab.getTotalOcupados();
					kmCorrida = ab.getKmCorrida();
					tarifa = ab.getTarifa();

					totalArrecadado = totalArrecadado.add(ab.getTrechoArrecadado());
					ocupacao = ocupacao.add(ab.getTotalAsientos().multiply(ab.getKmNominal()));

					if (ab.getGratuito()) {
						ocupacaoSemArrecadacao = ocupacaoSemArrecadacao.add(ab.getTotalAsientos().multiply(ab.getKmNominal()));
					} else {
						ocupacaoArrecadacao = ocupacaoArrecadacao.add(ab.getTotalAsientos().multiply(ab.getKmNominal()));
					}
				}

				totalNominal = tarifa.multiply(totalOcupados);

				BigDecimal arrecadadoKm = BigDecimal.ONE;
				BigDecimal nominalKmFinal = BigDecimal.ONE;
				try {
					arrecadadoKm = totalArrecadado.divide(kmCorrida, 4, RoundingMode.HALF_EVEN);
					nominalKmFinal = totalNominal.divide(kmCorrida, 4, RoundingMode.HALF_EVEN);
					ocupacao = ocupacao.divide(totalOcupados.multiply(kmCorrida), 4, RoundingMode.HALF_EVEN);
					ocupacaoSemArrecadacao = ocupacaoSemArrecadacao.divide(totalOcupados.multiply(kmCorrida), 4, RoundingMode.HALF_EVEN);
					ocupacaoArrecadacao = ocupacaoArrecadacao.divide(totalOcupados.multiply(kmCorrida), 4, RoundingMode.HALF_EVEN);

				} catch (ArithmeticException e) {
					arrecadadoKm = BigDecimal.ZERO;
					nominalKmFinal = BigDecimal.ZERO;
					ocupacao = BigDecimal.ZERO;
					ocupacaoSemArrecadacao = BigDecimal.ZERO;
					ocupacaoArrecadacao = BigDecimal.ZERO;
				}

				Locale locale = new Locale("pt", "BR");
				parametros.put("P_TOTAL_ARRECADADO", CurrencyUtil.getCurrencyBigDecimalFromStr(totalArrecadado, locale));
				parametros.put("P_TOTAL_NOMINAL", CurrencyUtil.getCurrencyBigDecimalFromStr(totalNominal, locale));

				parametros.put("P_ARRECADO_KM", CurrencyUtil.getCurrencyBigDecimalFromStr(arrecadadoKm, locale));
				parametros.put("P_NOMINAL_KM", CurrencyUtil.getCurrencyBigDecimalFromStr(nominalKmFinal, locale));

				parametros.put("P_OCUPACAO", CurrencyUtil.getPercentBigDecimalFromStr(ocupacao, locale));
				parametros.put("P_OCUPACAO_ARRECADACAO", CurrencyUtil.getPercentBigDecimalFromStr(ocupacaoArrecadacao, locale));
				parametros.put("P_OCUPACAO_S_ARRECADACAO", CurrencyUtil.getPercentBigDecimalFromStr(ocupacaoSemArrecadacao, locale));

				NamedParameterStatement nps = new NamedParameterStatement(conexao, getSqlDetail());

				nps.setInt("CORRIDA_ID", Integer.valueOf((String) parametros.get("CORRIDA_ID")));
				nps.setDate("FECCORRIDA", (java.sql.Date) parametros.get("FECCORRIDA"));

				rset = nps.executeQuery();

				lsDadosRelatorio = new ArrayList<RelatorioAproveitamentoBean>();

				while (rset.next()) {

					RelatorioAproveitamentoBean aproveitamentoBean = new RelatorioAproveitamentoBean();
					aproveitamentoBean.setCveparada((String) rset.getObject("CVEPARADA"));
					aproveitamentoBean.setAsiento((BigDecimal) rset.getObject("ASIENTO"));
					aproveitamentoBean.setOcupado((BigDecimal) rset.getObject("OCUPADO"));
					aproveitamentoBean.setOcupadoOperacao((BigDecimal) rset.getObject("OCUPADO_OPERACAO"));
					aproveitamentoBean.setNumsecuencia((BigDecimal) rset.getObject("NUMSECUENCIA"));

					lsDadosRelatorio.add(aproveitamentoBean);
				}

				Integer asiento = 1;
				BigDecimal ocupado = null;
				Integer secOcupado = 0;

				for (RelatorioAproveitamentoBean i : lsDadosRelatorio) {
					if (asiento.equals(i.getAsiento().intValue())) {
						if (i.getOcupado() != null) {
							if (secOcupado.equals(0)) {
								secOcupado++;
								ocupado = i.getOcupado();
								i.setOcupado(new BigDecimal(secOcupado));
							} else {
								if (!i.getOcupado().equals(ocupado)) {
									secOcupado++;
									ocupado = i.getOcupado();
									i.setOcupado(new BigDecimal(secOcupado));
								} else {
									i.setOcupado(new BigDecimal(secOcupado));
								}
							}

						}
					} else {
						secOcupado = 0;
						if (i.getOcupado() != null)
							i.setOcupado(BigDecimal.ONE);
					}

					asiento = i.getAsiento().intValue();
				}

				setLsDadosRelatorio(lsDadosRelatorio);

			}
		});

	}

	private String getSqlDetail() {

		StringBuilder sql = new StringBuilder();
		sql.append("SELECT DISTINCT PR.CVEPARADA AS CVEPARADA, ");
		sql.append("                TO_NUMBER(DD.ASIENTO)      AS ASIENTO, ");
		sql.append("                (SELECT BO.BOLETO_ID ");
		sql.append("                 FROM   BOLETO BO, ");
		sql.append("                        CORRIDA_TRAMO CTD, ");
		sql.append("                        CORRIDA_TRAMO CTO ");
		sql.append("                 WHERE  BO.CORRIDA_ID = CR.CORRIDA_ID ");
		sql.append("                        AND BO.FECCORRIDA = CR.FECCORRIDA ");
		sql.append("                        AND BO.NUMASIENTO = DD.ASIENTO ");
		sql.append("                        AND BO.ORIGEN_ID = CTO.ORIGEN_ID ");
		sql.append("                        AND BO.DESTINO_ID = CTD.DESTINO_ID ");
		sql.append("                        AND CTD.CORRIDA_ID = CR.CORRIDA_ID ");
		sql.append("                        AND CTD.FECCORRIDA = CR.FECCORRIDA ");
		sql.append("                        AND CTO.CORRIDA_ID = CR.CORRIDA_ID ");
		sql.append("                        AND CTO.FECCORRIDA = CR.FECCORRIDA ");
		sql.append("                        AND CTO.ACTIVO = 1 ");
		sql.append("                        AND CTD.ACTIVO = 1 ");
		sql.append("                        AND VT.NUMSECUENCIA BETWEEN ");
		sql.append("                            CTO.NUMSECUENCIA AND CTD.NUMSECUENCIA + 1 ");
		sql.append("                        AND BO.ACTIVO = 1 ");
		sql.append("                        AND ( BO.MOTIVOCANCELACION_ID IS NULL ");
		sql.append("                               OR BO.MOTIVOCANCELACION_ID = 0 ) ");
		sql.append("                        AND ROWNUM = 1)    OCUPADO, ");
		sql.append("                (SELECT DECODE(AE.VENDIBLE, 1, 1, ");
		sql.append("                                            0, 2) ");
		sql.append("                 FROM   ASIENTO_EXCLUSIVO AE, ");
		sql.append("                        CORRIDA_TRAMO CTD, ");
		sql.append("                        CORRIDA_TRAMO CTO ");
		sql.append("                 WHERE  AE.CORRIDA_ID = CR.CORRIDA_ID ");
		sql.append("                        AND AE.FECCORRIDA = CR.FECCORRIDA ");
		sql.append("                        AND AE.NUMASIENTO = DD.ASIENTO ");
		sql.append("                        AND AE.PARADA_ID = CTO.ORIGEN_ID ");
		sql.append("                        AND NVL(AE.DESTINO_ID, CR.DESTINO_ID) = CTD.DESTINO_ID ");
		sql.append("                        AND CTD.CORRIDA_ID = CR.CORRIDA_ID ");
		sql.append("                        AND CTD.FECCORRIDA = CR.FECCORRIDA ");
		sql.append("                        AND CTO.CORRIDA_ID = CR.CORRIDA_ID ");
		sql.append("                        AND CTO.FECCORRIDA = CR.FECCORRIDA ");
		sql.append("                        AND CTO.ACTIVO = 1 ");
		sql.append("                        AND CTD.ACTIVO = 1 ");
		sql.append("                        AND VT.NUMSECUENCIA BETWEEN ");
		sql.append("                            CTO.NUMSECUENCIA AND CTD.NUMSECUENCIA + 1 ");
		sql.append("                        AND AE.ACTIVO = 1) OCUPADO_OPERACAO, ");
		sql.append("                VT.NUMSECUENCIA AS NUMSECUENCIA ");
		sql.append("FROM   CORRIDA CR, ");
		sql.append("       (SELECT CT.ORIGEN_ID PARADA_ID, ");
		sql.append("               CT.NUMSECUENCIA ");
		sql.append("        FROM   CORRIDA_TRAMO CT ");
		sql.append("        WHERE  CT.CORRIDA_ID = :CORRIDA_ID ");
		sql.append("               AND TRUNC(CT.FECCORRIDA) = :FECCORRIDA ");
		sql.append("               AND CT.ACTIVO = 1 ");
		sql.append("        UNION ");
		sql.append("        SELECT CT.DESTINO_ID, ");
		sql.append("               CT.NUMSECUENCIA + 1 ");
		sql.append("        FROM   CORRIDA_TRAMO CT ");
		sql.append("        WHERE  CT.CORRIDA_ID = :CORRIDA_ID ");
		sql.append("               AND TRUNC(CT.FECCORRIDA) = :FECCORRIDA ");
		sql.append("               AND CT.ACTIVO = 1 ");
		sql.append("        ORDER  BY 2) VT, ");
		sql.append("       PARADA PR, ");
		sql.append("       ROL_OPERATIVO RO, ");
		sql.append("       DET_DIAGRAMA_AUTOBUS DD ");
		sql.append("WHERE  CR.CORRIDA_ID = :CORRIDA_ID ");
		sql.append("       AND TRUNC(CR.FECCORRIDA) = :FECCORRIDA ");
		sql.append("       AND VT.PARADA_ID = PR.PARADA_ID ");
		sql.append("       AND CR.ROLOPERATIVO_ID = RO.ROLOPERATIVO_ID ");
		sql.append("       AND RO.DIAGRAMAAUTOBUS_ID = DD.DIAGRAMAAUTOBUS_ID ");
		sql.append("       AND DD.VENDIBLE = 1 ");
		sql.append("ORDER  BY TO_NUMBER(DD.ASIENTO), ");
		sql.append("          VT.NUMSECUENCIA ");

		return sql.toString();
	}

	private String getSql() {

		ConstanteService constanteService = (ConstanteService) AppContext.getApplicationContext().getBean("constanteService");
		StringBuilder sql = new StringBuilder();
		sql.append("SELECT ");
		sql.append("    SUM(TRECHOS_VG.PRECIOPAGADO) AS TOTAL_ARRECADADO, ");
		sql.append("    COUNT(TRECHOS_VG.BOLETO_ID)  AS TOTAL_ASIENTOS, ");
		sql.append("    TRECHOS_VG.ORIGEN_ID         AS ORIGEN_ID, ");
		sql.append("    TRECHOS_VG.DESTINO_ID        AS DESTINO_ID, ");
		sql.append("    TRECHOS_VG.GRATUITO          AS GRATUITO, ");
		sql.append("    TRECHOS_VG.VENDIDOS          AS VENDIDOS, ");
		sql.append("    TRECHOS_VG.CANTKMREAL        AS KM_NOMINAL, ");
		sql.append("    TRECHOS_VG.DESCROLOPERATIVO  AS TOTAL_OCUPADOS, ");
		sql.append("    TRECHOS_VG.KM_CORRIDA        AS KM_CORRIDA, ");
		sql.append("    TRECHOS_VG.TARIFA            AS TARIFA ");
		sql.append("FROM ");
		sql.append("    ( ");
		sql.append("        SELECT ");
		sql.append("            BO.PRECIOPAGADO, ");
		sql.append("            BO.BOLETO_ID  AS BOLETO_ID, ");
		sql.append("            BO.ORIGEN_ID  AS ORIGEN_ID, ");
		sql.append("            BO.DESTINO_ID AS DESTINO_ID, ");
		sql.append("            BO.NUMKMVIAJE AS CANTKMREAL, ");
		sql.append("            CASE WHEN BO.PRECIOBASE = 0 THEN 1 ELSE 0 END AS GRATUITO, ");
		sql.append("            CASE WHEN BO.PRECIOBASE > 0 THEN 1 ELSE 0 END AS VENDIDOS, ");
		sql.append("            RO.DESCROLOPERATIVO, ");
		sql.append("            (SELECT SUM(CANTKMREAL) FROM CORRIDA_TRAMO BO ");
		sql.append("                INNER JOIN TRAMO T ON T.TRAMO_ID = BO.TRAMO_ID ");
		sql.append("                WHERE BO.CORRIDA_ID = :CORRIDA_ID ");
		sql.append("                AND BO.FECCORRIDA = :FECCORRIDA ");
		sql.append("                AND BO.ACTIVO = 1) AS KM_CORRIDA, ");
		sql.append("            (SELECT TF.PRECIO FROM CORRIDA CR ");
		sql.append("                INNER JOIN TRAMO TR ON TR.ORIGEN_ID = CR.ORIGEN_ID AND TR.DESTINO_ID = CR.DESTINO_ID ");
		sql.append("                INNER JOIN TARIFA TF ON TF.CLASESERVICIO_ID = CR.CLASESERVICIO_ID ");
		sql.append("                AND TF.MARCA_ID = CR.MARCA_ID ");
		sql.append("                AND TF.RUTA_ID = CR.RUTA_ID ");
		sql.append("                AND TF.TRAMO_ID = TR.TRAMO_ID ");
		sql.append("                INNER JOIN VIGENCIA_TARIFA VT ON TF.VIGENCIATARIFA_ID = VT.VIGENCIATARIFA_ID ");
		sql.append("                WHERE CR.CORRIDA_ID = :CORRIDA_ID ");
		sql.append("                AND CR.FECCORRIDA = :FECCORRIDA ");
		sql.append("                AND TF.STATUSTARIFA = 'A' ");
		sql.append("                AND TF.ACTIVO = 1 ");
		sql.append("                AND VT.ACTIVO = 1 ");
		sql.append("                AND CR.FECCORRIDA BETWEEN VT.FECINICIOVIGENCIA AND VT.FECFINVIGENCIA) AS TARIFA ");
		sql.append("        FROM ");
		sql.append("            BOLETO BO ");
		sql.append("        INNER JOIN CORRIDA CR ON BO.CORRIDA_ID = CR.CORRIDA_ID AND BO.FECCORRIDA = CR.FECCORRIDA ");
		sql.append("        INNER JOIN ROL_OPERATIVO RO ON RO.ROLOPERATIVO_ID = CR.ROLOPERATIVO_ID ");
		sql.append("        INNER JOIN DET_DIAGRAMA_AUTOBUS DD ON RO.DIAGRAMAAUTOBUS_ID = DD.DIAGRAMAAUTOBUS_ID ");
		sql.append("        WHERE ");
		sql.append("            BO.CORRIDA_ID = :CORRIDA_ID ");
		sql.append("        AND BO.FECCORRIDA = :FECCORRIDA ");
		sql.append("        AND CR.ACTIVO = 1 ");
		sql.append("        AND BO.ACTIVO = 1 ");
		sql.append("        AND BO.INDSTATUSOPERACION = 'F' ");
		sql.append("        AND BO.CATEGORIA_ID <> ");
		sql.append(constanteService.buscarPorNomeConstante("GRATUIDADE_CRIANCA").getValorconstante());
		sql.append("        AND BO.MOTIVOCANCELACION_ID IS NULL ");
		sql.append("        GROUP BY ");
		sql.append("            BO.PRECIOPAGADO, ");
		sql.append("            BO.BOLETO_ID, ");
		sql.append("            BO.ORIGEN_ID, ");
		sql.append("            BO.DESTINO_ID, ");
		sql.append("            BO.NUMKMVIAJE, ");
		sql.append("            (CASE WHEN BO.PRECIOBASE = 0 THEN 1 ELSE 0 END), ");
		sql.append("            (CASE WHEN BO.PRECIOBASE > 0 THEN 1 ELSE 0 END), ");
		sql.append("            RO.DESCROLOPERATIVO ");
		sql.append("        ORDER BY ");
		sql.append("            BO.ORIGEN_ID, ");
		sql.append("            BO.DESTINO_ID ) TRECHOS_VG ");
		sql.append("GROUP BY ");
		sql.append("    TRECHOS_VG.ORIGEN_ID, ");
		sql.append("    TRECHOS_VG.DESTINO_ID, ");
		sql.append("    TRECHOS_VG.GRATUITO, ");
		sql.append("    TRECHOS_VG.VENDIDOS, ");
		sql.append("    TRECHOS_VG.CANTKMREAL, ");
		sql.append("    TRECHOS_VG.DESCROLOPERATIVO, ");
		sql.append("    TRECHOS_VG.KM_CORRIDA, ");
		sql.append("    TRECHOS_VG.TARIFA");

		return sql.toString();
	}

	public List<RelatorioAproveitamentoBean> getLsDadosRelatorio() {
		return lsDadosRelatorio;
	}

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

	@Override
	protected void processaParametros() throws Exception {
	}

}
