/* 
* Copyright 2016 Agencia Estatal de Administración Tibutaria
*
* Licencia con arreglo a la EUPL, Versión 1.1 o –en cuanto
* sean aprobadas por la Comisión Europea– versiones
* posteriores de la EUPL (la «Licencia»);
* Solo podrá usarse esta obra si se respeta la Licencia.
* Puede obtenerse una copia de la Licencia en:
*  
* https://joinup.ec.europa.eu/software/page/eupl
*  
* Salvo cuando lo exija la legislación aplicable o se acuerde
* por escrito, el programa distribuido con arreglo a la
* Licencia se distribuye «TAL CUAL», SIN GARANTÍAS NI CONDICIONES
* DE NINGÚN TIPO, ni expresasni implícitas.
*
* Véase la Licencia en el idioma concreto que rige los permisos y 
* limitaciones que establece la Licencia.
*/ 

package administrador;

import administrador.utiles.*;
import sockets.BuferRecibidoEvent;
import sockets.MensajeRecibidoEvent;
import sockets.MessageSocket;
import sockets.MessageSocketListener;

public class Comunicaciones {

    //<editor-fold desc="Constantes">
    // mensajes recibidos
    public static final int CONEXION_ACEPTADA = 101;
    public static final int MSG_ENVIO_ACCIONES = 102;
    public static final int MSG_ENVIO_RESUMEN_RETRASOS = 103;
    public static final int MSG_ENVIO_REGISTRO_OPERADORES = 105;
    public static final int MSG_COMENZAR_OPERACION = 107;
    public static final int MSG_CAMBIO_CAPACIDAD = 108;
    public static final int MSG_CAMBIO_NAVEGACION = 109;
    public static final int MSG_CAMBIO_AUTOMATICO = 110;
    public static final int MSG_DATOS_TICKET = 111;
    public static final int MSG_DATOS_HISTORICO_TICKET = 112;
    public static final int MSG_HUECOS_POR_COLA = 113;
    public static final int MSG_COMIENZO_ENVIO_COLAS = 114;
    public static final int MSG_CIERRE_URGENTE = 80;
    public static final int MSG_ENVIO_REGISTRO_COLAS = 404;
    public static final int MSG_MENSAJE_DE_MESA = 120;
    public static final int MSG_ENVIO_LISTA_ADMINISTRADORES = 123;
    public static final int MSG_ENVIO_FICHERO_NOTIFICACIONES = 124;
    public static final int MSG_ENVIO_FICHERO_PRESENTES = 125;
    public static final int MSG_RANGO_HUECOS = 126;
    public static final int MSG_ENVIO_FICHERO_NOTAS = 127;
    public static final int MSG_COMENZAR_ENVIO_CERTIFICADO = 130;

    // mensajes enviados
    public static final int COD_CONECTAR = 101;
    public static final int COD_INICIAR_MODO_AUTOMATICO = 105;
    public static final int COD_PEDIR_HISTORICO_TICKET = 106;
    public static final int COD_PEDIR_DATOS_TICKET = 107;
    public static final int COD_CAMBIAR_CAPACIDAD = 108;
    public static final int COD_CERRAR_COLA = 109;
    public static final int COD_REPETIR_ENVIO = 110;
    public static final int COD_REPETIR_RECEPCION = 111;
    public static final int COD_ENVIAR_ACCIONES = 112;
    public static final int COD_MODIFICAR_UMBRAL_SUSTITUTOS = 113;
    public static final int COD_NUEVO_OPERADOR = 114;
    public static final int COD_GENERAR_HUECOS = 115;
    public static final int COD_OCUPAR_HUECOS = 116;
    public static final int COD_SOLICITO_HUECOS_COLA = 117;
    public static final int COD_MENSAJE_A_MESA = 120;
    public static final int COD_MENSAJE_A_GESTORES = 121;
    public static final int COD_MENSAJE_RECIBIDO = 122;
    public static final int COD_MENSAJE_A_OPERADORES = 123;
    public static final int COD_ENVIAR_LISTA_ADMINISTRADORES = 124;
    public static final int COD_ENVIO_MENSAJE_PARA_ADMINISTRADORES = 125;
    public static final int COD_ENVIO_FICHERO_NOTIFICACIONES = 126;
    public static final int COD_ENVIO_FICHERO_PRESENTES = 127;
    public static final int COD_ENVIO_MODI_RANGO = 128;
    public static final int COD_ENVIO_CERTIFICADO = 130;
    public static final int COD_ENVIO_FICHERO_NOTAS = 131;
    public static final int SOLICITO_CAMBIO_AUTOMATICO = 402;
    //</editor-fold>
    MessageSocket sock;
    String Ip;
    int puertoIp;
    PanelServidor panel;
    boolean local = false;
    Configuracion conf;

    public Comunicaciones(PanelServidor panel) {
        this.panel = panel;
        conf = Configuracion.instanciaUnica();
        sock = new MessageSocket();
    }

    public String getHost() {
        return Ip;
    }

    public void configuraIp(String Ip) {
        if (Ip.equals("")) {
            if (!conf.usandoUDP) {
                this.Ip = conf.IpServidorLocal;
                this.puertoIp = conf.puertoServidor;
            }
        } else {
            int pos = Ip.indexOf(':');
            if (pos >= 0) {
                this.Ip = Ip.substring(0, pos);
                puertoIp = Integer.parseInt(Ip.substring(pos + 1));
            } else {
                this.Ip = Ip;
                puertoIp = conf.puertoServidor;
            }
        }
    }

    public void cerrar() {
        sock.close();
    }

    public boolean estaAbierto() {
        return sock.abierto();
    }

    public boolean abrir() {
        if (!panel.soyLocal) {
            sock.setHost(Ip);
            sock.setPuerto(puertoIp);
            return sock.open();
        }
        if (conf.usandoUDP) {
            sockets.SocketUDP udp = new sockets.SocketUDP(conf.nombreServidor, conf.puertoServidor);
            String ip = udp.buscarServidorEnLaRed(2000);
            if (!ip.equals("")) {
                this.Ip = ip;
                sock.setHost(ip);
                sock.setPuerto(conf.puertoServidor);
                return sock.open();
            }
            return false;  // no se ha encontrado el servidor abierto

        } else {
            Ip = conf.IpServidorLocal;
            sock.setHost(Ip);
            sock.setPuerto(conf.puertoServidor);
            if (!sock.open()) {
                Ip = conf.IpServidorLocalSec;
                sock.setHost(Ip);
                sock.setPuerto(conf.puertoServidorSec);
                return sock.open();     // devolver intento con el secundario
            } else {
                return true;   // abierto con Ip primario
            }
        }
    }

    public void enviarCodigoConexion(String nombre) {
        enviar(COD_CONECTAR, nombre);
    }

    public void enviarMensaje(String origen, String mesa, String mensaje) {
        int codigo;
        if (mesa.equals("gestores")) {
            codigo = COD_MENSAJE_A_GESTORES;
        } else if (mesa.equals("operadores")) {
            codigo = COD_MENSAJE_A_OPERADORES;
        } else {
            codigo = COD_MENSAJE_A_MESA;
        }
        enviar(codigo, origen, mesa, mensaje);
    }

    public void confirmarLecturaMensaje(String mesaOrigen) {
        enviar(COD_MENSAJE_RECIBIDO, mesaOrigen);
    }

    public void pedirTicket(String ticket) {
        enviar(COD_PEDIR_DATOS_TICKET, ticket);
    }

    public void pedirUnaNotaTicket(String tabla, String id) {
        enviar(COD_ENVIO_FICHERO_NOTAS, tabla, id);
    }

    public void pedirHistoricoTicket(String nif) {
        enviar(COD_PEDIR_HISTORICO_TICKET, nif);
    }

    public void enviarCambioCapacidad(String codigo, String cadenaCapacidad, String cadenaSuplencias) {
        enviar(COD_CAMBIAR_CAPACIDAD, codigo, cadenaCapacidad, cadenaSuplencias);
    }

    void errorEnSocket(String msg) {
        try {
            sock.close();
            panel.errorEnSocket(msg);
        } catch (Exception exc) {
            exc.printStackTrace();
        }
    }

    void prepararSocket() {
        sock.setProcesaMensajes(true);
        sock.addMessageSocketListener(new MessageSocketListener() {

            @Override
            public void mensajeRecibido(MensajeRecibidoEvent ev) {
                final int codigo = ev.getCodigo();
                final String msj = ev.getMensaje();
                Runnable runnable = new Runnable() {

                    @Override
                    public void run() {
                        mensajeDelServidor(codigo, msj);
                    }
                };
                try {
                    javax.swing.SwingUtilities.invokeLater(runnable);
                } catch (Exception exc) {
                }
            }

            @Override
            public void errorSocket(MensajeRecibidoEvent ev) {
                errorEnSocket(ev.getMensaje());
            }

            @Override
            public void buferRecibido(BuferRecibidoEvent evt) {
            }
        });
    }

    void mensajeDelServidor(int codigo, String msg) {
        switch (codigo) {
            case CONEXION_ACEPTADA:
                panel.conexionAceptada(msg);
                break;
            case MSG_ENVIO_ACCIONES:
                panel.envioAcciones(msg);
                break;
            case MSG_ENVIO_RESUMEN_RETRASOS:
                panel.resumenRetrasos(msg);
                break;
            case MSG_ENVIO_REGISTRO_OPERADORES:
                panel.grabaRegistroOperadores(msg);
                break;
            case MSG_COMENZAR_OPERACION:
                panel.calcularOperadores();
                panel.activarInterfaz(true);
                break;
            case MSG_MENSAJE_DE_MESA:
                panel.mensajeDeMesa(msg);
                break;
            case COD_MENSAJE_RECIBIDO:
                Global.MsgBox("EL MENSAJE HA SIDO RECIBIDO");
                break;
            case MSG_COMIENZO_ENVIO_COLAS:
                panel.vaciarColas();
                break;
            case MSG_ENVIO_REGISTRO_COLAS:
                panel.registroColas(msg);
                break;
            case MSG_CAMBIO_CAPACIDAD:
                panel.cambioCapacidad(msg);
                break;
            case MSG_CAMBIO_NAVEGACION:
                break;
            case MSG_CAMBIO_AUTOMATICO:
                panel.actualizaModo(msg);
                break;
            case MSG_DATOS_TICKET:
                panel.mostrarDatosTicket(msg);
                break;
            case MSG_CIERRE_URGENTE:
                panel.desconectar();
                break;
            case MSG_COMENZAR_ENVIO_CERTIFICADO:
                panel.enviarCertificado();
                break;
            case MSG_HUECOS_POR_COLA:
                panel.cargarListaHuecos(msg);
                break;
            case MSG_ENVIO_LISTA_ADMINISTRADORES:
                panel.abrirMensajeAAdministradores(msg);
                break;
            case MSG_ENVIO_FICHERO_PRESENTES:
                panel.abrirFicheroPresentes(msg);
                break;
            case MSG_RANGO_HUECOS:
                panel.setcadenaRangoHuecos(msg);
                break;
            case MSG_ENVIO_FICHERO_NOTAS:
                panel.grabarNotas(msg);
                break;
            default:
                break;
        }
    }

    public void enviar(int codigo, Object... vars) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < vars.length; i++) {
            sb.append(vars[i].toString());
            if (i + 1 < vars.length) {
                sb.append('|');
            }
        }
        sock.enviar(sb.toString(), codigo);
    }

    public void enviar(java.io.InputStream data) {
        sock.enviar(data);
    }
}
