/* 
* 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 gestor;

import gestor.utiles.Global;
import sockets.*;

public class Comunicaciones {

   //<editor-fold desc="Constantes">
   // Mensajes recibidos
   public static final int CONEXION_ACEPTADA = 401;
   public static final int MSG_NUMERO_CANDIDATOS = 402;
   public static final int MSG_REGISTRO_CANDIDATOS = 403;
   public static final int MSG_REGISTRO_COLAS = 404;
   public static final int MSG_NUEVO_CANDIDATO = 405;
   public static final int MSG_MODIFICACION_CANDIDATO = 406;
   public static final int MSG_CAMBIO_ESTADO_MESA = 407;
   public static final int MSG_CAMBIO_NUMERO_MESAS = 408;
   public static final int MSG_REGISTRO_HUECOS = 409;
   public static final int MSG_CAMBIO_TURNO = 410;
   public static final int MSG_CIERRE_DE_COLA = 415;
   public static final int MSG_HUECO_OCUPADO = 416;
   public static final int MSG_OCUPAR_HUECO = 417;
   public static final int MSG_MODIFICACION_CANDIDATO_NOPRESENTE = 418;
   public static final int MSG_HUECOS_POR_COLA = 419;
   public static final int MSG_LISTAR_HUECOS = 423;
   public static final int MSG_PREGUNTAR_HORA = 426;
   public static final int MSG_RANGO_HUECOS = 427;
   public static final int MSG_CIERRE_URGENTE = 80;
   // Mensajes enviados
   public static final int CONEXION = 401;
   public static final int SOLICITO_HORA = 405;
   public static final int ENVIAR_TABLA_CANDIDATOS = 411;
   public static final int ENVIO_NUEVO_CANDIDATO = 412;
   public static final int ENVIO_MODIFICACION_CANDIDATO = 413;
   public static final int ENVIO_NUEVO_CANDIDATO_NOPRESENTE = 416;
   public static final int MENSAJE_A_ADMINISTRADOR = 420;
   public static final int ENVIO_HORA = 426;
   public static final int MSG_COMIENZO_ENVIO_COLAS = 114;
   public static final int MENSAJE_A_GESTORES = 121;
   //</editor-fold>
   MessageSocket sock;
   String ipHost;
   int puertoHost;
   public static Comunicaciones comm;
   String sep = "|";

   SocketUDP udp = null;
   Configuracion conf;

   public Comunicaciones() {
      comm = this;
      conf = gestor.Configuracion.instanciaUnica();
      if (!Configuracion.instanciaUnica().nombreServidor.equals("")) {
         try {
            udp = new SocketUDP(conf.nombreServidor, conf.puertoIpServidor);
         } catch (Exception exc) {
         }
      }
   }

   public void abrirSock(boolean principal) {
      if (!conf.usandoUDP) {
         if (principal) {
            sock.setHost(Configuracion.instanciaUnica().ipServidor);
            sock.setPuerto(Configuracion.instanciaUnica().puertoIpServidor);
         } else {
            sock.setHost(Configuracion.instanciaUnica().ipServidorSec);
            sock.setPuerto(Configuracion.instanciaUnica().puertoIpServidorSec);
         }
      } else {
         String ip = udp.buscarServidorEnLaRed(2000);
         if (!ip.equals("")) {
            sock.setHost(ip);
            sock.setPuerto(Configuracion.instanciaUnica().puertoIpServidor);
         } else {
            return;
         }
      }
      sock.open();
   }

   public boolean abrir() {
      if (sock != null && sock.abierto()) {
         sock.close();
      }
      sock = new MessageSocket();
      sock.setProcesaMensajes(true);
      abrirSock(true);
      boolean retorno = true;
      if (!sock.abierto()) {
         DlgReconectando dlg = new DlgReconectando(Global.mainForm);
         dlg.setVisible(true);
         if (dlg.cancelado) {
            retorno = false;
         }
         dlg.dispose();
         dlg = null;
      } else {
         restablecer();
      }
      return retorno;
   }

   public void restablecer() {
      sock.addMessageSocketListener(new MessageSocketListener() {

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

               public void run() {
                  mensajeDelServidor(codigo, msj);
               }
            };
            try {
               if (Global.panel == null) {
                  mensajeDelServidor(codigo, msj);
               } else {
                  javax.swing.SwingUtilities.invokeLater(runnable);
               }
            } catch (Exception exc) {
               exc.printStackTrace();
            }

         }

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

         public void buferRecibido(BuferRecibidoEvent evt) {
         }
      });
      enviar(CONEXION, Configuracion.instanciaUnica().codigoGestor, "1");
   }

   void mensajeDelServidor(int codigo, String mensaje) {
      switch (codigo) {
         case CONEXION_ACEPTADA:
            Global.mainForm.conexionAceptada(mensaje);
            break;
         case MSG_COMIENZO_ENVIO_COLAS:
            Global.mainForm.iniciarEnvioDeColas();
            break;
         case MSG_REGISTRO_COLAS:
            Global.mainForm.nuevoRegistroColas(mensaje);
            break;
         case MSG_CIERRE_DE_COLA:
            Global.mainForm.cambiarEstadoCola(mensaje);
            break;
         case MSG_NUEVO_CANDIDATO:
            Global.mainForm.nuevoCandidato(mensaje);
            break;
         case MSG_MODIFICACION_CANDIDATO_NOPRESENTE:
            Global.mainForm.nuevoCandidatoNoPresente(mensaje);
            break;
         case MSG_OCUPAR_HUECO:
            Global.mainForm.huecos.eliminar(mensaje);
            break;
         case MSG_HUECO_OCUPADO:
            Global.panel.huecoOcupado(mensaje);
            break;
         case MSG_HUECOS_POR_COLA:
            Global.mainForm.incorporarHuecos(mensaje);
            break;
         case MSG_MODIFICACION_CANDIDATO:
            Global.mainForm.cambiaEstadoCandidato(mensaje);
            break;
         case MSG_CAMBIO_ESTADO_MESA:
            break;
         case MSG_CAMBIO_NUMERO_MESAS:
            break;
         case MSG_NUMERO_CANDIDATOS:
            Global.mainForm.iniciarCargaCandidatos();
            break;
         case MSG_REGISTRO_CANDIDATOS:
            Global.mainForm.nuevoRegistroCandidatos(mensaje);
            break;
         case MSG_REGISTRO_HUECOS:
            Global.mainForm.nuevoRegistroHuecos(mensaje);
            break;
         case MSG_CAMBIO_TURNO:
            Global.mainForm.setTurno(mensaje);
            break;
         case MSG_LISTAR_HUECOS:
            gestor.datos.TablaHuecos.getTablaHuecos().listarHuecos();
            break;
         case MSG_PREGUNTAR_HORA:
             Global.mainForm.enviarHora();
            break;
         case MSG_RANGO_HUECOS:
             gestor.datos.TablaHuecos.getTablaHuecos().cargarRangoHuecos(mensaje);
            break;
         case MSG_CIERRE_URGENTE:
            Main.reiniciarConScript();
            break;
         default:
            break;
      }
   }

   void errorEnSocket(String mensaje) {
      if (mensaje.startsWith("Connection")) {
         try {
            sock.close();
            Runnable rn = new Runnable() {

               public void run() {
                  gestor.datos.TablaCandidatos.getTablaCandidatos().vaciar();
                  if (!abrir()) {
                     Global.panel.pedirPin(true);
                  }
               }
            };
            if (javax.swing.SwingUtilities.isEventDispatchThread()) {
               rn.run();
            } else {
               javax.swing.SwingUtilities.invokeAndWait(rn);
            }
         } catch (InterruptedException exc) {
         } catch (Exception exc) {
            System.out.println(gestor.utiles.Fecha.formatoHoraHMS(new java.util.Date()) +
                    " - Error procesando mensaje: " + mensaje);
            exc.printStackTrace();
         }
      }
   }

   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(sep);
      }
      sock.enviar(sb.toString(), codigo);
   }

   public void enviar(int codigo) {
      sock.enviar(codigo + "\n");
   }

}
