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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.sql.DataSource;

import org.apache.commons.lang.StringUtils;
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.Messagebox;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zul.Button;
import org.zkoss.zul.Comboitem;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.Radiogroup;
import org.zkoss.zul.Textbox;

import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.OrgaoConcedente;
import com.rjconsultores.ventaboletos.entidad.Ruta;
import com.rjconsultores.ventaboletos.relatorios.impl.RelatorioDesempenhoPorLinha;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.Relatorio;
import com.rjconsultores.ventaboletos.service.RutaService;
import com.rjconsultores.ventaboletos.utilerias.UsuarioLogado;
import com.rjconsultores.ventaboletos.vo.ruta.RutaVO;
import com.rjconsultores.ventaboletos.web.utilerias.MyComboboxEstandar;
import com.rjconsultores.ventaboletos.web.utilerias.MyGenericForwardComposer;
import com.rjconsultores.ventaboletos.web.utilerias.MyListbox;
import com.rjconsultores.ventaboletos.web.utilerias.render.RenderDesempenhoPorLinha;
import com.rjconsultores.ventaboletos.web.utilerias.render.RenderDesempenhoPorLinhaTrecho;

@Controller("relatorioDesempenhoPorLinhaController")
@Scope("prototype")
public class RelatorioDesempenhoPorLinhaController extends MyGenericForwardComposer {

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

	@Autowired
	private DataSource dataSourceRead;

	private Datebox datInicial;
	private Datebox datFinal;
	private MyComboboxEstandar cmbEmpresa;
	private List<Empresa> lsEmpresa;
	@Autowired
	private RutaService rutaService;

	private MyListbox linhaList;
	private MyListbox trechoList;
	private MyListbox linhaListSelList;
	private Textbox txtPalavraPesquisaLinha;
	private ArrayList<Ruta> lsNumLinha = new ArrayList<Ruta>();
	private Radiogroup rgLayout;
	private Map<Integer, List<RutaVO>> mapRutaTrecho = new HashMap<>();

	@Override
	public void doAfterCompose(Component comp) throws Exception {
		super.doAfterCompose(comp);

		lsEmpresa = UsuarioLogado.getUsuarioLogado().getEmpresa();
		linhaList.setItemRenderer(new RenderDesempenhoPorLinha());
		renderizarListRuta();
		trechoList.setItemRenderer(new RenderDesempenhoPorLinhaTrecho());

	}

	private void renderizarListRuta() {
		linhaListSelList.setItemRenderer(new ListitemRenderer() {
			@Override
			public void render(Listitem lstm, Object o) throws Exception {

				Ruta ruta = (Ruta) o;
				if (ruta == null) {
					return;
				}

				Listcell lc = new Listcell(ruta.getNumRuta() != null ? ruta.getNumRuta().toString() : "");
				lc.setParent(lstm);
				lc = new Listcell(ruta.getPrefixo());
				lc.setParent(lstm);
				lc = new Listcell(ruta.getDescruta());
				lc.setParent(lstm);

				OrgaoConcedente orgaoConcedente = ruta.getOrgaoConcedente();
				if (orgaoConcedente != null) {
					lc = new Listcell(orgaoConcedente.getDescOrgao());
				} else {
					lc = new Listcell("-");
				}
				lc.setParent(lstm);

				Button btn = new Button();
				lc = new Listcell();
				lc.setParent(lstm);

				btn.setWidth("16");
				btn.setHeight("16");
				btn.setImage("/gui/img/remove.png");

				btn.addEventListener("onClick", new EventListener() {
					@Override
					public void onEvent(Event event) throws Exception {
						MyListbox listBox = (MyListbox) event.getTarget().getParent().getParent().getParent();
						Listitem listItem = (Listitem) event.getTarget().getParent().getParent();
						listBox.removeItem((Ruta) listItem.getAttribute("data"));
						List<RutaVO> lsRutaVOAux = new ArrayList<>(trechoList.getListData());
						Ruta ruta = (Ruta) listItem.getAttribute("data");
						for (RutaVO rutaVO : (List<RutaVO>) trechoList.getListData()) {
							if (StringUtils.isNotBlank(ruta.getNumRuta()) && StringUtils.isNotBlank(rutaVO.getNumRuta())
									&& ruta.getNumRuta().equals(rutaVO.getNumRuta())) {
								lsRutaVOAux.remove(rutaVO);
								mapRutaTrecho.remove(rutaVO.getRutaId().intValue());
							}
						}
						trechoList.setData(lsRutaVOAux);
					}
				});
				lc.appendChild(btn);
				lstm.setAttribute("data", ruta);
			}
		});
	}

	public void carregarTramos(Ruta rutaSelecionada) {

		List<RutaVO> lsRutaVO = rutaService.buscaRutaParadas(rutaSelecionada.getRutaId());
		RutaVO ultimaRuta = lsRutaVO.get(lsRutaVO.size() - 1);
		RutaVO novaRuta = new RutaVO(ultimaRuta.getRutaId(), ultimaRuta.getNumRuta(), ultimaRuta.getPrefixo(),
				ultimaRuta.getDescruta(), ultimaRuta.getDescDestino(), ultimaRuta.getNumSecuencia(),
				ultimaRuta.getDestinoId(), ultimaRuta.getDestinoId());
		novaRuta.setDescOrigem(novaRuta.getDescParada());
		lsRutaVO.add(novaRuta);

		mapRutaTrecho.put(rutaSelecionada.getRutaId(), lsRutaVO);
		List<RutaVO> lsRutaVOAux = new ArrayList();
		lsRutaVOAux.addAll(trechoList.getListData());
		lsRutaVOAux.addAll(lsRutaVO);
		trechoList.setData(lsRutaVOAux);

	}

	public void actualizarDados(List<RutaVO> listaRutaVO) {

	}

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

	public void setLsEmpresa(List<Empresa> lsEmpresa) {
		this.lsEmpresa = lsEmpresa;
	}

	public void onDoubleClick$linhaList(Event ev) {
		Ruta rutaAux = (Ruta) linhaList.getSelected();
		if (rutaAux == null) {
			return;
		}
		linhaListSelList.addItemNovo(rutaAux);

		carregarTramos(rutaAux);
	}

	private void executarPesquisaLinha() {

		String palavraPesquisaRuta = txtPalavraPesquisaLinha.getText();
		linhaList.setData(rutaService.buscaRuta(palavraPesquisaRuta));

		if (linhaList.getData().length == 0) {
			try {
				Messagebox.show(Labels.getLabel("MSG.ningunRegistro"),
						Labels.getLabel("relatorioLinhasHorarioController.window.title"), Messagebox.OK,
						Messagebox.INFORMATION);
			} catch (InterruptedException ex) {
				log.error(ex);
			}
		} else {
			Collections.sort(linhaList.getListData(), new Comparator<Ruta>() {
				@Override
				public int compare(Ruta m1, Ruta m2) {
					return m1.getDescruta().compareTo(m2.getDescruta());
				}
			});
		}
	}

	public void onClick$btnPesquisaLinha(Event ev) {
		executarPesquisaLinha();
	}

	public void onClick$btnLimparLinha(Event ev) {
		linhaList.clearSelection();
		lsNumLinha.clear();
	}

	public void onClick$btnExecutarRelatorio(Event ev) throws Exception {
		executarRelatorio();
	}

	private void executarRelatorio() throws Exception {

		if (rgLayout.getSelectedItem().getValue().equals("EMISSAO_LINHA")) {
			executarRelatorioLinha();
		} else {
			executarRelatorioTrecho();
		}
	}

	private void executarRelatorioLinha() throws Exception {

		Map<String, Object> parametros = new HashMap<String, Object>();
		StringBuilder filtro = new StringBuilder();

		filtro.append("Linha: ");
		String linhaIds = "";
		String linhas = "";
		List<Ruta> lslinhaSelecionados = new ArrayList(Arrays.asList(linhaListSelList.getData()));
		if (lslinhaSelecionados.isEmpty()) {
			linhas = "Todas";
		} else {
			for (int i = 0; i < lslinhaSelecionados.size(); i++) {
				Ruta linha = lslinhaSelecionados.get(i);
				linhas = linhas + linha.getDescruta() + ", ";

				linhaIds = linhaIds + linha.getRutaId() + ", ";
			}

			// removendo ultima virgula
			linhaIds = linhaIds.substring(0, linhaIds.length() - 2);
			linhas = linhas.substring(0, linhas.length() - 2);
			parametros.put("LINHAS", linhaIds);
		}
		filtro.append(linhas).append(";");

		parametros.put("DATA_INICIAL", (java.util.Date) this.datInicial.getValue());
		parametros.put("DATA_FINAL", (java.util.Date) this.datFinal.getValue());
		parametros.put("NOME_RELATORIO", Labels.getLabel("relatorioDesempenhoPorLinhaController.window.title"));
		parametros.put("USUARIO", UsuarioLogado.getUsuarioLogado().getNombusuario());

		filtro.append(" Empresa: ");

		Comboitem itemEmpresa = cmbEmpresa.getSelectedItem();
		if (itemEmpresa != null) {
			Empresa empresa = (Empresa) itemEmpresa.getValue();
			parametros.put("EMPRESA_ID", empresa.getEmpresaId());
			parametros.put("EMPRESA", empresa.getNombempresa());
			filtro.append(empresa.getNombempresa() + ";");
		} else {
			filtro.append(" Todas;");
		}

		parametros.put("FILTROS", filtro.toString());
		Relatorio relatorio = new RelatorioDesempenhoPorLinha(parametros, dataSourceRead.getConnection());

		Map args = new HashMap();
		args.put("relatorio", relatorio);

		openWindow("/component/reportView.zul", Labels.getLabel("relatorioDesempenhoPorLinhaController.window.title"),
				args, MODAL);
	}

	private void executarRelatorioTrecho() throws Exception {

		Map<String, Object> parametros = new HashMap<String, Object>();
		StringBuilder filtro = new StringBuilder();
		List<RutaVO> lista = new ArrayList<>();
		Map<Integer, List<RutaVO>> mapRutaTrechoAux = new HashMap<>();

		for (Entry<Integer, List<RutaVO>> entry : mapRutaTrecho.entrySet()) {
			List<RutaVO> listaAux = entry.getValue();
			for (RutaVO rutaVO2 : (List<RutaVO>) trechoList.getListData()) {
				for (RutaVO rutaVO : listaAux) {
					if (rutaVO.getRutaId().equals(rutaVO2.getRutaId())) {
						lista.add(rutaVO2);
						break;
					}
				}
			}
			mapRutaTrechoAux.put(entry.getKey(), lista);
			lista = new ArrayList<>();
		}

		filtro.append("Linha: ");
		String linhaIds = "";
		String linhas = "";
		List<Ruta> lslinhaSelecionados = new ArrayList(Arrays.asList(linhaListSelList.getData()));
		if (lslinhaSelecionados.isEmpty()) {
			linhas = "Todas";
		} else {
			for (int i = 0; i < lslinhaSelecionados.size(); i++) {
				Ruta linha = lslinhaSelecionados.get(i);
				linhas = linhas + linha.getDescruta() + ", ";

				linhaIds = linhaIds + linha.getRutaId() + ", ";
			}

			// removendo ultima virgula
			linhaIds = linhaIds.substring(0, linhaIds.length() - 2);
			linhas = linhas.substring(0, linhas.length() - 2);
			parametros.put("LINHAS", linhaIds);
		}
		filtro.append(linhas).append(";");

		parametros.put("DATA_INICIAL", (java.util.Date) this.datInicial.getValue());
		parametros.put("DATA_FINAL", (java.util.Date) this.datFinal.getValue());
		parametros.put("NOME_RELATORIO", Labels.getLabel("relatorioDesempenhoPorLinhaController.window.title"));
		parametros.put("USUARIO", UsuarioLogado.getUsuarioLogado().getNombusuario());
		parametros.put("TRECHOS", trechoList.getListData());
		parametros.put("MAPRUTATRECHO", mapRutaTrechoAux);

		filtro.append(" Empresa: ");

		Comboitem itemEmpresa = cmbEmpresa.getSelectedItem();
		if (itemEmpresa != null) {
			Empresa empresa = (Empresa) itemEmpresa.getValue();
			parametros.put("EMPRESA_ID", empresa.getEmpresaId());
			parametros.put("EMPRESA", empresa.getNombempresa());
			filtro.append(empresa.getNombempresa() + ";");
		} else {
			filtro.append(" Todas;");
		}

		parametros.put("FILTROS", filtro.toString());
		Relatorio relatorio = new RelatorioDesempenhoPorLinha(parametros, dataSourceRead.getConnection());

		Map args = new HashMap();
		args.put("relatorio", relatorio);

		openWindow("/component/reportView.zul", Labels.getLabel("relatorioDesempenhoPorLinhaController.window.title"),
				args, MODAL);
	}
}