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

public class Operadores implements Iterable<Operador> {

    public ColaLibres libres;
    protected HashMap<String, Operador> lista;

    public Operadores() {
        lista = new HashMap<>();
        libres = new ColaLibres();
    }

    public int size() {
        return lista.size();
    }

    public int cuentaLibres() {
        return libres.size();
    }

    public int cuenta() {
        return lista.size();
    }

    public boolean contiene(Operador operador) {
        return lista.containsKey(operador.getPuesto());
    }

    public boolean codigoOperadorConectado(String codOperador) {
        for (Operador op : lista.values()) {
            if (op.getNombre().equals(codOperador)) {
                return true;
            }
        }
        return false;
    }

    public void remove(Operador operador) {
        libres.elimina(operador);
        lista.remove(operador.getPuesto());
    }

    @Override
    public Iterator<Operador> iterator() {
        return lista.values().iterator();
    }

    public void add(Operador operador) {
        lista.put(operador.getPuesto(), operador);
    }

    public void meterEnLibres(Operador operador) {
        libres.encola(operador);
    }

    public void sacarDeLibres(Operador operador) {
        libres.elimina(operador);
    }

    public Operador buscaLibreConCapacidad(String colaDemandada) {
        return libres.buscaLibre(colaDemandada);
    }

    public Operador buscaPorMesa(String mesa) {
        return libres.buscaPorMesa(mesa);
    }

    public Operador get(String puesto) {
        return lista.get(puesto);
    }

    public void listar() {
        if (lista.isEmpty()) {
            System.out.println(" ** No hay Operadores conectados");
            return;
        }
        System.out.println(" ** Operadores conectados : ");

        Collection<Operador> opers = lista.values();
        Operador[] ops = opers.toArray(new Operador[0]);
        Arrays.sort(ops, (Operador op1, Operador op2) -> op1.getNumPuesto() - op2.getNumPuesto());
        for (Operador op : ops) {
            System.out.println(op.toString());
        }
    }

    public Operador encuentraOperadorPorCodigo(String codigo) {
        for (Operador op : lista.values()) {
            if (op.getNombre().equals(codigo)) {
                return op;
            }
        }
        return null;
    }

    public boolean cambiarCapacidad(String op, String caps, String supls) {
        Operador operador = encuentraOperadorPorCodigo(op);
        if (operador != null) {
            operador.cargaCapacidades(caps);
            operador.cargaSuplencias(supls);
            return true;
        }
        return false;
    }

    public boolean hayOperadorConCapacidad(String cola) {
        for (Operador op : lista.values()) {
            if (op.isOperativo() && (op.tieneCapacidad(cola) || op.esSuplente(cola))) {
                return true;
            }
        }
        return false;
    }

    public int contarOperadoresAptos(String cola) {
        int res = 0;
        for (Operador op : lista.values()) {
            if (op.isOperativo() && op.tieneCapacidad(cola)) {
                res++;
            }
        }
        return res;
    }

    public void enviarCapacidades(Administrador adminis) {
        for (Operador op : lista.values()) {
            adminis.enviaMensaje(Administrador.MSG_CAMBIO_CAPACIDAD, op.getNombre(), op.capacidadesToString_2(), op.suplenciasToString());
        }
    }

    public String listaOperadorConCapacidad(String cola) {
        StringBuilder listaOpe;
        listaOpe = new StringBuilder("0|Vacio|No selecionar ");
        int contador = 1;
        for (Operador op : lista.values()) {
            if (op.isOperativo() && (op.tieneCapacidad(cola))) {
                listaOpe.append("#").append(op.getPuesto()).append("|").append(op.getNombre()).append("|").append(op.getNombreLargo());
                contador++;
                if (contador > 16) {
                    break;
                }
            }
        }
        return listaOpe.toString();
    }

    public void cargarLocalizacion() {
        for (Operador op : lista.values()) {
            op.cargaLocalizacion(op.getPuesto());
        }
    }

    public void operadorRun(String[] args) {
        int pp = args[0] == null ? 1 : 2;
        String lenguaje = "";
        if (args[pp].endsWith("VBS")) {
            lenguaje = "vbscript";
        } else if (args[pp].endsWith("JS")) {
            lenguaje = "jscript";
        } else {
            System.err.println("Solo se admiten ficheros .VBS ó .JS");
            return;
        }
        String code = servidor.utiles.Global.preparaCodigoScript(args[pp]);
        if (code == null) {
            return;
        }
        StringBuilder parametros = new StringBuilder(lenguaje);
        parametros.append('|').append(code);
        for (int i = pp + 1; i < args.length; i++) {
            parametros.append('|').append(args[i]);
        }
        if (args[0] == null) {
            ejecutaScript(parametros.toString());
        } else {
            Operador op = get(args[1]);
            op.ejecutaScript(parametros.toString());
        }
    }

    public void ejecutaScript(String argumentos) {
        for (Operador op : lista.values()) {
            op.ejecutaScript(argumentos);
        }
    }

    public void apagarOperadores(String msg) {
        Operador[] ops = new Operador[lista.size()];
        ops = lista.values().toArray(ops);
        for (Operador op : ops) {
            try {
                servidor.comunicaciones.GestorColas.getGestor().desconectarOperador(op.getPuesto());
            }catch (Exception exc) {
                exc.printStackTrace();
            }
            op.enviaMensajeUrgente(Operador.MSG_CIERRE_URGENTE, msg);
            op.setEstado(Operador.NOCONECTADO);
        }
    }

    public void apagarOperador(String puesto) {
        Operador op = get(puesto);
        if (op != null) {
            op.enviaMensajeUrgente(Operador.MSG_CIERRE_URGENTE, "ADIOS");
            op.setEstado(Operador.NOCONECTADO);
        }
        try {
            servidor.comunicaciones.GestorColas.getGestor().desconectarOperador(puesto);
        } catch (Exception exc) {
            // Aqui no queremos hacer nada
        }
    }

    public void enviaMensaje(int codigo, String mensaje) {
        for (Operador op : lista.values()) {
            op.enviaMensaje(codigo, mensaje);
        }
    }

    public void reiniciar() {
        for (Operador op : lista.values()) {
            op.reiniciar();
        }
    }

    public void enviarTablas(boolean porReleer) {
        for (Operador op : lista.values()) {
            op.enviarTablas(porReleer);
        }
    }

    public void enviaMensaje(int codigo, String texto1, String texto2) {
        enviaMensaje(codigo, texto1 + "|" + texto2);
    }
}
