package br.com.centralit.citsmart.rest.inventory;

import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import javax.ws.rs.Consumes;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;

import br.com.centralit.citcorpore.bean.EvmConexaoDTO;
import br.com.centralit.citcorpore.bean.EvmInventoryConfiguracaoDTO;
import br.com.centralit.citcorpore.bean.FormulaDTO;
import br.com.centralit.citcorpore.bean.InventarioDTOTmp;
import br.com.centralit.citcorpore.bean.ItemConfiguracaoDTO;
import br.com.centralit.citcorpore.comm.server.ProcessarHashmapInventarioAgente;
import br.com.centralit.citcorpore.metainfo.script.ScriptRhinoJSExecute;
import br.com.centralit.citcorpore.metainfo.util.RuntimeScript;
import br.com.centralit.citcorpore.negocio.EvmConexaoService;
import br.com.centralit.citcorpore.negocio.EvmInventoryConfiguracaoService;
import br.com.centralit.citcorpore.negocio.FormulaService;
import br.com.centralit.citcorpore.negocio.ItemConfiguracaoService;
import br.com.centralit.citsmart.rest.evm.RestUtilsEVM;
import br.com.centralit.citsmart.rest.schema.CtInventario;
import br.com.centralit.citsmart.rest.schema.CtLogin;
import br.com.centralit.citsmart.rest.schema.HostItem;
import br.com.citframework.excecao.LogicException;
import br.com.citframework.excecao.ServiceException;
import br.com.citframework.service.ServiceLocator;
import br.com.citframework.util.UtilDatas;
import br.com.citframework.util.UtilI18N;

/**
 * Esta classe contém os métodos para acesso via webservice do Citsmart Inventory
 * 
 * @since 20/02/2015
 * @author cristian.guedes
 *
 */
@Path("/citsmartInventory")
public class RestCitsmartInventoryResources extends RestUtilsEVM {
	private Logger logger = Logger.getLogger(RestCitsmartInventoryResources.class.getName());

	/**
	 * Este método do resteasy receberá o resultado do inventário realizado pelo Citsmart Inventory
	 * 
	 * @param login
	 * @return O status do processamento
	 */
	@PUT
	@Path("/recebeInventario")
	@Consumes("application/json")
	public Response setRetornoInventario(CtInventario ctInventario) {

		try {
			CtLogin login = new CtLogin();
			login.setPassword(ctInventario.getPassword());
			login.setUserName(ctInventario.getUserName());

			if (isAutenticar(login)) {

				Set<HostItem> inventario = ctInventario.getInventario();

				StringBuilder mapParaXML = new StringBuilder();

				mapParaXML.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
				mapParaXML.append("<REQUEST>");
				mapParaXML.append("<CONTENT>");

				for (HostItem hostItem : ctInventario.getInventario()) {
					mapParaXML.append("<" + hostItem.getName() + ">");

					for (Map.Entry<String, String> entry : hostItem.getProperties().entrySet()) {
						String key = entry.getKey();
						String value = entry.getValue();

						mapParaXML.append("<" + key + ">");

						value = value.replaceAll("\\<", "usainbolt_menorque");

						value = value.replaceAll("\\>", "usainbolt_maiorque");

						// remove caracteres não imprimíveis
						value = value.replaceAll("[\\x00\\x08\\x0B\\x0C\\x0E-\\x1F]", "");

						if (value.contains("&")) {
							value = value.replaceAll("\\&", "usainbolt_ecomercial");
						}

						mapParaXML.append(value);

						mapParaXML.append("</" + key + ">");

					}

					mapParaXML.append("</" + hostItem.getName() + ">");

				}

				mapParaXML.append("</CONTENT>");
				mapParaXML.append("</REQUEST>");

				logger.info(mapParaXML.toString());

				persistirIC(inventario);

				logger.info("Acesso ao WS realizada.");
				logger.info("Serviço acessado: /citsmartInventory/inventario");
				return Response.status(Status.OK).entity("Evento/Inventário foi recebido pelo Citsmart!").build();

			} else {
				logger.info("Acesso ao WS realizada.");
				logger.info("Houve falha no acesso ao serviço!");
				return Response.status(Status.PRECONDITION_FAILED).entity(UtilI18N.internacionaliza(httpRequest, "operacaoRest.autenticacaoFalhou")).build();

			}

		} catch (Exception e) {
			e.printStackTrace();
			return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
		}

	}

	private void persistirIC(Set<HostItem> objetosInventario) throws ServiceException, LogicException, Exception {
		ProcessarHashmapInventarioAgente mapReadDtdAgente = new ProcessarHashmapInventarioAgente();

		// Ignora dados de ic's que nãõ puderam ser inventariados. Possui a palavra "UNREACHABLE" no nó "NETWORKS".
		if (objetosInventario.size() < 3) {
			return;
		}

		List<ItemConfiguracaoDTO> list = mapReadDtdAgente.processarHashmapInventario(objetosInventario);

		SimpleDateFormat spd = new SimpleDateFormat("yyyyMMdd");
		Date dataAtual = UtilDatas.getDataAtual();
		String dataAtualInv = spd.format(dataAtual).trim();

		if (list != null) {

			ItemConfiguracaoService serviceItem = null;
			try {
				serviceItem = (ItemConfiguracaoService) ServiceLocator.getInstance().getService(ItemConfiguracaoService.class, null);
			} catch (ServiceException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}

			FormulaService formulaService = null;

			try {
				formulaService = (FormulaService) ServiceLocator.getInstance().getService(FormulaService.class, null);
			} catch (ServiceException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}

			try {
				Collection<FormulaDTO> col = formulaService.findByIdentificador(FormulaDTO.FORMULA_INVENTORY_PROCESS_SAVE);
				if (col != null && !col.isEmpty()) {
					for (FormulaDTO formulaDTO : col) {
						if (formulaDTO != null) {
							String strScript = formulaDTO.getConteudo();
							if (strScript != null && !strScript.trim().equalsIgnoreCase("")) {
								ScriptRhinoJSExecute scriptExecute = new ScriptRhinoJSExecute();
								RuntimeScript runtimeScript = new RuntimeScript();
								Context cx = Context.enter();
								Scriptable scope = cx.initStandardObjects();
								scope.put("listaInfo", scope, list);
								// scope.put("fileName", scope, fileName);
								// scope.put("netMapDTO", scope, netMapDTO);
								scope.put("thread", scope, this);
								scope.put("out", scope, System.out);
								scope.put("dataAtualInv", scope, dataAtualInv);
								scope.put("RuntimeScript", scope, runtimeScript);
								scriptExecute.processScript(cx, scope, strScript, FormulaDTO.FORMULA_INVENTORY_PROCESS_SAVE);
							}
						}
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			try {
				List<ItemConfiguracaoDTO> listaSincronizada = Collections.synchronizedList(new ArrayList<ItemConfiguracaoDTO>(list));
				synchronized (listaSincronizada) {
					if (listaSincronizada != null && !listaSincronizada.isEmpty()) {
						for (ItemConfiguracaoDTO itemConfiguracaoDTO : listaSincronizada) {
							serviceItem.createItemConfiguracao(itemConfiguracaoDTO, null);
						}
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}

		}

	}

	@PUT
	@Path("/obtemParametrosInicializacao")
	@Consumes("application/json")
	@Produces("application/json")
	public Response getParametrosInicializacao(CtLogin login) {

		InventarioDTOTmp inventarioDTOTmp = null;

		try {
			logger.info("Citsmart > Obtendo configuração válida de inicialização para o Citsmart Inventory.");

			if (isAutenticar(login)) {
				EvmInventoryConfiguracaoService evmInventoryConfiguracaoService = (EvmInventoryConfiguracaoService) ServiceLocator.getInstance().getService(EvmInventoryConfiguracaoService.class, null);
				EvmInventoryConfiguracaoDTO evmInventoryConfiguracaoDTO = evmInventoryConfiguracaoService.getByIdInventory(login.getIdCitsmartInventory());
				
				EvmConexaoService evmConexaoService = (EvmConexaoService) ServiceLocator.getInstance().getService(EvmConexaoService.class, null);
				EvmConexaoDTO evmConexaoDTO = evmConexaoService.getConexaoById(evmInventoryConfiguracaoDTO.getIdConexao());

				if (evmConexaoDTO != null) {
					inventarioDTOTmp = new InventarioDTOTmp();
					inventarioDTOTmp.setCompleto(true);
					inventarioDTOTmp.setFaixa(evmInventoryConfiguracaoDTO.getFaixaIp());
					if(evmInventoryConfiguracaoDTO.getPortaNet() != null)
						inventarioDTOTmp.setPortaAgenteDotNet(evmInventoryConfiguracaoDTO.getPortaNet());
					inventarioDTOTmp.setPortaSNMP(String.valueOf(evmInventoryConfiguracaoDTO.getPortaSNMP()));
					inventarioDTOTmp.setDestino(evmInventoryConfiguracaoDTO.getDestinoInventario());
					inventarioDTOTmp.setExpressaoCron(evmInventoryConfiguracaoDTO.getExpressaoCron());
					inventarioDTOTmp.setIpServidorInv(evmInventoryConfiguracaoDTO.getIpServidor());
					inventarioDTOTmp.setIgnorarIcsInventariados(evmInventoryConfiguracaoDTO.getIgnorarIcsInventariados());
					inventarioDTOTmp.setTempoIgnorarIcs(evmInventoryConfiguracaoDTO.getTempoIgnorarIcs());
					inventarioDTOTmp.setTipoIgnorarIcs(evmInventoryConfiguracaoDTO.getTipoIgnorarIcs());
					inventarioDTOTmp.setIdConexao(evmInventoryConfiguracaoDTO.getIdConexao());
				} else {
					logger.info("Citsmart > Não foi possível obter uma configuração válida de inicialização para o Citsmart Inventory.");
				}

				logger.info("Citsmart > Acesso ao WS realizada. Serviço acessado: /citsmartInventory/parametros");
				return Response.status(Status.OK).entity(inventarioDTOTmp).build();
			} else {
				logger.info("Citsmart > Falha no acesso ao serviço.");
				return Response.status(Status.PRECONDITION_FAILED).entity(UtilI18N.internacionaliza(httpRequest, "operacaoRest.autenticacaoFalhou")).build();
			}
		} catch (Exception e) {
			e.printStackTrace();
			return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
		}

	}

}
