package br.com.centralit.citcorpore.ajaxForms;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONArray;
import org.json.JSONObject;

import com.corundumstudio.socketio.AckCallback;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.DataListener;

import br.com.centralit.citajax.html.AjaxFormAction;
import br.com.centralit.citajax.html.DocumentHTML;
import br.com.centralit.citcorpore.bean.result.ItemQuantidadeDTO;
import br.com.centralit.citcorpore.negocio.UsuarioService;
import br.com.centralit.citcorpore.util.DataSocketIO;
import br.com.centralit.citcorpore.util.Enumerados.ParametroSistema;
import br.com.centralit.citcorpore.util.Enumerados.SituacaoAtivoInativo;
import br.com.centralit.citcorpore.util.ParametroUtil;
import br.com.centralit.citcorpore.util.WebUtil;
import br.com.citframework.excecao.ServiceException;
import br.com.citframework.service.ServiceLocator;
import br.com.citframework.util.Constantes;

public class FormSocketIO extends AjaxFormAction {
	private static SocketIOServer server;
	private static Map<String, Set<UUID>> clients = new HashMap<String, Set<UUID>>();
	private static UsuarioService usuarioService;

	public void startSocketIO(DocumentHTML document, HttpServletRequest request, HttpServletResponse response) throws Exception {
		Configuration config = new Configuration();

		String hostname = "";
		String line = Constantes.SERVER_ADDRESS;
		Pattern pattern = Pattern.compile("http:\\/\\/([a-zA-Z0-9\\-\\.]+)(:|$)");
		Matcher matcher = pattern.matcher(line);
		while (matcher.find()) {
			hostname = matcher.group(1);
			if (hostname.equalsIgnoreCase("localhost")) {
				line = ParametroUtil.getValor(ParametroSistema.URL_Sistema);
				matcher = pattern.matcher(line);
				while (matcher.find()) {
					hostname = matcher.group(1);
				}
			}
		}

		if (!hostname.isEmpty()) {
			document.executeScript("hostname = '" + hostname + "';");
			config.setHostname(hostname);
			config.setPort(3000);
			server = new SocketIOServer(config);

			try {
				server.start();
			} catch (Exception e) {

			}
		}
	}

	public void addListeners(DocumentHTML document, final HttpServletRequest request, HttpServletResponse response) throws Exception {
		server.removeAllListeners("registerClientDashboardUsuarios");
		//server.removeAllListeners("registerClientDashboardSolicitacoes");

		server.addEventListener("registerClientDashboardUsuarios", DataSocketIO.class, registerClientDashboardUsuarios());
		//server.addEventListener("registerClientDashboardSolicitacoes", DataSocketIO.class, registerClientDashboardSolicitacoes(document, request));
	}

	private DataListener<DataSocketIO> registerClientDashboardUsuarios() {
		return new DataListener<DataSocketIO>() {
			@Override
			public void onData(final SocketIOClient client, DataSocketIO data, final AckRequest ackRequest) throws Exception {
				if (ackRequest.isAckRequested()) {
					ackRequest.sendAckData("");
				}
				if (clients != null && clients.get("dashboard-usuarios") != null) {
					clients.get("dashboard-usuarios").add(client.getSessionId());
				} else {
					Set<UUID> set = new HashSet<>();
					set.add(client.getSessionId());
					clients.put("dashboard-usuarios", set);
				}

				FormSocketIO.sendDataDashboardUsuarios();
			}
		};
	}

	/*private DataListener<DataSocketIO> registerClientDashboardSolicitacoes(final DocumentHTML document, final HttpServletRequest request) {
		return new DataListener<DataSocketIO>() {
			@Override
			public void onData(final SocketIOClient client, DataSocketIO data, final AckRequest ackRequest) throws Exception {
				if (ackRequest.isAckRequested()) {
					ackRequest.sendAckData("");
				}
				if (clients != null && clients.get("dashboard-solicitacoes") != null) {
					clients.get("dashboard-solicitacoes").add(client.getSessionId());
				} else {
					Set<UUID> set = new HashSet<>();
					set.add(client.getSessionId());
					clients.put("dashboard-solicitacoes", set);
				}

				FormSocketIO.sendDataDashboardSolicitacoes(document, request);
			}
		};
	}*/

	public static void sendDataDashboardUsuarios() throws Exception {
		Set<UUID> actualClientsDashboardUsuarios = new HashSet<UUID>();
		Set<UUID> clientsDashboardUsuarios = clients.get("dashboard-usuarios");
		if (clientsDashboardUsuarios != null && !clientsDashboardUsuarios.isEmpty()) {
			for (UUID uuid : clientsDashboardUsuarios) {
				SocketIOClient client = server.getClient(uuid);
				if (client == null) {
					continue;
				} else if (!client.isChannelOpen()) {
					client.disconnect();
					continue;
				}
				actualClientsDashboardUsuarios.add(uuid);
				DataSocketIO dataSocketIO = new DataSocketIO();
				int usuariosLogados = WebUtil.getSession().size();

				JSONArray data = new JSONArray();
				data.put(new JSONObject().put("tipo", "countLoggedUsers").put("quantidade", usuariosLogados));

				List<ItemQuantidadeDTO> usersByStatus = getUsuarioService().countByStatus();

				for (ItemQuantidadeDTO itemQuantidadeDTO : usersByStatus) {
					if (SituacaoAtivoInativo.ATIVO.getIdentificador().equalsIgnoreCase(itemQuantidadeDTO.getItem())) {
						data.put(new JSONObject().put("tipo", "countActiveUsers").put("quantidade", itemQuantidadeDTO.getQuantidade()));
					} else {
						data.put(new JSONObject().put("tipo", "countInnactiveUsers").put("quantidade", itemQuantidadeDTO.getQuantidade()));
					}
				}

				dataSocketIO.setJson(data.toString());
				client.sendEvent("setDataDashboardUsuarios", new AckCallback<String>(String.class) {
					@Override
					public void onSuccess(String result) {
						// TODO alguma ação após enviar o evento
					}
				}, dataSocketIO);
			}
		}
		clients.put("dashboard-usuarios", new HashSet<UUID>(actualClientsDashboardUsuarios));
	}

	/*public static void sendDataDashboardSolicitacoes(DocumentHTML document, HttpServletRequest request) throws Exception {
		Set<UUID> clientsDashboardSolicitacoes = clients.get("dashboard-solicitacoes");
		if (clientsDashboardSolicitacoes != null && !clientsDashboardSolicitacoes.isEmpty()) {
			for (UUID uuid : clientsDashboardSolicitacoes) {
				SocketIOClient client = server.getClient(uuid);
				DataSocketIO dataSocketIO = new DataSocketIO();

				JSONObject obj = new JSONObject();

				GerenciamentoServicosDTO gerenciamentoServicosDTO = new GerenciamentoServicosDTO();
				gerenciamentoServicosDTO.setIdStatus(ServiceRequestStatus.IN_PROGRESS.getId());

				if (AppContextHolder.getHttpServletRequest() != null && AppContextHolder.getHttpServletRequest().getSession(true) != null) {
					UsuarioDTO usuarioDTO = (UsuarioDTO) AppContextHolder.getHttpServletRequest().getSession(true).getAttribute(Constantes.getValue("USUARIO_SESSAO") + "_CITCORPORE");

					String COLABORADORES_VINC_CONTRATOS = ParametroUtil.getValorParametroCitSmartHashMap(br.com.centralit.citcorpore.util.Enumerados.ParametroSistema.COLABORADORES_VINC_CONTRATOS, "N");

					if (COLABORADORES_VINC_CONTRATOS == null) {
						COLABORADORES_VINC_CONTRATOS = "N";
					}

					Collection<ContratoDTO> listContratoUsuarioLogado = null;

					if (COLABORADORES_VINC_CONTRATOS != null && COLABORADORES_VINC_CONTRATOS.equalsIgnoreCase("S")) {
						listContratoUsuarioLogado = FormSocketIO.getContratoService().findAtivosByIdEmpregado(usuarioDTO.getIdEmpregado());
					} else {
						listContratoUsuarioLogado = FormSocketIO.getContratoService().listAtivos();
					}

					List<SolicitacaoServicoDTO> listSolicitacaoServicoDTO = FormSocketIO.getSolicitacaoServicoService(null).recuperaSolicitacoesPorUsuarioComFiltro(usuarioDTO, listContratoUsuarioLogado, gerenciamentoServicosDTO);
					Map<String, Integer> mapTipoSolicitacaoServico = FormSocketIO.getSolicitacaoServicoService(null).resumoTipoDemandaServico(listSolicitacaoServicoDTO);

					for (Map.Entry<String, Integer> tipoSolicitacaoServico : mapTipoSolicitacaoServico.entrySet()) {
						obj.put(UtilI18N.internacionaliza(request, tipoSolicitacaoServico.getKey()), tipoSolicitacaoServico.getValue());
					}
				}

				dataSocketIO.setJson(obj.toString());
				client.sendEvent("setDataDashboardSolicitacoes", new AckCallback<String>(String.class) {
					@Override
					public void onSuccess(String result) {
						// TODO alguma ação após enviar o evento
					}
				}, dataSocketIO);
			}
		}
	}*/

	public void stopSocketIO(DocumentHTML document, HttpServletRequest request, HttpServletResponse response) throws Exception {
		server.stop();
	}

	@Override
	public void load(DocumentHTML document, HttpServletRequest request, HttpServletResponse response) throws Exception {

	}

	@Override
	public Class<DataSocketIO> getBeanClass() {
		return DataSocketIO.class;
	}

	private static UsuarioService getUsuarioService() throws ServiceException {
		if (usuarioService == null) {
			usuarioService = (UsuarioService) ServiceLocator.getInstance().getService(UsuarioService.class, null);
		}

		return usuarioService;
	}
}
