package com.rjconsultores.ventaboletos.web.gui.controladores.relatorios;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.zkoss.util.resource.Labels;
import org.zkoss.zhtml.Filedownload;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zul.Bandbox;
import org.zkoss.zul.Combobox;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Paging;

import com.rjconsultores.ventaboletos.entidad.Categoria;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.service.EmpresaService;
import com.rjconsultores.ventaboletos.service.SisdapService;
import com.rjconsultores.ventaboletos.utilerias.UsuarioLogado;
import com.rjconsultores.ventaboletos.web.utilerias.MyGenericForwardComposer;
import com.rjconsultores.ventaboletos.web.utilerias.MyListbox;
import com.rjconsultores.ventaboletos.web.utilerias.MyTextbox;
import com.rjconsultores.ventaboletos.web.utilerias.paginacion.HibernateSearchObject;
import com.rjconsultores.ventaboletos.web.utilerias.paginacion.PagedListWrapper;
import com.rjconsultores.ventaboletos.web.utilerias.render.RenderDescontoGratuidade;
import com.rjconsultores.ventaboletos.web.utilerias.render.RenderGratuidadeEstudante;
import com.rjconsultores.ventaboletos.web.utilerias.render.RenderGratuidadeProfessor;

@Controller("relatorioSieController")
@Scope("prototype")
public class RelatorioSieController extends MyGenericForwardComposer {

	private static final long serialVersionUID = 1L;
	private static Logger log = LogManager.getLogger(RelatorioSieController.class);

	private Integer MAX_BUFFER_ZIP = Integer.valueOf(18024);
	
	@Autowired
	private transient PagedListWrapper<Categoria> plwCategoriaGratuidade;
	
	@Autowired
	private transient PagedListWrapper<Categoria> plwCategoriaDescontoIdoso;

	@Autowired
	private transient PagedListWrapper<Categoria> plwCategoriaDescontoJovem;
	
	@Autowired
	private transient PagedListWrapper<Categoria> plwCategoriaGratuidadeIdoso;
	
	@Autowired
	private transient PagedListWrapper<Categoria> plwCategoriaGratuidadeJovem;
	
	@Autowired
	private transient PagedListWrapper<Categoria> plwCategoriaGratuidadeEstudante;
	
	@Autowired
	private transient PagedListWrapper<Categoria> plwCategoriaGratuidadeProfessor;
	
	private Datebox datInicio;
	private Datebox datFinal;
	private Empresa empresa;
	private Combobox cmbEmpresa;

	private MyTextbox txtGratuidade;
	private Bandbox bbGratuidade;
	private MyListbox pesquisaGratuidade;
	private MyListbox pesquisaGratuidadeList;
	private Paging pagingGratuidade;
	
	private MyTextbox txtDescontoIdoso;
	private Bandbox bbDescontoIdoso;
	private MyListbox pesquisaDescontoIdoso;
	private MyListbox pesquisaDescontoIdosoList;
	private Paging pagingDescontoIdoso;
	
	private MyTextbox txtDescontoJovem;
	private Bandbox bbDescontoJovem;
	private MyListbox pesquisaDescontoJovem;
	private MyListbox pesquisaDescontoJovemList;
	private Paging pagingDescontoJovem;
	
	private MyTextbox txtGratuidadeIdoso;
	private Bandbox bbGratuidadeIdoso;
	private MyListbox pesquisaGratuidadeIdoso;
	private MyListbox pesquisaGratuidadeIdosoList;
	private Paging pagingGratuidadeIdoso;
	
	private MyTextbox txtGratuidadeJovem;
	private Bandbox bbGratuidadeJovem;
	private MyListbox pesquisaGratuidadeJovem;
	private MyListbox pesquisaGratuidadeJovemList;	
	private Paging pagingGratuidadeJovem;
	
	private MyTextbox txtGratuidadeEstudante;
	private Bandbox bbGratuidadeEstudante;
	private MyListbox pesquisaGratuidadeEstudante;
	private MyListbox pesquisaGratuidadeEstudanteList;
	private Paging pagingGratuidadeEstudante;
	
	
	private MyTextbox txtGratuidadeProfessor;
	private Bandbox bbGratuidadeProfessor;
	private MyListbox pesquisaGratuidadeProfessor;
	private MyListbox pesquisaGratuidadeProfessorList;
	private Paging pagingGratuidadeProfessor;
	
	
	@Autowired
	private EmpresaService empresaService;

	@Autowired
	private SisdapService sieService;

	private List<Empresa> lsEmpresa;

	@Override
	public void doAfterCompose(Component comp) throws Exception {
		lsEmpresa = empresaService.obtenerTodos();
		
		super.doAfterCompose(comp);
		
		pesquisaGratuidadeList.setItemRenderer(new RenderDescontoGratuidade());
		pesquisaDescontoIdosoList.setItemRenderer(new RenderDescontoGratuidade());
		pesquisaGratuidadeIdosoList.setItemRenderer(new RenderDescontoGratuidade());
		pesquisaDescontoJovemList.setItemRenderer(new RenderDescontoGratuidade());
		pesquisaGratuidadeJovemList.setItemRenderer(new RenderDescontoGratuidade());
		pesquisaGratuidadeEstudanteList.setItemRenderer(new RenderGratuidadeEstudante());
		pesquisaGratuidadeProfessorList.setItemRenderer(new RenderGratuidadeProfessor());
	}
	
	public void onClick$btnPesquisaGratuidadeProfessor(Event ev) {
		HibernateSearchObject<Categoria> categoria = new HibernateSearchObject<Categoria>(Categoria.class, pagingGratuidadeProfessor.getPageSize());
		categoria.addFilterILike("desccategoria", "%" + txtGratuidadeProfessor.getValue() + "%");
		categoria.addSortAsc("desccategoria");
		categoria.addFilterEqual("activo", Boolean.TRUE);
		plwCategoriaGratuidadeProfessor.init(categoria, pesquisaGratuidadeProfessorList, pagingGratuidadeProfessor);
	}
	
	public void onClick$btnPesquisaGratuidadeEstudante(Event ev) {
		HibernateSearchObject<Categoria> categoria = new HibernateSearchObject<Categoria>(Categoria.class, pagingGratuidadeEstudante.getPageSize());
		categoria.addFilterILike("desccategoria", "%" + txtGratuidadeEstudante.getValue() + "%");
		categoria.addSortAsc("desccategoria");
		categoria.addFilterEqual("activo", Boolean.TRUE);
		plwCategoriaGratuidadeEstudante.init(categoria, pesquisaGratuidadeEstudanteList, pagingGratuidadeEstudante);
	}
	
	public void onClick$btnPesquisaGratuidade(Event ev) {
		HibernateSearchObject<Categoria> categoria = new HibernateSearchObject<Categoria>(Categoria.class, pagingGratuidade.getPageSize());
		categoria.addFilterILike("desccategoria", "%" + txtGratuidade.getValue() + "%");
		categoria.addSortAsc("desccategoria");
		categoria.addFilterEqual("activo", Boolean.TRUE);
		plwCategoriaGratuidade.init(categoria, pesquisaGratuidadeList, pagingGratuidade);
	}
	
	public void onClick$btnPesquisaDescontoIdoso(Event ev) {
		HibernateSearchObject<Categoria> categoria = new HibernateSearchObject<Categoria>(Categoria.class, pagingDescontoIdoso.getPageSize());
		categoria.addFilterILike("desccategoria", "%" + txtDescontoIdoso.getValue() + "%");
		categoria.addSortAsc("desccategoria");
		categoria.addFilterEqual("activo", Boolean.TRUE);
		plwCategoriaDescontoIdoso.init(categoria, pesquisaDescontoIdosoList, pagingDescontoIdoso);
	}
	
	public void onClick$btnPesquisaDescontoJovem(Event ev) {
		HibernateSearchObject<Categoria> categoria = new HibernateSearchObject<Categoria>(Categoria.class, pagingDescontoJovem.getPageSize());
		categoria.addFilterILike("desccategoria", "%" + txtDescontoJovem.getValue() + "%");
		categoria.addSortAsc("desccategoria");
		categoria.addFilterEqual("activo", Boolean.TRUE);
		plwCategoriaDescontoJovem.init(categoria, pesquisaDescontoJovemList, pagingDescontoJovem);
	}
	
	public void onClick$btnPesquisaGratuidadeIdoso(Event ev) {
		HibernateSearchObject<Categoria> categoria = new HibernateSearchObject<Categoria>(Categoria.class, pagingGratuidadeIdoso.getPageSize());
		categoria.addFilterILike("desccategoria", "%" + txtGratuidadeIdoso.getValue() + "%");
		categoria.addSortAsc("desccategoria");
		categoria.addFilterEqual("activo", Boolean.TRUE);
		plwCategoriaGratuidadeIdoso.init(categoria, pesquisaGratuidadeIdosoList, pagingGratuidadeIdoso);
	}
	
	public void onClick$btnPesquisaGratuidadeJovem(Event ev) {
		HibernateSearchObject<Categoria> categoria = new HibernateSearchObject<Categoria>(Categoria.class, pagingGratuidadeJovem.getPageSize());
		categoria.addFilterILike("desccategoria", "%" + txtGratuidadeJovem.getValue() + "%");
		categoria.addSortAsc("desccategoria");
		categoria.addFilterEqual("activo", Boolean.TRUE);
		plwCategoriaGratuidadeJovem.init(categoria, pesquisaGratuidadeJovemList, pagingGratuidadeJovem);
	}
	
	public void onDoubleClick$pesquisaGratuidade(Event ev) {
		Categoria categoria = (Categoria) pesquisaGratuidade.getSelected();
		pesquisaGratuidade.removeItem(categoria);
	}
	
	public void onDoubleClick$pesquisaDescontoIdoso(Event ev) {
		Categoria categoria = (Categoria) pesquisaDescontoIdoso.getSelected();
		pesquisaDescontoIdoso.removeItem(categoria);
	}

	public void onDoubleClick$pesquisaDescontoJovem(Event ev) {
		Categoria categoria = (Categoria) pesquisaDescontoJovem.getSelected();
		pesquisaDescontoJovem.removeItem(categoria);
	}
	
	public void onDoubleClick$pesquisaGratuidadeIdoso(Event ev) {
		Categoria categoria = (Categoria) pesquisaGratuidadeIdoso.getSelected();
		pesquisaGratuidadeIdoso.removeItem(categoria);
	}
	
	public void onDoubleClick$pesquisaGratuidadeJovem(Event ev) {
		Categoria categoria = (Categoria) pesquisaGratuidadeJovem.getSelected();
		pesquisaGratuidadeJovem.removeItem(categoria);
	}
	
	public void onDoubleClick$pesquisaGratuidadeList(Event ev) {
		Categoria categoria = (Categoria) pesquisaGratuidadeList.getSelected();
		pesquisaGratuidade.addItemNovo(categoria);
	}
	
	public void onDoubleClick$pesquisaDescontoIdosoList(Event ev) {
		Categoria categoria = (Categoria) pesquisaDescontoIdosoList.getSelected();
		pesquisaDescontoIdoso.addItemNovo(categoria);
	}

	public void onDoubleClick$pesquisaDescontoJovemList(Event ev) {
		Categoria categoria = (Categoria) pesquisaDescontoJovemList.getSelected();
		pesquisaDescontoJovem.addItemNovo(categoria);
	}
	
	public void onDoubleClick$pesquisaGratuidadeIdosoList(Event ev) {
		Categoria categoria = (Categoria) pesquisaGratuidadeIdosoList.getSelected();
		pesquisaGratuidadeIdoso.addItemNovo(categoria);
	}
	
	public void onDoubleClick$pesquisaGratuidadeJovemList(Event ev) {
		Categoria categoria = (Categoria) pesquisaGratuidadeJovemList.getSelected();
		pesquisaGratuidadeJovem.addItemNovo(categoria);
	}
	
	public void onDoubleClick$pesquisaGratuidadeProfessorList(Event ev) {
		Categoria categoria = (Categoria) pesquisaGratuidadeProfessorList.getSelected();
		pesquisaGratuidadeProfessor.addItemNovo(categoria);
	}
	
	public void onDoubleClick$pesquisaGratuidadeEstudanteList(Event ev) {
		Categoria categoria = (Categoria) pesquisaGratuidadeEstudanteList.getSelected();
		pesquisaGratuidadeEstudante.addItemNovo(categoria);
	}
	
	public void onClick$btnLimparGratuidade(Event ev) {
		pesquisaGratuidadeList.setData(new ArrayList<Categoria>());
		bbGratuidade.setText("");
	}
	
	public void onClick$btnLimparDescontoIdoso(Event ev) {
		pesquisaDescontoIdosoList.setData(new ArrayList<Categoria>());
		bbDescontoIdoso.setText("");
	}

	public void onClick$btnLimparDescontoJovem(Event ev) {
		pesquisaDescontoJovemList.setData(new ArrayList<Categoria>());
		bbDescontoJovem.setText("");
	}
	
	public void onClick$btnLimparGratuidadeIdoso(Event ev) {
		pesquisaGratuidadeIdosoList.setData(new ArrayList<Categoria>());
		bbGratuidadeIdoso.setText("");
	}
	
	public void onClick$btnLimparGratuidadeJovem(Event ev) {
		pesquisaGratuidadeJovemList.setData(new ArrayList<Categoria>());
		bbGratuidadeJovem.setText("");
	}
	
	public void onClick$btnLimparGratuidadeEstudante(Event ev) {
		pesquisaGratuidadeEstudante.setData(new ArrayList<Categoria>());
		bbGratuidadeEstudante.setText("");
	}
	
	public void onClick$btnLimparGratuidadeProfessor(Event ev) {
		pesquisaGratuidadeProfessor.setData(new ArrayList<Categoria>());
		bbGratuidadeProfessor.setText("");
	}
	
	public void onClick$btnExecutarRelatorio(Event ev) throws Exception {
		if (pesquisaGratuidade.getListData().size() == 0) {
			try {
				Messagebox.show(Labels.getLabel("relatorioSieController.MSG.gratuidade.obrigatorio"),
						Labels.getLabel("filtroRelatorioSie.window.title"),
						Messagebox.OK, Messagebox.INFORMATION);
			} catch (InterruptedException e) {
				log.error("", e);
			}
			return;
		}
		if (pesquisaDescontoIdoso.getListData().size() == 0) {
			try {
				Messagebox.show(Labels.getLabel("relatorioSieController.MSG.desconto.idoso.obrigatorio"),
						Labels.getLabel("filtroRelatorioSie.window.title"),
						Messagebox.OK, Messagebox.INFORMATION);
			} catch (InterruptedException e) {
				log.error("", e);
			}
			return;
		}
		if (pesquisaGratuidadeIdoso.getListData().size() == 0) {
			try {
				Messagebox.show(Labels.getLabel("relatorioSieController.MSG.gratuidade.idoso.obrigatorio"),
						Labels.getLabel("filtroRelatorioSie.window.title"),
						Messagebox.OK, Messagebox.INFORMATION);
			} catch (InterruptedException e) {
				log.error("", e);
			}
			return;
		}
		if (pesquisaDescontoJovem.getListData().size() == 0) {
			try {
				Messagebox.show(Labels.getLabel("relatorioSieController.MSG.desconto.jovem.obrigatorio"),
						Labels.getLabel("filtroRelatorioSie.window.title"),
						Messagebox.OK, Messagebox.INFORMATION);
			} catch (InterruptedException e) {
				log.error("", e);
			}
			return;
		}
		if (pesquisaGratuidadeJovem.getListData().size() == 0) {
			try {
				Messagebox.show(Labels.getLabel("relatorioSieController.MSG.gratuidade.jovem.obrigatorio"),
						Labels.getLabel("filtroRelatorioSie.window.title"),
						Messagebox.OK, Messagebox.INFORMATION);
			} catch (InterruptedException e) {
				log.error("", e);
			}
			return;
		}
		
		if (cmbEmpresa.getSelectedIndex() < 0) {
			Messagebox.show(Labels.getLabel("relatorioSieController.MSG.empresaErro"),
					Labels.getLabel("filtroRelatorioSie.window.title"),
					Messagebox.OK, Messagebox.INFORMATION);
			return;
		}
		
		if (pesquisaGratuidadeEstudante.getListData().size() == 0) {
			try {
				Messagebox.show(Labels.getLabel("relatorioSieController.MSG.gratuidade.estudante.obrigatorio"),
						Labels.getLabel("filtroRelatorioSie.window.title"),
						Messagebox.OK, Messagebox.INFORMATION);
			} catch (InterruptedException e) {
				log.error("", e);
			}
			return;
		}
		
		if (pesquisaGratuidadeProfessor.getListData().size() == 0) {
			try {
				Messagebox.show(Labels.getLabel("relatorioSieController.MSG.gratuidade.professor.obrigatorio"),
						Labels.getLabel("filtroRelatorioSie.window.title"),
						Messagebox.OK, Messagebox.INFORMATION);
			} catch (InterruptedException e) {
				log.error("", e);
			}
			return;
		}
		processarRelatorioSie(datInicio.getValue(), datFinal.getValue(), pesquisaGratuidade, pesquisaDescontoIdoso, pesquisaGratuidadeIdoso, pesquisaDescontoJovem, pesquisaGratuidadeJovem, pesquisaGratuidadeProfessor, pesquisaGratuidadeEstudante);
	}

	private void zipFiles(String[] filesToZip, String fileOutputName) {
		byte[] buffer = new byte[MAX_BUFFER_ZIP];

		try {
			ZipOutputStream out = new ZipOutputStream(new FileOutputStream(fileOutputName));

			// Ajusta modo de compressão
			out.setLevel(Deflater.DEFAULT_COMPRESSION);

			// faz a iteração sobre os arquivos, adicionando-os ao arquivo ZIP
			for (int i = 0; i < filesToZip.length; i++) {

				FileInputStream in = new FileInputStream(filesToZip[i]);

				// Add ZIP entry to output stream.
				out.putNextEntry(new ZipEntry(filesToZip[i]));

				// Transfer bytes from the current file to the ZIP file
				int len;
				while ((len = in.read(buffer)) > 0) {
					out.write(buffer, 0, len);
				}

				// Close the current entry
				out.closeEntry();

				// Close the current file input stream
				in.close();
			}

			// Close the ZipOutPutStream
			out.close();

		} catch (IllegalArgumentException iae) {
			log.error("", iae);
		} catch (FileNotFoundException fnfe) {
			log.error("", fnfe);
		} catch (IOException ioe) {
			log.error("", ioe);
		}
	}

	private void processarRelatorioSie(Date fecInicio, Date fecFinal, MyListbox gratuidade, MyListbox pesquisaDescontoIdoso, MyListbox pesquisaGratuidadeIdoso, MyListbox pesquisaDescontoJovem, MyListbox pesquisaGratuidadeJovem, MyListbox pesquisaGratuidadeProfessor, MyListbox pesquisaGratuidadeEstudante) {

		List<String> movimentoLinhas = sieService.getMovimentoLinhas(fecInicio, fecFinal, empresa.getEmpresaId());
		@SuppressWarnings("unchecked")
		List<String> movimentoSecoes = sieService.getMovimentoSecoes(fecInicio, fecFinal, empresa.getEmpresaId(), gratuidade.getListData(), pesquisaDescontoIdoso.getListData(), pesquisaGratuidadeIdoso.getListData(), pesquisaDescontoJovem.getListData(), pesquisaGratuidadeJovem.getListData(), pesquisaGratuidadeProfessor.getListData(), pesquisaGratuidadeEstudante.getListData());


		if (movimentoLinhas.size() <= 1 && movimentoSecoes.size() <= 1) {
			// Não retornou dados
			try {
				
				Messagebox.show(Labels.getLabel("relatorioSieController.MSG.nenhumRegistro"),
						Labels.getLabel("filtroRelatorioSie.window.title"),
						Messagebox.OK, Messagebox.INFORMATION);
			} catch (InterruptedException e) {
				log.error("", e);
			}
			return;
		}

		
		try {
			String nomeArquivo =  UsuarioLogado.getUsuarioLogado().getNombusuario()
					  + "_" + Calendar.getInstance().getTime().getTime()
					  + "_" + "Sie.xls"; 
			InputStream arquivo = gerarArquivoExcel(movimentoLinhas);			
			Filedownload.save(arquivo, "application/xls", nomeArquivo);
			Messagebox.show( nomeArquivo + " " +  Labels.getLabel("relatorioSieController.MSG.arquivogerado"),
					Labels.getLabel("filtroRelatorioSie.window.title"),
					Messagebox.OK, Messagebox.INFORMATION);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
						
		}
		
		try {
			String nomeArquivo =  UsuarioLogado.getUsuarioLogado().getNombusuario()
					  + "_" + Calendar.getInstance().getTime().getTime()
					  + "_" + "Sie.xls"; 
			InputStream arquivo = gerarArquivoExcel(movimentoSecoes);
			Filedownload.save(arquivo, "application/xls", nomeArquivo);
			Messagebox.show( nomeArquivo + " " +  Labels.getLabel("relatorioSieController.MSG.arquivogerado"),
							Labels.getLabel("filtroRelatorioSie.window.title"),
							Messagebox.OK, Messagebox.INFORMATION);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
						
		}

	}	
	
	public Empresa getEmpresa() {
		return empresa;
	}

	public void setEmpresa(Empresa empresa) {
		this.empresa = empresa;
	}

	public List<Empresa> getLsEmpresa() {
		return lsEmpresa;
	}

	public void setLsEmpresa(List<Empresa> lsEmpresa) {
		this.lsEmpresa = lsEmpresa;
	}
	
	private void criarRow(int numRow, HSSFSheet sheet, String[] dados) {
		int numColumn = 0;
		HSSFRow row = sheet.createRow(numRow);
		for (String dado : dados) {
			HSSFCell cell = row.createCell(numColumn++);
			cell.setCellValue(dado);
		}
	}
	
	private void criarArquivoExcel(HSSFWorkbook wb, List<String> movimento) {        	
		HSSFSheet sheet = wb.createSheet("Sie");
		int contRow = 0;
		
		String cabecalhoStr = movimento.get(0);
		String[] arrOfcabecalhoStr = cabecalhoStr.split(";", -2); //transforma a linha em array para se transforma na coluna do excel
		criarRow(contRow++, sheet, arrOfcabecalhoStr);
				
		for (int i = 1; i < movimento.size(); i++) {
			String str = movimento.get(i);
			String[] strArray = str.split(";", -2);  //transforma a linha em array para se transforma na coluna do excel
			criarRow(contRow++, sheet, strArray);
		}
		
		for (int i = 0; i < arrOfcabecalhoStr.length; i++) {
			sheet.autoSizeColumn(i);
		}
	}
	
	private InputStream gerarArquivoExcel(List<String> movimento) throws IOException {
		HSSFWorkbook wb = new HSSFWorkbook(); //cria a planilha do excel
		
		criarArquivoExcel(wb, movimento); 
		
		String nomeArquivo =  UsuarioLogado.getUsuarioLogado().getNombusuario()
							  + "_" + Calendar.getInstance().getTime().getTime()
							  + "_" + "Sie";

		File fNomeArquivo = File.createTempFile(nomeArquivo, ".tmp");
		
		FileOutputStream stream = new FileOutputStream(fNomeArquivo);
		stream.flush();
		wb.write(stream);
		stream.close();

		InputStream is = new FileInputStream(fNomeArquivo);
		
		return is;
	}
	

	
}
