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.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
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.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.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;

@Controller("relatorioSisdapController")
@Scope("prototype")
public class RelatorioSisdapController extends MyGenericForwardComposer {

	private static final long serialVersionUID = 1L;
	private static Logger log = LogManager.getLogger(RelatorioSisdapController.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;
	
	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;
	
	
	@Autowired
	private EmpresaService empresaService;

	@Autowired
	private SisdapService sisdapService;

	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());
	}
	
	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 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$btnExecutarRelatorio(Event ev) throws Exception {
		if (pesquisaGratuidade.getListData().size() == 0) {
			try {
				Messagebox.show(Labels.getLabel("relatorioSisdapController.MSG.gratuidade.obrigatorio"),
						Labels.getLabel("filtroRelatorioSisdap.window.title"),
						Messagebox.OK, Messagebox.INFORMATION);
			} catch (InterruptedException e) {
				log.error("", e);
			}
			return;
		}
		if (pesquisaDescontoIdoso.getListData().size() == 0) {
			try {
				Messagebox.show(Labels.getLabel("relatorioSisdapController.MSG.desconto.idoso.obrigatorio"),
						Labels.getLabel("filtroRelatorioSisdap.window.title"),
						Messagebox.OK, Messagebox.INFORMATION);
			} catch (InterruptedException e) {
				log.error("", e);
			}
			return;
		}
		if (pesquisaGratuidadeIdoso.getListData().size() == 0) {
			try {
				Messagebox.show(Labels.getLabel("relatorioSisdapController.MSG.gratuidade.idoso.obrigatorio"),
						Labels.getLabel("filtroRelatorioSisdap.window.title"),
						Messagebox.OK, Messagebox.INFORMATION);
			} catch (InterruptedException e) {
				log.error("", e);
			}
			return;
		}
		if (pesquisaDescontoJovem.getListData().size() == 0) {
			try {
				Messagebox.show(Labels.getLabel("relatorioSisdapController.MSG.desconto.jovem.obrigatorio"),
						Labels.getLabel("filtroRelatorioSisdap.window.title"),
						Messagebox.OK, Messagebox.INFORMATION);
			} catch (InterruptedException e) {
				log.error("", e);
			}
			return;
		}
		if (pesquisaGratuidadeJovem.getListData().size() == 0) {
			try {
				Messagebox.show(Labels.getLabel("relatorioSisdapController.MSG.gratuidade.jovem.obrigatorio"),
						Labels.getLabel("filtroRelatorioSisdap.window.title"),
						Messagebox.OK, Messagebox.INFORMATION);
			} catch (InterruptedException e) {
				log.error("", e);
			}
			return;
		}
		
		if (cmbEmpresa.getSelectedIndex() < 0) {
			Messagebox.show(Labels.getLabel("relatorioSisdapController.MSG.empresaErro"),
					Labels.getLabel("filtroRelatorioSisdap.window.title"),
					Messagebox.OK, Messagebox.INFORMATION);
			return;
		}
		processarRelatorioSisdap(datInicio.getValue(), datFinal.getValue(), pesquisaGratuidade, pesquisaDescontoIdoso, pesquisaGratuidadeIdoso, pesquisaDescontoJovem, pesquisaGratuidadeJovem);
	}

	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 processarRelatorioSisdap(Date fecInicio, Date fecFinal, MyListbox gratuidade, MyListbox pesquisaDescontoIdoso, MyListbox pesquisaGratuidadeIdoso, MyListbox pesquisaDescontoJovem, MyListbox pesquisaGratuidadeJovem) {

		List<String> movimentoLinhas = sisdapService.getMovimentoLinhas(fecInicio, fecFinal, empresa.getEmpresaId());
		List<String> movimentoSecoes = sisdapService.getMovimentoSecoes(fecInicio, fecFinal, empresa.getEmpresaId(), gratuidade.getListData(), pesquisaDescontoIdoso.getListData(), pesquisaGratuidadeIdoso.getListData(), pesquisaDescontoJovem.getListData(), pesquisaGratuidadeJovem.getListData());


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

		exportarZip(movimentoLinhas, movimentoSecoes);

	}

	private void exportarZip(List<String> movimentoLinhas, List<String> movimentoSecoes) {
		try {
			File f1 = File.createTempFile("movimentoLinhas", ".txt");
			log.info(f1.getAbsolutePath());
			FileWriter writer = new FileWriter(f1);
			for (int i = 0; i < movimentoLinhas.size(); i++) {
				String str = movimentoLinhas.get(i);
				if (i < movimentoLinhas.size() - 1) {
					writer.write(str + "\r\n");
				} else {
					writer.write(str);
				}
			}
			writer.close();

			File f2 = File.createTempFile("movimentoSecoes", ".txt");
			writer = new FileWriter(f2);
			for (int i = 0; i < movimentoSecoes.size(); i++) {
				String str = movimentoSecoes.get(i);
				if (i < movimentoSecoes.size() - 1) {
					writer.write(str + "\r\n");
				} else {
					writer.write(str);
				}
			}
			writer.close();

			String[] files = new String[] { f1.getAbsolutePath(), f2.getAbsolutePath() };
			
			File f3 = File.createTempFile("sisdap", ".zip");
			zipFiles(files, f3.getAbsolutePath());
			FileInputStream is = new FileInputStream(f3);
			Filedownload.save(is, "application/zip", "sisdap.zip");
		} catch (Exception e) {
			log.error("", 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;
	}
}
