package br.com.centralit.asterisk;

import java.io.IOException;
import org.asteriskjava.manager.AuthenticationFailedException;
import org.asteriskjava.manager.ManagerConnection;
import org.asteriskjava.manager.ManagerConnectionFactory;
import org.asteriskjava.manager.ManagerConnectionState;
import org.asteriskjava.manager.ManagerEventListener;
import org.asteriskjava.manager.TimeoutException;
import org.asteriskjava.manager.action.EventsAction;
import org.asteriskjava.manager.event.AgentCalledEvent;
import org.asteriskjava.manager.event.DialEvent;
import org.asteriskjava.manager.event.DisconnectEvent;
import org.asteriskjava.manager.event.ManagerEvent;

import br.com.centralit.citajax.framework.AjaxReverse;
import br.com.centralit.citcorpore.util.Enumerados.ParametroSistema;
import br.com.centralit.citcorpore.util.ParametroUtil;

/**
 * @author euler.ramos - Integração com o servidor Asterisk para detecção de ligações
 */
public class Asterisk extends Thread implements ManagerEventListener {

	private ManagerConnection managerConnection;
	private EventsAction ec;

	public EventsAction getEc() {
		return ec;
	}

	public void setEc(EventsAction ec) {
		this.ec = ec;
	}

	private boolean filaPermitida(String queue) {
		String filas = ParametroUtil.getValorParametroCitSmartHashMap(ParametroSistema.SERVASTERISKFILA, "");
		if (filas.length()>0){
			String[] arrayFilas = filas.split(",");
			for(String s: arrayFilas){
				if(s.equals(queue))
					return true;
			}
			return false;
		} else {
			return true;
		}
	}
	
	private void enviarAlerta(String ligacao, String queue) {
		if (((queue==null)||(queue.length()<=0))||(this.filaPermitida(queue))){
			AjaxReverse.executarAjaxReverseWithAllSessions("exibirNotificacaoAsterisk", new StringBuilder(ligacao).toString());
		}
	}

	public void conectar() {

		if (ParametroUtil.getValorParametroCitSmartHashMap(ParametroSistema.SERVASTERISKATIVAR, "N").equalsIgnoreCase("S")) {
			do {
				if ((this.managerConnection != null)
						&& (!(this.managerConnection.getState().equals(ManagerConnectionState.DISCONNECTED) || this.managerConnection.getState().equals(ManagerConnectionState.DISCONNECTING)))) {
					this.managerConnection.logoff();
				}

				final String asteriskIP = ParametroUtil.getValorParametroCitSmartHashMap(ParametroSistema.SERVASTERISKIP, "0.0.0.0");
				final String asteriskLogin = ParametroUtil.getValorParametroCitSmartHashMap(ParametroSistema.SERVASTERISKLOGIN, "admin");
				final String asteriskSenha = ParametroUtil.getValorParametroCitSmartHashMap(ParametroSistema.SERVASTERISKSENHA, "0");

				ManagerConnectionFactory factory = new ManagerConnectionFactory(asteriskIP, asteriskLogin, asteriskSenha);
				this.managerConnection = factory.createManagerConnection();
				this.managerConnection.addEventListener(this);

				try {
					this.managerConnection.login();
				} catch (IllegalStateException | IOException | AuthenticationFailedException | TimeoutException e) {
					e.printStackTrace();
					this.managerConnection = null;
				}
			} while ((this.managerConnection == null)
					|| ((this.managerConnection != null) && ((this.managerConnection.getState().equals(ManagerConnectionState.DISCONNECTED) || this.managerConnection.getState().equals(
							ManagerConnectionState.DISCONNECTING)))));
		}

	}

	public void run() {
		this.conectar();
	}

	public void onManagerEvent(ManagerEvent event) {

		if (ParametroUtil.getValorParametroCitSmartHashMap(ParametroSistema.SERVASTERISKATIVAR, "N").equalsIgnoreCase("S")) {
			// Evento de Ligação de Ramal para Ramal
			if (event instanceof DialEvent) {
				DialEvent dial = (DialEvent) event;
				if (dial.getSubEvent().equalsIgnoreCase("Begin")) {
					this.enviarAlerta(dial.getCallerIdNum().replaceAll("\\D+","") + "," + dial.getDialString().replaceAll("\\D+","") + "#","");
				}
			}

			// Evento de Ligação Utilizando Agente dinâmico ou Fila
			if (event instanceof AgentCalledEvent) {
				AgentCalledEvent noAnsEvent = (AgentCalledEvent) event;
				this.enviarAlerta(noAnsEvent.getCallerIdNum().replaceAll("\\D+","") + "," + noAnsEvent.getAgentCalled().replaceAll("\\D+","") + "#",noAnsEvent.getQueue());
			}

			// Reconectar para o caso de ocorrer a desconexão
			if (event instanceof DisconnectEvent) {
				this.conectar();
			}
		}

	}

}