package com.rjconsultores.ventaboletos.relatorios.render;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Locale;
import java.util.ResourceBundle;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.export.JExcelApiExporter;
import net.sf.jasperreports.engine.export.JExcelApiExporterParameter;

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

import com.rjconsultores.ventaboletos.relatorios.utilitarios.Relatorio;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.SaidaRelatorio;
import com.rjconsultores.ventaboletos.utilerias.LocaleUtil;

/**
 * Implementação da classe abstrata de renderização acoplada a uma tecnologia de renderização especifica
 * 
 * @author Bruno H. G. Gouvêa <bruno@rjconsultores.com.br>
 * 
 */
public class RenderRelatorioJasper {
	
	private static Logger log = Logger.getLogger(Relatorio.class);

	protected JasperPrint jasperPrint;

	private Relatorio relatorio;
	
	/**
	 * @param relatorio
	 *            Enum do tipo Relatorio contendo as configurações de geração de todos os relatórios
	 * @param connection
	 *            Objeto de conexão do banco que será utilizado para geração do relatório, só deve ser passado se não for utilizado nenhum tipo de Custom Data Source
	 * 
	 * @throws Exception
	 *             Excessão contendo regra de utilização da classe
	 */
	public RenderRelatorioJasper(Relatorio relatorio) throws Exception {
		this.relatorio = relatorio;
	}
	
	public void preRender() {
		this.initBundler();
		this.initLocale();

	}

	private void initBundler() {
		// TODO Alterar para injeção de acordo com usuário logado ou outro meio para obter o Locale correto
		
		Locale locale = LocaleUtil.getLocale();
		try {

			ResourceBundle resource = ResourceBundle.getBundle("com.rjconsultores.ventaboletos.relatorios.internacionalizacao." + this.relatorio.getNome(), locale);
			this.relatorio.getParametros().put(JRParameter.REPORT_RESOURCE_BUNDLE, resource);
			
			/* Adicionar o arquivo de internacionalização para o subreporte quando informado */
			if(this.relatorio.getNomeSubReporte() != null && this.relatorio.getNomeSubReporte().length > 0) {
				if(this.relatorio.getNomeSubReporte().length == 1 && StringUtils.isNotBlank(this.relatorio.getNomeSubReporte()[0])) {
					ResourceBundle resourceSubReporte = ResourceBundle.getBundle("com.rjconsultores.ventaboletos.relatorios.internacionalizacao." + this.relatorio.getNomeSubReporte()[0], locale);
					this.relatorio.getParametros().put("SUBREPORT_RESOURCE_BUNDLE", resourceSubReporte);
				} else if(this.relatorio.getNomeSubReporte() != null && this.relatorio.getNomeSubReporte().length > 1) {
					int indice = 0;
					for (String nomeSubReporte : this.relatorio.getNomeSubReporte()) {
						if(StringUtils.isNotBlank(nomeSubReporte)) {
							ResourceBundle resourceSubReporte = ResourceBundle.getBundle("com.rjconsultores.ventaboletos.relatorios.internacionalizacao." + nomeSubReporte, locale);
							this.relatorio.getParametros().put("SUBREPORT_RESOURCE_BUNDLE" + "_" + (++indice), resourceSubReporte);
						}
					}
				}
			}
		} catch (Exception e) {
			log.error(e.getMessage(),e);
		}
	}

	private void initLocale() {
		this.relatorio.getParametros().put(JRParameter.REPORT_LOCALE, LocaleUtil.getLocale());
	}

	protected InputStream getTemplateInputStream() throws Exception {
		String diretorio = "/com/rjconsultores/ventaboletos/relatorios/templates/" + this.relatorio.getNome() + ".jasper";
		InputStream iStemplate = this.getClass().getResourceAsStream(diretorio);

		if (iStemplate == null) {
			throw new Exception("Não foi possivel localizar o template do relátorio no diretorio a seguir: " + diretorio);
		}

		return iStemplate;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.rjconsultores.ventaboletos.relatorios.utilitarios.IRenderRelatorio#render()
	 */

	public byte[] render(SaidaRelatorio saida) throws Exception {
		this.preRender();

		byte[] conteudo = null;
		
		if (this.jasperPrint == null) {

			if (this.relatorio.isCollectionDataSource()) {
				this.jasperPrint = JasperFillManager.fillReport(this.getTemplateInputStream(), this.relatorio.getParametros(), this.relatorio.getCollectionDataSource());
			} else {
				if (this.relatorio.isCustomDataSource())
					this.jasperPrint = JasperFillManager.fillReport(this.getTemplateInputStream(), this.relatorio.getParametros(), (JRDataSource) this.relatorio.getCustomDataSource());
				else
					this.jasperPrint = JasperFillManager.fillReport(this.getTemplateInputStream(), this.relatorio.getParametros(), this.relatorio.getConexao());
			}
		}

		switch (saida) {

		case PDF:
			conteudo = this.renderPdf();
			break;

		case XLS:
			conteudo = this.renderXls();
			break;

		}

		return conteudo;
	}

	protected byte[] renderXls() throws Exception {

		JExcelApiExporter exporterXLS = new JExcelApiExporter();
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		exporterXLS.setParameter(JExcelApiExporterParameter.JASPER_PRINT, this.jasperPrint);
		exporterXLS.setParameter(JExcelApiExporterParameter.OUTPUT_STREAM, output);
		exporterXLS.setParameter(JExcelApiExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.FALSE);
		exporterXLS.setParameter(JExcelApiExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);
		exporterXLS.setParameter(JExcelApiExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);
		exporterXLS.setParameter(JExcelApiExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);

		// collapseRowSpan
		// JRXlsExporterParameter.
		exporterXLS.exportReport();
		return output.toByteArray();

	}

	protected byte[] renderPdf() throws Exception {

		return JasperExportManager.exportReportToPdf(this.jasperPrint);

	}

}
