package com.fitbank.uci.webservice.client;

import com.fitbank.uci.client.UCILogger;
import com.fitbank.uci.common.UCIException;
import com.fitbank.uci.server.ConnectionProcesor;
import com.fitbank.uci.server.Controlador;
import com.fitbank.uci.server.manager.DeviceEventTypes;
import com.fitbank.uci.server.manager.ParameterDetail;

import java.io.Serializable;

import java.net.InetAddress;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;

public class WSController extends Controlador {

    private SoapClient soapClient = null;
    private UCILogger logger;
    private InetAddress address = null;
    private boolean service = true;
    private boolean monitor = false;
    private boolean connected = false;

    public WSController() {
        logger = UCILogger.getInstance();
    }

    public void setParameters(String pParameters) throws Exception {
        this.parameters = new Properties();

        String[] data = pParameters.split("#");

        if (data.length != 3) {
            throw new UCIException("WSC001", "Error de parametrizacion WSC " + data.length);
        }
        parameters.setProperty("URLSERVICE", "" + data[0]);
        parameters.setProperty("NAMESPACE", "" + data[1]);
        parameters.setProperty("SOAPACTION", "" + data[2]);
        this.service = true;
        soapClient = new SoapClient();
        soapClient.setUrlService(data[0]);
        soapClient.setNameSpace(data[1]);
        soapClient.setSoapAction(data[2]);
        this.addMessage("El servicio WS Client (" + name + ") se ha Iniciado", DeviceEventTypes.INIT);
        this.connected = true;
        this.addMessage("Conexión establecida: " + data[0], DeviceEventTypes.CONNECT);
        start();
    }

    public boolean isConnected() throws Exception {
        return connected;
    }

    public String getDescription() throws Exception {
        return "Conector WSC que permite el manejo de Sockets Cliente";
    }

    public boolean isStarted() throws Exception {
        return this.service;
    }

    public String getStatus() throws Exception {
        return (this.service) ? "UP" : "DOWN";
    }

    public void disconnect() throws Exception {
        try {
            this.connected = false;
            this.service = true;
            addMessage("Cierre de comunicación: " + this.address, DeviceEventTypes.DISCONNECT);
        } catch (Exception e) {
            addMessage(e.getMessage(), DeviceEventTypes.ERROR);
            throw e;
        }
    }

    public Serializable receiveMessage() throws Exception {
        throw new UCIException("UCI-0015", "El controlador (" + name + ") no recive mensajes");
    }

    public void run() {}

    public void sendMessage(Serializable pMessage, Properties pProperties) throws Exception {
        String message = (String) pMessage;

        try {
            String numeroTarjeta = message.split(":")[0];
            String pinEncriptado = message.split(":")[1];
            String result = soapClient.getHomePinBlock(numeroTarjeta, pinEncriptado);

            this.setLastOutputMessage(pMessage.toString());
            this.setLastInputMessage(numeroTarjeta + ":" + result);

            ConnectionProcesor cp = new ConnectionProcesor(numeroTarjeta + ":" + result, this);

            cp.run();
        } catch (Exception e) {
            logger.severe(e.getMessage());
            addMessage("Cierre de comunicación: " + this.address, DeviceEventTypes.DISCONNECT);
            throw e;
        }
    }

    public void shutdown() throws Exception {
        try {
            if (!service) {
                throw new UCIException("UCI-0013", "El Controlador WS Client (" + name + ") ya está detenido");
            }
            disconnect();
            this.addMessage("WS Client (" + name + ") se ha Detenido", DeviceEventTypes.FINISH);
        } catch (Exception e1) {
            throw new Exception(e1);
        }
    }

    public synchronized void startup() throws Exception {
        while (monitor) {
            wait();
        }
        try {
            monitor = true;
            monitor = false;
            this.notify();
        } catch (Exception e1) {
            monitor = false;
            this.notify();
            throw e1;
        }
    }

    @SuppressWarnings("unchecked")
    public String formatParameters(Map pParameters) throws Exception {
        String data = "";
        String aux = "" + Integer.parseInt((String) pParameters.get("URLSERVICE"));

        if (aux == null || aux.compareTo("") == 0) {
            throw new UCIException("PARAM-0001", "URLSERVICE: VALOR REQUERIDO");
        }
        data += aux;
        aux = "" + Integer.parseInt((String) pParameters.get("NAMESPACE"));
        if (aux == null || aux.compareTo("") == 0) {
            throw new UCIException("PARAM-0001", "NAMESPACE: VALOR REQUERIDO");
        }
        data += "#" + aux;
        aux = "" + Integer.parseInt((String) pParameters.get("SOAPACTION"));
        if (aux == null || aux.compareTo("") == 0) {
            throw new UCIException("PARAM-0001", "SOAPACTION: VALOR REQUERIDO");
        }
        data += "#" + aux;
        return data;
    }

    @SuppressWarnings("unchecked")
    public Map parseParametes(String pParameters) throws Exception {
        Map m = this.initParameters();

        if (pParameters == null || pParameters.compareTo("") == 0) {
            return m;
        }

        StringTokenizer st = new StringTokenizer(pParameters, "#");
        List<String> l = new ArrayList<String>();

        while (st.hasMoreElements()) {
            l.add((String) st.nextElement());
        }
        if (l.size() != 3) {
            throw new UCIException("PARAM-0000", "ERROR DE CONFIGURACION");
        }

        ParameterDetail d = (ParameterDetail) m.get("URLSERVICE");

        d.setValue(l.get(0));
        d = (ParameterDetail) m.get("NAMESPACE");
        d.setValue(l.get(1));
        d = (ParameterDetail) m.get("SOAPACTION");
        d.setValue(l.get(2));
        return m;
    }

    private Map<String, ParameterDetail> initParameters() throws Exception {
        Map<String, ParameterDetail> m = new HashMap<String, ParameterDetail>();
        ParameterDetail d = new ParameterDetail("URLSERVICE", "URL del WebService", String.class, true);

        m.put(d.getName(), d);
        d = new ParameterDetail("NAMESPACE", "NameSpace del WebService", String.class, true);
        m.put(d.getName(), d);
        d = new ParameterDetail("SOAPACTION", "Nombre del Método", String.class, true);
        m.put(d.getName(), d);
        return m;
    }
}
