/* 
* 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 servidor.clientes;

import java.util.*;
import java.util.logging.Level;
import servidor.comunicaciones.*;
import servidor.datos.TablaPuestos;
import servidor.datos.base.*;
import servidor.utiles.Global;
import servidor.utiles.MensajeException;

public class Operador extends Cliente {

    //<editor-fold desc="1. Constantes ">
    public static final int NOCONECTADO = 0;
    public static final int CONECTADO = 1;
    public static final int LIBRE = 2;
    public static final int ENTRANSITO = 3;
    public static final int OCUPADO = 4;
    public static final int DESCANSO = 5;
    String[] txtEstado = {"No conectado", "Conectado", "Libre", "En tránsito", "Ocupado", "No Disponible"};
    public static final int CONEXION_ACEPTADA = 1;
    public static final int MSG_NUEVO_CONTRIBUYENTE = 2;
    public static final int MSG_NUEVO_CONTRIBUYENTEVINCULADO = 3;
    public static final int MSG_PENDIENTES = 4;
    public static final int MSG_MENSAJE_DEL_ADMINISTRADOR = 20;
    public static final int MSG_MENSAJE_DEL_GESTOR = 21;
    public static final int MSG_MENSAJE_RECIBIDO = 22;
    public static final int MSG_EJECUTA_SCRIPT = 23;
    public static final int MSG_MENSAJE_MASCITAS = 24;
    public static final int MSG_ESTADO_CITA = 25;
    public static final int MSG_ESTADO_COLAS = 26;
    public static final int MSG_CATEGORIA_ESTADISTICA = 27;
    public static final int MSG_ESTADO_BOTONCOLACERO = 28;
    public static final int MSG_HUECO_CONCEDIDO = 29;
    public static final int MSG_HUECO_DENEGADO = 30;
    public static final int MSG_LISTAOPERADORES = 31;
    public static final int MSG_IGNORA_ESTE_MENSAJE = 97;
    public static final int MESA_RECHAZADA = 98;
    public static final int OPERADOR_RECHAZADO = 99;
    public static final int MSG_CIERRE_URGENTE = 80;
    public static final int MSG_REINICIAR = 81;
    private String puesto;
    private String nombre;
    private int estado;
    private HashMap<String, DatosCapacidad> capacidades;
    private HashSet<String> suplencias;
    private String estadoNavegacion;
    public Date horaUltimaAsignacion;
    public String colaActual;
    public int citasActuales;
    public String localizacion;
    public String version = "no espec.";
    public boolean operativo = false;
    public RegistroCandidatos reg = null;
    public boolean autorizadoParaReenviar = true;
    public String nombrelargo = "";
    public String centro = " ";

    public String getPuesto() {
        return puesto;
    }

    public String getCentro() {
        return centro;
    }

    public void setCentro(String centroOpe) {
        centro = centroOpe;
    }

    public int getNumPuesto() {
        try {
            return Integer.parseInt(puesto);
        } catch (NumberFormatException exc) {
            return 0;
        }
    }

    public String getNombre() {
        return nombre;
    }

    public String getNombreLargo() {
        return nombrelargo;
    }

    public void setNombreLargo(String nombreCompleto) {
        nombrelargo = nombreCompleto;
    }

    public void setEstado(int estado) {
        this.estado = estado;
        operativo = estado != 0;
    }

    public int getEstado() {
        return estado;
    }

    public void setEstadoNavegacion(String nuevoEstado) {
        estadoNavegacion = nuevoEstado;
    }

    public String getEstadoNavegacion() {
        return estadoNavegacion;
    }

    public String getLocalizacion() {
        return localizacion;
    }

    public void setLocalizacion(String localizacion) {
        if (localizacion == null) {
            localizacion = " ";
        }
        this.localizacion = localizacion;
    }

    public void setOperativo(boolean s) {
        operativo = s;
    }

    public boolean isOperativo() {
        return operativo;
    }

    public void marcarAsignacion(String cola, int citas) {
        horaUltimaAsignacion = new Date();
        colaActual = cola;
        citasActuales = citas;
        estado = ENTRANSITO; //OCUPADO;
        operativo = true;
    }

    public Operador(servidor.comunicaciones.Mensaje msj) throws MensajeException {
        super(msj.getHandler());
        tipo = "operador";
        if (msj.numParams() < 2) {
            throw new MensajeException(msj);
        }
        puesto = msj.params[0].toUpperCase();
        nombre = msj.params[1].toUpperCase();
        capacidades = new HashMap<>();
        suplencias = new HashSet<>();

    }

    @Override
    public String toString() {
        return "IP: " + ipAdd + "; Puesto: " + puesto + "; Operador: " + nombre + "; Vers. " + version + "\n"
                + "   Capacidades: " + capacidadesToString() + "; Estado: " + txtEstado[estado] + "; Centro: " + centro;
    }

    public void aceptadaConexion(String nombreReconocido, int estado, String favEstadisticas) {
        String modo = "";
        servidor.Configuracion conf = servidor.Configuracion.getConfiguracion();
        int vmodo = modoArranque(conf);
        switch (vmodo) {
            case 0:
                modo = "ConGestor";
                break;
            case 1:
                modo = "SinGestor";
                break;
            case 2:
                modo = "ColaCero";
                break;      // este ya no puede darse
            case 3:
                modo = "SinGestorColaCero";
                break;
        }
        nombrelargo = nombreReconocido;
        enviaMensaje(CONEXION_ACEPTADA, nombreReconocido, modo, String.valueOf(estado), (conf.apagarOperadoresFantasma ? "1" : "0"), conf.nombreOficina, favEstadisticas, conf.colaCero, (conf.permitirNoIden ? "1" : "0"));
    }

    public int modoArranque(servidor.Configuracion conf) {
        //   servidor.Configuracion conf = servidor.Configuracion.getConfiguracion();
        if (conf.modoSinGestor && !conf.modoColaCero) {
            return 1;
        }
        if (conf.modoSinGestor && conf.modoColaCero) {
            return 3;
        }
        if (!conf.modoSinGestor && !conf.modoColaCero) {
            return 0;
        }
        if (!conf.modoSinGestor && conf.modoColaCero) {
            return 2;
        }
        return 0;
    }

    @Override
    public void cerrarConexion() {
        try {
            gestor.desconectarOperador(puesto);
        } catch (Exception exc) {
            servidor.ServidorMain.log.log(Level.WARNING, "Error al desconectar mesa {0}\n{1}", new Object[]{puesto, exc.getMessage()});
        }
    }

    public void ejecutaScript(String argumentos) {
        enviaMensaje(MSG_EJECUTA_SCRIPT, argumentos);
    }

    public void mensajeRechazadaMesa() {
        enviaMensaje(MESA_RECHAZADA, "");
    }

    public void mensajeRechazadoOperador() {
        enviaMensaje(OPERADOR_RECHAZADO, "");
    }

    public void reiniciar() {
        enviaMensaje(MSG_REINICIAR, "");
    }

    public void cargaInicialCapacidades(String codOperador) {
        RegistroOperadores regOp = GestorColas.getGestor().tablaOperadores.buscarCodigo(codOperador);
        String listaCapacidades = regOp.getCapacidad();
        listaCapacidades = listaCapacidades.replace(',','-');
        capacidades.clear();
        if (listaCapacidades != null) {
            String[] caps = Global.split(listaCapacidades, '-');
            for (String cap : caps) {
                DatosCapacidad dc = new DatosCapacidad(cap.toUpperCase(), true, true, false);
                capacidades.put(dc.nombre, dc);
            }
        }

        String listaSuplencias = regOp.getSuplencias();
        if (listaSuplencias != null) {
            String[] caps = Global.split(listaSuplencias, '-');
            for (String cap : caps) {
                String s = cap.trim();
                if (s.length() > 0) {
                    suplencias.add(s.toUpperCase());
                }
            }
        }

        comprobarCapacidadesPorMesa();

        String listaFavoritas = regOp.getFavoritas();
        if (listaFavoritas != null) {
            String[] caps = Global.split(listaFavoritas, '-');
            for (String cap : caps) {
                if (!cap.trim().equals("")) {
                    DatosCapacidad dc = capacidades.get(cap.toUpperCase());
                    if (dc != null) {
                        dc.Favorita = true;
                    }
                }
            }
        }
    }

    public void cargaCapacidades(String listaCapacidades) {
        capacidades.clear();
        if (listaCapacidades != null) {
            String[] caps = Global.split(listaCapacidades, '-');
            for (String cap : caps) {
                if (!cap.trim().equals("")) {
                    DatosCapacidad dc = new DatosCapacidad(cap);
                    capacidades.put(dc.nombre, dc);
                }
            }
        }
    }

    public void cargaSuplencias(String listaSuplencias) {
        suplencias.clear();
        if (listaSuplencias != null) {
            String[] caps = Global.split(listaSuplencias, '-');
            for (String cap : caps) {
                String s = cap.trim();
                if (s.length() > 0) {
                    suplencias.add(s.toUpperCase());
                }
            }
        }
    }

    public void cargaLocalizacion(String mesa) {
        TablaPuestos tp = Global.tablaPuestos;
        if (tp.hayDatos(puesto)) {
            setLocalizacion(tp.getLocalizacion(mesa));
        } else {
            setLocalizacion(" ");
        }
    }

    public void enviarTablas(boolean porReleer) {
        GestorColas gc = GestorColas.getGestor();
        if (porReleer) {
            enviaMensaje(Administrador.MSG_COMIENZO_ENVIO_COLAS, "");
        }
        gc.enviosMasivos.enviarTablaColas(this);
        gc.enviosMasivos.enviarTablaCodEstadisticos(this);
    }

    public void comprobarCapacidadesPorMesa() {
        TablaPuestos tp = Global.tablaPuestos;
        if (tp.hayDatos(puesto)) {
            String[] caps = Global.split(tp.capacidades(puesto), '-');
            if (caps.length > 0) {
                if (tp.esExclusivo(puesto)) {
                    suplencias.clear();
                    for (DatosCapacidad dc : capacidades.values()) {
                        dc.Actual = false;
                    }
                }
                for (String cap : caps) {
                    String capacidad = cap.trim().toUpperCase();
                    if (!capacidad.equals("")) {
                        if (!capacidades.containsKey(capacidad)) {
                            capacidades.put(capacidad, new DatosCapacidad(capacidad, false, true, true));
                        } else {
                            DatosCapacidad dc = capacidades.get(capacidad);
                            dc.Actual = true;
                            dc.DeMesa = true;
                        }
                    }
                }
            }
        }
    }

    public boolean tieneCapacidad(String cap) {
        if (capacidades.containsKey(cap)) {
            DatosCapacidad dc = capacidades.get(cap);
            return dc.Actual;
        } else {
            return false;
        }
    }

    public boolean tieneAlgunaCapacidadActiva(String cola0) {
        for (DatosCapacidad dc : capacidades.values()) {
            if (!dc.nombre.trim().equalsIgnoreCase("")) {
                if (!dc.nombre.trim().equalsIgnoreCase(cola0)) {
                    if (dc.Actual == true) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public boolean tieneAlgunaFavorita() {
        for (DatosCapacidad dc : capacidades.values()) {
            if (dc.Favorita && dc.Actual) {
                return true;
            }
        }
        return false;
    }

    public boolean tieneFavorita(String cap) {
        if (capacidades.containsKey(cap)) {
            DatosCapacidad dc = capacidades.get(cap);
            return dc.Favorita && dc.Actual;
        } else {
            return false;
        }
    }

    public boolean esSuplente(String cap) {
        return suplencias.contains(cap);
    }

    public Iterator<DatosCapacidad> iteradorCapacidades() {
        return capacidades.values().iterator();
    }

    public Iterator<String> iteradorSuplencias() {
        return suplencias.iterator();
    }

    public String capacidadesToString() {
        ArrayList<String> a = new ArrayList<>(50);
        for (DatosCapacidad dc : capacidades.values()) {
            if (dc.Actual) {
                String s = dc.nombre;
                if (dc.Favorita) {
                    s = "(" + s + ")";
                }
                a.add(s);
            }
        }
        Collections.sort(a);
        if (a.isEmpty()) {
            return "";
        }
        StringBuilder s = new StringBuilder(a.get(0));
        for (int i = 1; i < a.size(); i++) {
            s.append("-").append(a.get(i));
        }
        return s.toString();
    }

    public String capacidadesToString_2() {
        StringBuilder s = new StringBuilder();
        for (DatosCapacidad dc : capacidades.values()) {
            s.append(dc.toString()).append("-");
        }
        if (s.length() > 0) {
            s.setLength(s.length() - 1);
        }
        return s.toString();
    }

    public String suplenciasToString() {
        StringBuilder s = new StringBuilder();
        for (String sup : suplencias) {
            s.append(sup).append("-");
        }
        if (s.length() > 0) {
            s.setLength(s.length() - 1);
        }
        return s.toString();
    }

    public class DatosCapacidad {

        public boolean Permanente;
        public boolean Actual;
        public boolean DeMesa;
        public boolean Favorita = false;
        public String nombre;

        public DatosCapacidad(String nombre, boolean s1, boolean s2, boolean s3) {
            this.nombre = nombre;
            Permanente = s1;
            Actual = s2;
            DeMesa = s3;
        }

        public DatosCapacidad(String s) {
            int l = s.length();
            nombre = s.substring(0, l - 4);
            Permanente = s.charAt(l - 4) != '0';
            Actual = s.charAt(l - 3) != '0';
            DeMesa = s.charAt(l - 2) != '0';
            Favorita = s.charAt(l - 1) != '0';
        }

        @Override
        public String toString() {
            return nombre + (Permanente ? '1' : '0') + (Actual ? '1' : '0') + (DeMesa ? '1' : '0') + (Favorita ? '1' : '0');
        }
    }
}
