/*
 * and open the template in the editor.
 */
package com.rjconsultores.ventaboletos.web.gui.controladores.seguridad;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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.Combobox;
import org.zkoss.zul.Comboitem;
import org.zkoss.zul.Paging;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.api.Datebox;

import com.google.gson.Gson;
import com.rjconsultores.ventaboletos.auditoria.AuditControl;
import com.rjconsultores.ventaboletos.entidad.AuditLog;
import com.rjconsultores.ventaboletos.entidad.AuditModule;
import com.rjconsultores.ventaboletos.entidad.AuditService;
import com.rjconsultores.ventaboletos.entidad.Sistema;
import com.rjconsultores.ventaboletos.enums.auditoria.EnumAuditAction;
import com.rjconsultores.ventaboletos.service.AuditLogService;
import com.rjconsultores.ventaboletos.service.AuditModuleService;
import com.rjconsultores.ventaboletos.service.SistemaService;
import com.rjconsultores.ventaboletos.web.utilerias.MyGenericForwardComposer;
import com.rjconsultores.ventaboletos.web.utilerias.MyListbox;
import com.rjconsultores.ventaboletos.web.utilerias.paginacion.HibernateSearchObject;
import com.rjconsultores.ventaboletos.web.utilerias.paginacion.PagedListWrapper;
import com.rjconsultores.ventaboletos.web.utilerias.render.RenderAudit;
import com.rjconsultores.ventaboletos.web.utilerias.render.RenderEntityDetail;

/**
 * 
 * @author eduardo
 */
@Controller("auditoriaController")
@Scope("prototype")
public class AuditoriaController extends MyGenericForwardComposer {

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

	@Autowired
	private AuditModuleService auditModuleService;

	@Autowired
	private SistemaService sistemaService;

	@Autowired
	private AuditLogService auditLogService;

	private List<AuditModule> lsModulo;
	private List<Sistema> lsAmbiente;
	private List<EnumAuditAction> lsAcao;

	private Combobox cmbModulo;
	private Combobox cmbAmbiente;
	private Combobox cmbAcao;

	private Datebox dtDataInicial;
	private Datebox dtDataFinal;

	private Textbox txtMdUsuario;
	private Textbox txtMdCustom;

	private MyListbox auditoriaList;
	private MyListbox auditoriaModelDetailList;

	@Autowired
	private transient PagedListWrapper<AuditLog> plwAuditoria;

	private Paging pagingAudit;
	private Paging pagingModuleDetail;

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

		lsModulo = new ArrayList<AuditModule>();
		AuditModule modulo = new AuditModule();
		modulo.setNameModule("Todos");

		lsModulo.add(modulo);
		lsModulo.addAll(auditModuleService.obtenerTodos());

		lsAmbiente = new ArrayList<Sistema>();
		Sistema sistemaTodos = new Sistema();
		sistemaTodos.setNombsistema("TODOS");

		lsAmbiente.add(sistemaTodos);
		lsAmbiente.addAll(sistemaService.obtenerTodos());

		lsAcao = obterAcoes();

		super.doAfterCompose(comp);

		auditoriaList.setItemRenderer(new RenderAudit());
		auditoriaList.addEventListener("onDoubleClick", new EventListener() {

			@Override
			public void onEvent(Event event) throws Exception {
				verDetalhesModulo(auditoriaList.getSelected());
			}
		});

		auditoriaModelDetailList.setItemRenderer(new RenderEntityDetail());
		auditoriaModelDetailList.addEventListener("onDoubleClick", new EventListener() {

			@Override
			public void onEvent(Event event) throws Exception {
				verDetalhesModulo(auditoriaModelDetailList.getSelected());
			}
		});

		refreshLista();
	}

	public void onClick$btnPesquisa(Event ev) {
		if ((txtMdCustom.getValue() == null || txtMdCustom.getValue().isEmpty()) && 
			(txtMdUsuario.getValue() == null || txtMdUsuario.getValue().isEmpty())) {
			refreshLista();
		} else {
			
			gerarLogModelDetail();
		}
	}

	public Paging getPagingAudit() {
		return pagingAudit;
	}

	public void setPagingAudit(Paging pagingAudit) {
		this.pagingAudit = pagingAudit;
	}

	public Combobox getCmbModulo() {
		return cmbModulo;
	}

	public void setCmbModulo(Combobox cmbModulo) {
		this.cmbModulo = cmbModulo;
	}

	public List<AuditModule> getLsModulo() {
		return lsModulo;
	}

	public void setLsModulo(List<AuditModule> lsModulo) {
		this.lsModulo = lsModulo;
	}

	public MyListbox getAuditoriaList() {
		return auditoriaList;
	}

	public void setAuditoriaList(MyListbox auditoriaList) {
		this.auditoriaList = auditoriaList;
	}

	public List<Sistema> getLsAmbiente() {
		return lsAmbiente;
	}

	public void setLsAmbiente(List<Sistema> lsAmbiente) {
		this.lsAmbiente = lsAmbiente;
	}

	public Combobox getCmbAmbiente() {
		return cmbAmbiente;
	}

	public void setCmbAmbiente(Combobox cmbAmbiente) {
		this.cmbAmbiente = cmbAmbiente;
	}

	public Combobox getCmbAcao() {
		return cmbAcao;
	}

	public void setCmbAcao(Combobox cmbAcao) {
		this.cmbAcao = cmbAcao;
	}

	public List<EnumAuditAction> getLsAcao() {
		return lsAcao;
	}

	public void setLsAcao(List<EnumAuditAction> lsAcao) {
		this.lsAcao = lsAcao;
	}

	public Paging getPagingModuleDetail() {
		return pagingModuleDetail;
	}

	public void setPagingModuleDetail(Paging pagingModuleDetail) {
		this.pagingModuleDetail = pagingModuleDetail;
	}

	private void refreshLista() {
		
		auditoriaList.setVisible(true);
		auditoriaModelDetailList.setVisible(false);

		HibernateSearchObject<AuditLog> auditBusqueda = new HibernateSearchObject<AuditLog>(AuditLog.class,
				pagingAudit.getPageSize());

		Comboitem cbiModulo = cmbModulo.getSelectedItem();
		if (cbiModulo != null) {
			AuditModule module = (AuditModule) cbiModulo.getValue();

			if (module.getAuditModuleId() != null) {
				auditBusqueda.addFilterEqual("service.module", module);
			}
		}

		Date dataInicial = dtDataInicial.getValue();
		if (dataInicial != null) {
			auditBusqueda.addFilterGreaterOrEqual("createdDate", dataInicial);
		}

		Date dataFinal = dtDataFinal.getValue();
		if (dataFinal != null) {
			auditBusqueda.addFilterLessOrEqual("createdDate", dataFinal);
		}

		Comboitem cbiAmbiente = cmbAmbiente.getSelectedItem();

		if (cbiAmbiente != null) {
			Sistema sistema = (Sistema) cbiAmbiente.getValue();

			if (sistema.getNombsistema().equals("DIGITACAO")) {
				try {
					Messagebox.show("A auditoria não está habilitada para o sistema " + sistema.getNombsistema(),
							Labels.getLabel("auditoriaController.window.title"),
							Messagebox.OK, Messagebox.INFORMATION);

				} catch (InterruptedException e) {
				}

				return;
			}

			if (sistema.getSistemaId() != null) {
				auditBusqueda.addFilterEqual("sistema", sistema);
			}
		}

		Comboitem cbiAcao = cmbAcao.getSelectedItem();
		if (cbiAcao != null) {
			EnumAuditAction action = (EnumAuditAction) cbiAcao.getValue();
			if (action != EnumAuditAction.TODOS) {
				auditBusqueda.addFilterEqual("action", action.getId());
			}
		}

		plwAuditoria.init(auditBusqueda, auditoriaList, pagingAudit);

		if (auditoriaList.getData().length == 0) {
			try {
				Messagebox.show(Labels.getLabel("MSG.ningunRegistro"),
						Labels.getLabel("auditoriaController.window.title"),
						Messagebox.OK, Messagebox.INFORMATION);

			} catch (InterruptedException ex) {
			}
		}
	}

	@SuppressWarnings("unchecked")
	private void verDetalhesModulo(Object auditLog) {
		if (auditLog == null) {
			return;
		}

		@SuppressWarnings("rawtypes")
		Map args = new HashMap();
		args.put("auditLog", auditLog);

		openWindow("/gui/seguridad/auditModuleDetail.zul",
				Labels.getLabel("auditModuleDetailController.window.title"), args, MODAL);

	}

	private void gerarLogModelDetail() {
		
		auditoriaList.setVisible(false);
		auditoriaModelDetailList.setVisible(true);
		
		AuditLog auditLog = new AuditLog();
		AuditModule module = null;

		Comboitem cbiModulo = cmbModulo.getSelectedItem();
		if (cbiModulo != null) {
			module = (AuditModule) cbiModulo.getValue();

			if (module.getAuditModuleId() != null) {
				AuditService service = new AuditService();
				service.setModule(module);
			}
		}

		Date dataInicio = dtDataInicial.getValue();
		Date dataFim = dtDataFinal.getValue();

		if (dataInicio != null && dataFim != null) {
			auditLog.setDataInicio(dataInicio);
			auditLog.setDataFim(dataFim);
		}

		Comboitem cbiAmbiente = cmbAmbiente.getSelectedItem();

		if (cbiAmbiente != null) {
			Sistema sistema = (Sistema) cbiAmbiente.getValue();

			if (sistema.getNombsistema().equals("DIGITACAO")) {
				try {
					Messagebox.show("A auditoria não está habilitada para o sistema " + sistema.getNombsistema(),
							Labels.getLabel("auditoriaController.window.title"),
							Messagebox.OK, Messagebox.INFORMATION);

				} catch (InterruptedException e) {
				}

				return;
			}

			if (sistema.getSistemaId() != null) {
				auditLog.setSistema(sistema);
			}
		}

		Comboitem cbiAcao = cmbAcao.getSelectedItem();
		if (cbiAcao != null) {
			EnumAuditAction action = (EnumAuditAction) cbiAcao.getValue();
			if (action != EnumAuditAction.TODOS) {
				auditLog.setAction(action.getId());
			}
		}

		List<AuditLog> logs = auditLogService.filtrarLog(auditLog);

		if (logs == null || logs.size() == 0) {
			try {
				Messagebox.show(Labels.getLabel("MSG.ningunRegistro"),
						Labels.getLabel("auditoriaController.window.title"),
						Messagebox.OK, Messagebox.INFORMATION);

			} catch (InterruptedException ex) {
			}

			return;
		}

		if (!txtMdUsuario.getValue().isEmpty()) {
			Integer userId = Integer.parseInt(txtMdUsuario.getValue());

			logs = recuperarUserLogs(logs, userId);
		}

		if (!txtMdCustom.getValue().isEmpty()) {
			logs = recuperarCustomLogs(logs, txtMdCustom.getValue());
		}

		if (logs.size() == 0) {
			try {
				Messagebox.show(Labels.getLabel("MSG.ningunRegistro"),
						Labels.getLabel("auditoriaController.window.title"),
						Messagebox.OK, Messagebox.INFORMATION);

			} catch (InterruptedException ex) {
				log.info(ex.getStackTrace());
			}
		}

		pagingModuleDetail.setTotalSize(logs.size());
		auditoriaModelDetailList.setData(logs);

	}

	public void onClick$btnRefresh(Event ev) {
		refreshLista();
	}

	private List<EnumAuditAction> obterAcoes() {
		List<EnumAuditAction> lsAcao = new ArrayList<EnumAuditAction>();
		lsAcao.add(EnumAuditAction.TODOS);
		lsAcao.add(EnumAuditAction.CRIACAO);
		lsAcao.add(EnumAuditAction.ALTERACAO);
		lsAcao.add(EnumAuditAction.EXCLUSAO);

		return lsAcao;
	}

	private List<AuditLog> recuperarUserLogs(List<AuditLog> logs, Integer userId) {
		Gson gson = AuditControl.getGson();
		List<AuditLog> logsUser = new ArrayList<AuditLog>();

		try {
			for (AuditLog auditLog : logs) {
				Class<?> clazz = Class.forName("com.rjconsultores.ventaboletos.entidad.".concat(auditLog.getEntityName()));
				Object entity = gson.fromJson(auditLog.getEntityDetail(), clazz);

				for (Field field : entity.getClass().getDeclaredFields()) {
					if (field.getName().equalsIgnoreCase("usuarioid")) {
						field.setAccessible(true);
						if (field.get(entity).equals(userId)) {
							logsUser.add(auditLog);
						}

						break;
					}
				}
			}
		} catch (ClassNotFoundException classNotFoundException) {
			log.error(classNotFoundException.getStackTrace());
		} catch (SecurityException securityException) {
			log.error(securityException.getStackTrace());
		} catch (IllegalArgumentException illegalArgumentException) {
			log.error(illegalArgumentException.getStackTrace());
		} catch (IllegalAccessException illegalAccessException) {
			log.error(illegalAccessException.getStackTrace());
		}

		return logsUser;
	}

	private List<AuditLog> recuperarCustomLogs(List<AuditLog> logs, String param) {

		List<AuditLog> logsCustom = new ArrayList<AuditLog>();

		for (AuditLog auditLog : logs) {
			if (auditLog.getEntityDetail().contains(param)) {
				logsCustom.add(auditLog);
			}

		}
		return logsCustom;
	}
}
