/* 
* 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 java.io.*;
import java.util.*;
import java.util.regex.*;
import javax.swing.*;
import administrador.datos.*;
import administrador.utiles.*;
import java.awt.Color;
import javax.swing.table.DefaultTableModel;

public final class PanelServidor extends javax.swing.JPanel implements PanelBase {

    //<editor-fold desc="Variables">
    String nombreServidor;
    int presentesR = 0;
    int presentesU = 0;
    javax.swing.Timer timerDesconexion;
    javax.swing.Timer timerRefrescoRetraso;
    int tiempoDesconexion = 20 * 60 * 1000;  // 20 minutillos
    int tiempoRefrescoRetraso = 10 * 1000;
    java.sql.Timestamp ultimoRetraso = null;
    static final String[] textoEstados = {"Desconectado", "Conectado", "Libre", "En espera", "Trabajando", "No disponible", "??"};
    MapaOperadores mapaOperadores;
    ColeccionMesas colMesas;
    ColeccionRegistros colColas;
    Comunicaciones comu;
    TiemposColas tiempoColas;
    ListaColasFavoritas listaColas;
    FormTransmisiones recepcionForm = null;
    FormTransmisiones envioForm = null;
    FormOtrosDatos otrosDatosForm = null;
    FormInformacionTiemposAviso formInformacionAviso = null;
    int presentes;
    int ahora;
    boolean avisado = false;
    boolean activo = false;
    public boolean soyLocal = false;
    String numeroDeAdministrador;
    public String servidorSql = null;
    long marcaHoraSeleccionColas = 0;
    //  TModelOperaciones tmOp;
    TModelTiempos tmTi;
    TModelUbac tmUbac;
    FormAsignacionCapacidades formCapacidades = null;
    JTable gridVisible;
    FormGestionCitas gestionCitas = null;
    boolean windowsVista = false;
    String cadenaRangoHuecos = "";
    public String BaseDatos = "ateneo";
    public String CodigoCentro = "00000";
    public String path = "";

    //</editor-fold>
    public PanelServidor(String nombre, String Ip) {
        comu = new Comunicaciones(this);
        comu.configuraIp(Ip);
        nombreServidor = nombre;
        initComponents();
        timerDesconexion = new javax.swing.Timer(tiempoDesconexion, new java.awt.event.ActionListener() {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                tickTimerDesconexion();
            }
        });
        timerRefrescoRetraso = new javax.swing.Timer(tiempoRefrescoRetraso, new java.awt.event.ActionListener() {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                tickTimerRetraso();
            }
        });
        prepararDatos();
        listaColas = ListaColasFavoritas.instanciaUnica();
        colMesas.setFiltro(true);
        colColas.setFiltro(true);
        comu.prepararSocket();
        prepararGrids(true);
        gridVisible = gridUbac;
    }

    public void hacerLocal() {
        soyLocal = true;
        menuCerrarCola.setEnabled(true);
        menuCambiarTiempo.setEnabled(true);
        menuCambiarUmbral.setEnabled(true);
        marcaHoraSeleccionColas = System.currentTimeMillis() + 20000;
    }

    public void esWindowsVista(boolean esVista) {
        windowsVista = esVista;
    }

    public String getcadenaRangoHuecos() {
        return cadenaRangoHuecos;
    }

    public void setcadenaRangoHuecos(String cadena) {
        if (soyLocal) {
            cadenaRangoHuecos = cadena;
            if (this.gestionCitas != null) {
                this.gestionCitas.actualizarRangosenHuecos();
            }

        }
    }

    public void grabarNotas(String datos) {
        String[] sregs = datos.split("##");
        String pathNotas = Global.miPath() + "\\Notas";
        int pos = datos.indexOf("{\\rtf");
        String texto = "";
        if (pos > 0) {
            texto = datos.substring(pos);
        } else {
            texto = sregs[sregs.length - 1];
        }
        stringToFile(texto, pathNotas + "\\" + sregs[0] + "_" + sregs[1] + ".rtf");
        FormVerFichero ffi = new FormVerFichero(sregs[0] + "_" + sregs[1]);
        ffi.setVisible(true);
    }

    public void stringToFile(String text, String fileName) {
        try {
            File file = new File(fileName);
            if (!file.exists()) {
                file.createNewFile();
            }
            FileWriter fw = new FileWriter(file.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(text);
            bw.close();
            //System.out.println("Done writing to " + fileName); //For testing 
        } catch (IOException e) {
            System.out.println("Error: " + e);
            e.printStackTrace();
        }
    } //End method stringToFile

    public boolean conectado() {
        return comu.estaAbierto();
    }

    void aplicaLayout() {
    }

    void prepararDatos() {
        mapaOperadores = new MapaOperadores(this);
        colMesas = new ColeccionMesas(mapaOperadores);
        colColas = new ColeccionRegistros();
        tiempoColas = new TiemposColas(colColas);
    }

    public void setNumero(String num) {
        numeroDeAdministrador = num;
    }

    public void setCodigoCentro(String centro) {
        CodigoCentro = centro;
    }

    public void setBaseDatos(String basedatos) {
        BaseDatos = basedatos;
    }

    public void abrirGraficos() {
        if (comu.estaAbierto()) {
            String parametros = servidorSql + " " + nombreServidor + " " + BaseDatos;
            try {
                Runtime.getRuntime().exec("javaw -jar graficAteneoIV.jar " + parametros);
            } catch (Exception exc) {
            }
        }
    }

    public void intentarModoAutomatico() {
        if (comu.estaAbierto() && soyLocal && confirmarCambioModo("AUTOMATICO")) {
            comu.enviar(Comunicaciones.COD_INICIAR_MODO_AUTOMATICO, "");
        }
    }

    public void pasarModoManual() {
        if (comu.estaAbierto() && soyLocal && confirmarCambioModo("MANUAL")) {
            comu.enviar(Comunicaciones.SOLICITO_CAMBIO_AUTOMATICO, "0", String.valueOf(false));
        }
    }

    boolean confirmarCambioModo(String nuevoModo) {
        return (javax.swing.JOptionPane.showConfirmDialog(this, "Se va a cambiar el modo del Servidor ATENEO a " + nuevoModo
                + "\n¿Está seguro?", "CAMBIO MODO SERVIDOR", javax.swing.JOptionPane.YES_NO_OPTION) == javax.swing.JOptionPane.YES_OPTION);
    }

    void conexionAceptada(String msg) {
        String[] params = Global.split(msg, '|');
        setNumero(params[0]);
        servidorSql = params[1].toLowerCase();
        String ipServidor = comu.getHost().toLowerCase();
        if (servidorSql.equals("localhost") || ipServidor.startsWith(servidorSql)) {
            servidorSql = ipServidor;
        }
        if (params.length == 4) {
            setBaseDatos(params[2]);
            setCodigoCentro(params[3]);
        }
        Global.principal.activarMenus(true, soyLocal);
    }

    void mostrarConectados() {
        colMesas.setFiltro(this.ckbSoloConectados.isSelected());
        repintaGrids();
    }

    void cambiadoGrid() {
        if ((JPanel) tabPanelSuperior.getSelectedComponent() == tabColas) {
            gridVisible = gridUbac;
            lbPresentes.setVisible(false);
            lbRetraso.setVisible(false);
            lbPresentesU.setVisible(true);
        } else {
            lbPresentes.setVisible(true);
            lbRetraso.setVisible(true);
            lbPresentesU.setVisible(false);
        }
    }

    public void repintaGrids() {
        ahora = (int) (System.currentTimeMillis() / 1000);
        gridVisible.revalidate();
        gridVisible.repaint();
        gridTiempos.revalidate();
        gridTiempos.repaint();
    }

    void prepararGrids(boolean conDatos) {
        tmTi = new TModelTiempos(this);
        tmUbac = new TModelUbac(this);
        preparaGrid(gridTiempos, tmTi);
        gridUbac.setModel(tmUbac);
        if (conDatos) {
            gridTiempos.getColumnModel().getColumn(4).setCellRenderer(new renderCeldaRojaTiempos());
            gridTiempos.getColumnModel().getColumn(1).setCellRenderer(new renderCeldaGrisTiempos());
            gridUbac.getColumnModel().getColumn(4).setCellRenderer(new renderCeldaRojaUbac());
            gridUbac.getColumnModel().getColumn(1).setCellRenderer(new renderCeldaRojaCola());
            gridUbac.getColumnModel().getColumn(2).setCellRenderer(new renderCeldaRojaCola());
            gridUbac.getColumnModel().getColumn(5).setCellRenderer(new renderCeldaRojaCola());
            gridUbac.getColumnModel().getColumn(0).setMaxWidth(80);
            gridUbac.getColumnModel().getColumn(0).setPreferredWidth(80);
            gridUbac.getColumnModel().getColumn(1).setPreferredWidth(350);
        }
    }

    void preparaGrid(javax.swing.JTable grid, javax.swing.table.TableModel tm) {
        try {
            grid.setModel(tm);
            grid.getColumnModel().getColumn(0).setPreferredWidth(110);
            grid.getColumnModel().getColumn(1).setPreferredWidth(310);
            grid.getColumnModel().getColumn(0).setCellRenderer(new renderCeldaEstado());
        } catch (Exception exc) {
        }
    }

    void activarInterfaz(boolean b) {
        prepararGrids(b);
        activo = b;
        ckbSoloConectados.setEnabled(b);
        if (soyLocal) {
            btCapacidades.setEnabled(b);
            btGestionCitas.setEnabled(b);
        }
        repintaGrids();

    }

    public void mostrarSeleccionColas() {
        if (!comu.estaAbierto()) {
            return;
        }
        timerRefrescoRetraso.stop();
        FormSelectorColasVisibles scv = new FormSelectorColasVisibles(Global.principal, nombreServidor);
        scv.setSize(400, 450);
        scv.cargarDatos(colColas);
        scv.setLocationRelativeTo(null);
        scv.setVisible(true);
        colColas.setFiltro(true);
        colMesas.clear();
        repintaGrids();
        marcaHoraSeleccionColas = System.currentTimeMillis() + 20000;
        comu.enviar(Comunicaciones.COD_ENVIAR_ACCIONES, "");
        timerRefrescoRetraso.start();
    }

    boolean esOperadorConCapacidad(MapaOperadores.RegistroOperador op) {
        for (DatosCapacidad dc : op.capacidades.values()) {
            RegistroCola cola = (RegistroCola) colColas.get(dc.nombre);
            if (dc.Actual) {
                if (cola != null && !cola.estaDesconectado() || dc.nombre.equals(" ")) {
                    return true;
                }
            }
        }
        for (String s : op.suplencias) {
            RegistroCola cola = (RegistroCola) colColas.get(s);
            if (cola != null && !cola.estaDesconectado()) {
                return true;
            }
        }
        return false;
    }

    synchronized void envioAcciones(String msg) {
        RegistroMesa reg = new RegistroMesa(msg);
        MapaOperadores.RegistroOperador op = mapaOperadores.actualizaEstado(reg.codigo, reg.estado);
        if (op == null) {
            return;
        }
        if (esOperadorConCapacidad(op) || op.sinCapacidades()) {
            colMesas.add(reg);
            if (activo) {
                repintaGrids();
            }
            calcularSiAvisarII();
        }
    }

    public void enviarCambioCapacidad(String codigo, String cadenaCapacidad, String cadenaSuplencias) {
        comu.enviarCambioCapacidad(codigo, cadenaCapacidad, cadenaSuplencias);
    }

    void cambioCapacidad(String msg) {
        mapaOperadores.actualizaOperador(msg);
        calcularOperadores();
        repintaGrids();
        if (formCapacidades != null) {
            formCapacidades.refrescarGrids();
        }
    }

    void vaciarColas() {
        for (Iterator it = colColas.iteradorValores(); it.hasNext();) {
            RegistroCola reg = (RegistroCola) it.next();
            reg.actualizado = false;
        }
    }

    void registroColas(String msg) {
        if (!msg.equals("FIN_REGISTROS")) {
            RegistroCola reg = new RegistroCola(msg);
            colColas.add(reg);
            reg.actualizado = true;
            if (activo) {
                repintaGrids();
            }
        } else {
            ArrayList<RegistroCola> borrables = new ArrayList<>();
            for (Iterator it = colColas.iteradorValores(); it.hasNext();) {
                RegistroCola reg = (RegistroCola) it.next();
                if (!reg.actualizado) {
                    borrables.add(reg);
                }
            }
            for (RegistroCola r : borrables) {
                colColas.borrar(r);
            }
            tiempoColas.crearDeNuevo();
            if (soyLocal) {
                tiempoColas.cargar();
            }
        }
    }

    void resumenRetrasos(String msg) {
        presentesR = 0;
        presentesU = 0;
        timerRefrescoRetraso.stop();
        actualizaColeccionColas(msg);
        actualizarEtiquetasPresentes();
        calcularOperadores();
        repintaGrids();
        timerRefrescoRetraso.start();
        calcularSiAvisar();
    }

    void grabaRegistroOperadores(String reg) {
        mapaOperadores.graba(reg);
        if (formCapacidades != null) {
            formCapacidades.cargaInicial();
        }
    }

    void actualizaModo(String msg) {
        String[] p = Global.split(msg, '|');
        if (soyLocal && p.length > 1 && p[0].equals("Manual")) {
            String msj = "El sistema pasa a modo Manual\nCompruebe el funcionamiento de los monitores";
            if (p[1].length() > 0) {
                msj += ":\n" + p[1];
            }
            Global.MsgBox(msj);
        }
        lbModo.setText("Modo: " + p[0]);
    }

    void actualizarEtiquetasPresentes() {
        try {
            lbPresentes.setForeground(Color.BLACK);
            lbPresentesU.setForeground(Color.BLACK);
            lbPresentes.setText("Presentes: " + presentesR);
            lbPresentesU.setText("Presentes: " + presentesU);
        } catch (Exception exc) {
            exc.printStackTrace();
        }
    }

    void actualizaColeccionColas(String msg) {
        String infoCola[] = Global.split(msg, '|');
        long tmin = System.currentTimeMillis();
        boolean hayRetraso = false;
        presentesR = 0;
        for (String infoCola1 : infoCola) {
            String[] partes = Global.split(infoCola1, '=');
            RegistroCola reg = (RegistroCola) colColas.get(partes[0]);
            if (reg != null) {
                reg.setPresentes(partes[1]);
                reg.setRetraso((partes[2] == null) ? "" : partes[2]);
                reg.setTicket(partes[3]);
                reg.setHoraEstimada(partes[4]);
                reg.setHoraCalculada2(partes[5]);
                if (reg.esRenta()) {
                    presentesR += reg.getPresentes();
                    if (!reg.getRetraso().equals("")) {
                        hayRetraso = true;
                        long ts = java.sql.Timestamp.valueOf(reg.getRetraso()).getTime();
                        if (ts < tmin) {
                            tmin = ts;
                        }
                    }
                }
                presentesU = presentesU + reg.getPresentes();
            }
        }
        escribeRetraso(tmin, hayRetraso);
    }

    void escribeRetraso(long milisecs, boolean hayRetraso) {
        if (!hayRetraso) {
            lbRetraso.setForeground(Color.BLACK);
            lbRetraso.setText("Tiempo: 00:00:00");
            return;
        }
        int dif = ahora - (int) (milisecs / 1000);
        String txt = Global.segundosAsString(dif);
        if (txt.startsWith("-")) {
            lbRetraso.setText("Anticipo: " + txt);
            lbRetraso.setForeground(Color.BLUE);
        } else {
            lbRetraso.setText("Retraso: " + txt);
            lbRetraso.setForeground(Color.RED);
        }
    }

    void calcularSiAvisar() {
        if (!soyLocal || !Configuracion.instanciaUnica().alertaOperadores) {
            return;
        }
        calcularOperadores();
        if (System.currentTimeMillis() < marcaHoraSeleccionColas) {
            return;
        }
        boolean avisar = false;
        for (Iterator it = colColas.iteradorValores(); it.hasNext();) {
            RegistroCola reg = (RegistroCola) it.next();
            if (reg.getPresentes() > 0 && (reg.operadores + reg.operadoresSup) == 0) {
                avisar = true;
                break;
            }
        }
        if (!avisar) {
            avisado = false;
        } else {
            if (!avisado) {
                try {
                    java.net.InetAddress ie = java.net.InetAddress.getLocalHost();
                    String nombreMaquina = ie.getHostName();
                    if (!windowsVista) {
                        Runtime.getRuntime().exec("NET SEND " + nombreMaquina + " Hay colas con pendientes sin operador válido");
                    } else {
                        File f = new File("C:\\windows\\System32\\msg.exe");
                        if (f.exists()) {
                            Runtime.getRuntime().exec("C:\\windows\\System32\\msg.exe * Hay colas con pendientes sin operador válido");
                        } else {
                            Runtime.getRuntime().exec("C:\\windows\\sysnative\\msg.exe * Hay colas con pendientes sin operador válido");
                        }
                    }
                    avisado = true;
                    marcaHoraSeleccionColas = System.currentTimeMillis() + 300000;
                } catch (Exception exc) {
                }
            }
        }
    }

    void calcularSiAvisarII() {
        if (!soyLocal || !Configuracion.instanciaUnica().alertaOperadores) {
            return;
        }
        calcularOperadores();
        if (System.currentTimeMillis() < marcaHoraSeleccionColas) {
            return;
        }
        for (Iterator it = colColas.iteradorValores(); it.hasNext();) {
            RegistroCola reg = (RegistroCola) it.next();
            if (reg.getPresentes() > 0 && reg.operadores == 0) {
                marcaHoraSeleccionColas = System.currentTimeMillis() + 30000;
                return;
            }
        }
    }

//    void mostrarMensajesEnElVisor() {
//        for (int i = 0; i < colMesas.size(); i++) {
//            RegistroMesa reg = (RegistroMesa) colMesas.getRegistro(i);
//            String s = reg.puesto + " - ";
//            s += reg.horaUltimoMovimiento + " - ";
//            s += reg.tiempoDescanso + " - ";
//            s += reg.tiempoLibre + " - ";
//            s += reg.tiempoOcupado + " - ";
//            s += reg.codigo + " - ";
//            s += reg.estado + " - ";
//            s += reg.numeroCitas;
//        }
//    }
//
    @Override
    public void recibirFoco() {
        if (timerDesconexion.isRunning()) {
            timerDesconexion.stop();
        }
    }

    @Override
    public void perderFoco() {
        if (comu.estaAbierto()) {
            timerDesconexion.start();
        }
    }

    void seleccionarFilaGrid(JTable grid, java.awt.Point p) {
        int r = grid.rowAtPoint(p);
        if (r != -1) {
            //  gridOperaciones.changeSelection(r, 0, false, false);
            gridTiempos.changeSelection(r, 0, false, false);
        }
    }

    void cambiarOrdenGridTiempos(int columna) {
        colMesas.ordenar(columna);
        repintaGrids();
    }

    void seleccionarFilaGridUbac(JTable grid, java.awt.Point p) {
        int r = grid.rowAtPoint(p);
        if (r != -1) {
            gridUbac.changeSelection(r, 0, false, false);
        }
    }

    void mostrarMenuPopupGrid(JTable grid, int x, int y) {
        if (grid.getSelectedRowCount() > 0) {
            popupMenuGrid.show(grid, x, y);
        }
    }

    void mostrarMenuSuperior(JTable grid, int x, int y) {
        if (grid.getSelectedRowCount() < 1) {
            return;
        }
        int idx = grid.getSelectedRow();
        Boolean b = (Boolean) grid.getValueAt(idx, 6);
        if (b) {
            menuCerrarCola.setText("Abrir cola");
        } else {
            menuCerrarCola.setText("Cerrar cola");
        }
        popupMenuSuperior.show(grid, x, y);
    }

    public void calcularOperadores() {
        this.timerRefrescoRetraso.stop();
        int numColas = colColas.size();
        int numConectados = colMesas.size();
        for (int i = 0; i < numColas; i++) {
            int ops = 0;
            int sup = 0;
            RegistroCola cola = (RegistroCola) colColas.getRegistro(i);
            for (int j = 0; j < numConectados; j++) {
                RegistroMesa regMe = (RegistroMesa) colMesas.getRegistro(j);
                MapaOperadores.RegistroOperador regOp = mapaOperadores.get(regMe.codigo);
                if (!regOp.estado.equals("0") && !regOp.estado.equals("5")) {
                    if (regOp.tieneCapacidad(cola.getId())) {
                        ops++;
                    }
                    if (regOp.esSuplente(cola.getId())) {
                        sup++;
                    }
                }
            }
            cola.operadores = ops;
            cola.operadoresSup = sup;
        }
        this.timerRefrescoRetraso.start();
    }

    void MostrarCapacidades() {
        int f = this.gridTiempos.getSelectedRow();
        if (f == -1) {
            return;
        }
        String nombre = (String) gridTiempos.getValueAt(f, 1);
        RegistroMesa reg = (RegistroMesa) colMesas.getRegistro(f);
        String texto;
        texto = "Capacidades del Operador: " + nombre + "\n\n" + "Presentes      Cola" + "\n";
        texto += "------------------------------------------------------------------------------\n";
        String codigo = reg.codigo;
        ArrayList capac = mapaOperadores.getCapacidades(codigo);
        for (Object capac1 : capac) {
            RegistroCola cola = (RegistroCola) colColas.get((String) capac1);
            if (cola != null) {
                String linea = Global.formatea(cola.getPresentes(), cola.getDescripcion());
                texto += linea + "\n";
            }
        }
        String[] supls = mapaOperadores.getSuplencias(codigo);
        if (supls != null && supls.length > 0) {
            for (String supl : supls) {
                RegistroCola cola = (RegistroCola) colColas.get(supl);
                if (cola != null) {
                    String linea = Global.formatea(cola.getPresentes(), cola.getDescripcion() + "  (Supl.");
                    if (cola.getUmbralSuplencia() > cola.operadores) {
                        linea = linea + " ACTIVA";
                    }
                    texto += linea + ")" + "\n";
                }
            }
        }
        Global.MsgBox(texto);
    }

    void mostrarOperadoresPorCola() {
        int r = gridUbac.getSelectedRow();
        StringBuilder texto = new StringBuilder("Operando en '").append((String) gridUbac.getValueAt(r, 1)).append("':\n");
        String codigoCola = (String) gridUbac.getValueAt(r, 0);
        int numConectados = colMesas.size();
        StringBuilder operando = new StringBuilder();
        for (int i = 0; i < numConectados; i++) {
            RegistroMesa reg = (RegistroMesa) colMesas.getRegistro(i);
            if (!"05".contains(reg.estado)) {
                ArrayList capac = mapaOperadores.getCapacidades(reg.codigo);
                if (capac.contains(codigoCola)) {
                    operando.append("  ").append(mapaOperadores.getNombre(reg.codigo)).append("\n");
                }
            }
        }
        if (operando.length() == 0) {
            operando.append("  ---\n");
        }
        texto.append(operando);
        StringBuilder suplentes = new StringBuilder();
        for (int i = 0; i < numConectados; i++) {
            RegistroMesa reg = (RegistroMesa) colMesas.getRegistro(i);
            if (!"05".contains(reg.estado)) {
                MapaOperadores.RegistroOperador regOp = mapaOperadores.get(reg.codigo);
                if (regOp.esSuplente(codigoCola)) {
                    suplentes.append("  ").append(regOp.nombre).append("\n");
                }
            }
        }
        if (suplentes.length() > 0) {
            texto.append("Suplentes: \n").append(suplentes);
        }
        Global.MsgBox(texto.toString());
    }

    void mostrarGestionCapacidades() {
        if (soyLocal) {
            formCapacidades = new FormAsignacionCapacidades(this);
            formCapacidades.setSize(600, 400);
            formCapacidades.setLocationRelativeTo(this);
            formCapacidades.setVisible(true);
            formCapacidades.dispose();
            formCapacidades = null;
            colMesas.clear();
            comu.enviar(Comunicaciones.COD_ENVIAR_ACCIONES, "");
        }
    }

    public void enviarAltaOperador(String codigo, String nombre, String centro) {
        comu.enviar(Comunicaciones.COD_NUEVO_OPERADOR, codigo, nombre, centro);
    }

    void MostrarFichaInformacion(RegistroCandidatos[] regs) {
        FormInformacionTiket formInformacionT = new FormInformacionTiket(comu);
        if (Configuracion.instanciaUnica().scriptsCandidato.size() > 0) {
            formInformacionT.setSize(560, 384);
        } else {
            formInformacionT.setSize(560, 364);
        }
        formInformacionT.setLocationRelativeTo(this);
        formInformacionT.copiardatos(regs);
        formInformacionT.Rellenardatos(0);
        formInformacionT.setVisible(true);
    }

    public void cerrarTodasLasColas() {
        if (!soyLocal || !comu.estaAbierto()) {
            return;
        }
        if (JOptionPane.showConfirmDialog(this, "Se van a cerrar TODAS las colas, excepto las de CITA PREVIA"
                + "\nNo se podrán emitir mas tiques para estos servicios.\n  ¿ Está COMPLETAMENTE seguro ?",
                "CIERRE DE COLAS", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {

            for (int i = 0; i < colColas.size(); i++) {
                RegistroCola cola = (RegistroCola) colColas.getRegistro(i);
                if (!cola.esCitaPrevia()) {
                    comu.enviar(Comunicaciones.COD_CERRAR_COLA, cola.getId(), "si", " ");
                }
            }
        }
    }

    public void abrirTodasLasColas() {
        if (!soyLocal || !comu.estaAbierto()) {
            return;
        }
        if (JOptionPane.showConfirmDialog(this, "Se van a abrir TODAS las colas"
                + "\nSe volverán a emitir tiques para estos servicios.\n  ¿ Está COMPLETAMENTE seguro ?",
                "APERTURA DE COLAS", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {

            for (int i = 0; i < colColas.size(); i++) {
                RegistroCola cola = (RegistroCola) colColas.getRegistro(i);
                if (!cola.esCitaPrevia()) {
                    comu.enviar(Comunicaciones.COD_CERRAR_COLA, cola.getId(), "no", " ");
                }
            }
        }
    }

    void cambiarEstadoCola() {
        int idx = gridUbac.getSelectedRow();
        RegistroCola cola = ((TModelUbac) gridUbac.getModel()).colaSeleccionada(idx);
        if (cola.estaCerrada()) {
            comu.enviar(Comunicaciones.COD_CERRAR_COLA, cola.getId(), "no", " ");
        } else {
            confirmarCierreCola(cola);
        }
    }

    void cambiarUmbralSutitutos() {
        int idx = gridUbac.getSelectedRow();
        RegistroCola rCola = ((TModelUbac) gridUbac.getModel()).colaSeleccionada(idx);
        String valor = String.valueOf(rCola.getUmbralSuplencia());
        String nValor = JOptionPane.showInputDialog(this, "Introduzca numero minimo de operadores para activar SUSTITUCIONES, para esta cola", valor);
        if (nValor == null) {
            return;
        }
        if (!valor.equals(nValor)) {
            int nuevoValor;
            try {
                nuevoValor = Integer.parseInt(nValor);
                rCola.setUmbralSuplencia(nuevoValor);
                gridUbac.repaint();
                comu.enviar(Comunicaciones.COD_MODIFICAR_UMBRAL_SUSTITUTOS, rCola.getId(), "" + nuevoValor);
            } catch (Exception exc) {
                JOptionPane.showMessageDialog(this, "El valor introducido no es válido");
            }
        }
    }

    void cambiarTiempoCola() {
        int idx = gridUbac.getSelectedRow();
        RegistroCola rCola = ((TModelUbac) gridUbac.getModel()).colaSeleccionada(idx);
        String cola = rCola.getId();
        String valor = String.valueOf(tiempoColas.get(cola) / 60);
        String nValor = JOptionPane.showInputDialog(this, "Introduzca tiempo en minutos para mostrar alerta de retraso para esta cola", valor);
        if (nValor == null) {
            return;
        }
        if (!valor.equals(nValor)) {
            int nuevoTiempo;
            try {
                nuevoTiempo = Integer.parseInt(nValor);
                tiempoColas.set(cola, nuevoTiempo * 60);
                gridUbac.repaint();
            } catch (Exception exc) {
                JOptionPane.showMessageDialog(this, "El valor introducido no es válido");
            }
        }
    }

    void confirmarCierreCola(RegistroCola cola) {
        DlgCierreCola dlg = new DlgCierreCola(Global.principal, cola.getDescripcion());
        dlg.setVisible(true);
        if (dlg.confirmado) {
            comu.enviar(Comunicaciones.COD_CERRAR_COLA, cola.getId(), "si", dlg.texto);
        }
    }

    public void cargarListaHuecos(String msg) {
        String[] p = Global.split(msg, '|');
        if (gestionCitas != null) {
            gestionCitas.incorporarCitas(p[0], p[1], p[2]);
        }
    }

    void cerrarConexion() {
        comu.cerrar();
        timerRefrescoRetraso.stop();
        prepararDatos();
        activarInterfaz(false);
    }

    void tickTimerDesconexion() {
        cerrarConexion();
    }

    void tickTimerRetraso() {
        calcularSiAvisar();
        repintaGrids();
    }

    void pulsadoConectar() {
        if (btConectar.getText().equals("Conectar")) {
            prepararDatos();
            if (!comu.estaAbierto()) {
                if (!comu.abrir()) {
                    if (soyLocal && Configuracion.instanciaUnica().usandoUDP) {
                        Global.MsgBox("No se localiza al servidor " + Configuracion.instanciaUnica().nombreServidor);
                    } else {
                        Global.MsgBox("No se pudo abrir el socket con " + comu.Ip);
                    }
                    return;
                }
                conectar();
            }
            btConectar.setText("Desconectar");
        } else {
            desconectar();
        }
    }

    void conectar() {
        if (!Global.principal.iconosCargados) {
            Global.principal.cargarIconos();
        }
        String nombre = Global.miNombre();
        comu.enviarCodigoConexion(nombre);
        timerRefrescoRetraso.start();
    }

    void desconectar() {
        btConectar.setText("Conectar");
        cerrarConexion();
        Global.principal.activarMenus(false, false);
    }

    void errorEnSocket(String msg) {
        if (Global.principal.panelSeleccionado == this && msg.startsWith("Connection reset")) {
            JOptionPane.showMessageDialog(null, "Se ha perdido la conexión con el servidor");
        }
        cerrarConexion();
        btConectar.setText("Conectar");
        lbPresentes.setForeground(Color.RED);
        lbPresentesU.setForeground(Color.RED);
        lbPresentes.setText("No Conectado");
        lbPresentesU.setText("No Conectado");
    }

    void enviarMensajeALaMesa() {
        int f = gridTiempos.getSelectedRow();
        if (f == -1) {
            return;
        }
        String mesa = (String) gridTiempos.getValueAt(f, 2);
        enviarMensaje(mesa);
    }

    void enviarMensajeATodosOperadores() {
        enviarMensaje("operadores");
    }

    void enviarMensajeAGestores() {
        enviarMensaje("gestores");
    }

    void enviarMensajeAAdministradores() {
        if (!comu.estaAbierto()) {
            return;
        }
        comu.enviar(Comunicaciones.COD_ENVIAR_LISTA_ADMINISTRADORES, numeroDeAdministrador);
    }

    void pedirficheroPresentes() {
        if (!comu.estaAbierto()) {
            return;
        }
        comu.enviar(Comunicaciones.COD_ENVIO_FICHERO_PRESENTES, " ");
    }

    void abrirMensajeAAdministradores(String msg) {
        String[] admin = Global.split(msg, '·');
        if (admin.length < 1) {
            JOptionPane.showMessageDialog(null, "No hay administradores que puedan recibir mensajes");
            return;
        }
        FormMensajeAdministradores formAdminis = new FormMensajeAdministradores(Global.principal, admin);
        formAdminis.setVisible(true);
        if (formAdminis.enviar) {
            String retorno;
            if (formAdminis.marcados.size() > 1) {
                retorno = "noretorno";
            } else {
                retorno = numeroDeAdministrador;
            }
            for (String destinatario : formAdminis.marcados) {
                comu.enviar(Comunicaciones.COD_ENVIO_MENSAJE_PARA_ADMINISTRADORES, destinatario, retorno, formAdminis.mensaje, Global.miNombre());
            }
        }
        formAdminis.dispose();
    }

    void abrirFicheroPresentes(String msg) {
        FormPresentes prese = new FormPresentes(msg);
        prese.setVisible(true);
    }

    void abrirFicheroNotificaciones(String msg) {
        if (msg.length() < 10) {
            JOptionPane.showMessageDialog(null, "No hay datos");
            return;
        }
        msg = msg.replaceAll("\\|", "\t");
        msg = msg.replaceAll("\\/", ".");
        msg = msg.replaceAll("#", "\n");
        ExportaAHojaExcell(msg);
    }

    public void ExportaAHojaExcell(String msj) {
        String message = crearFicheroXLS(msj);
        try {
            Runtime.getRuntime().exec("rundll32 shell32.dll,ShellExec_RunDLL \"" + message + "\"");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public String crearFicheroXLS(String msj) {
        try {
            File temp = File.createTempFile("Presentes", ".XLS");
            PrintWriter out = new PrintWriter(new FileWriter(temp));
            StringBuilder sb = new StringBuilder();
            sb.append("Orden" + "\t" + " Cola " + "\t" + "Numero" + "\t" + " Nif " + "\t" + "Nombre" + "\t" + " Hora " + "\n").append(msj);
            out.println(sb.toString());
            out.close();
            return temp.getAbsolutePath();
        } catch (IOException e) {
            return null;
        }
    }

    void enviarMensaje(String destino) {
        if (!comu.estaAbierto()) {
            return;
        }
        DlgMensaje dlg = new DlgMensaje(Global.principal);
        if (destino.equals("gestores")) {
            dlg.setTitle("Mensaje a los Gestores");
        } else if (destino.equals("operadores")) {
            dlg.setTitle("Mensaje a los TODOS los operadores");
        } else {
            dlg.setTitle("Mensaje a la mesa " + destino);
        }
        dlg.setSize(415, 200);
        dlg.setLocationRelativeTo(this);
        dlg.setVisible(true);
        if (dlg.enviar) {
            comu.enviarMensaje("administrador" + numeroDeAdministrador, destino, dlg.getMensaje());
        }
        dlg.dispose();
    }

    void mensajeDeMesa(String msg) {
        String[] a = Global.split(msg, '|');
        if (!a[0].startsWith("administrador") && (!soyLocal || !Configuracion.instanciaUnica().recibirMensajes)) {
            return;
        }
        String texto = a[2].replaceAll("#", "\n") + "\n";
        String titulo = "";
        if (a[0].equals("servidor")) {
            titulo = "ATENCIÓN: MENSAJE DEL SERVIDOR";
        } else if (a[0].equalsIgnoreCase("autoServicio")) {
            if (!Configuracion.instanciaUnica().recibirMensajesAutoservicio) {
                return;
            }
            titulo = "AVISO DESDE EL AUTOSERVICIO";
        } else if (a[0].startsWith("gestor")) {
            titulo = "Mensaje desde el gestor " + a[1];
        } else if (a[0].startsWith("administrador")) {
            titulo = "Mensaje de Administrador ";
            texto = "Origen: " + a[1] + "\n\n" + texto;
        } else {
            MapaOperadores.RegistroOperador op = mapaOperadores.get(a[1]);
            if (op == null || !esOperadorConCapacidad(op)) {
                return;
            }
            String nombre = mapaOperadores.getNombre(a[1]);
            titulo = "Mensaje desde la mesa " + a[0];
            texto = "-- Mensaje de " + nombre + " --\n" + texto;
        }
        Global.principal.hacerVisible();
        java.awt.Toolkit.getDefaultToolkit().beep();
        JOptionPane.showMessageDialog(null, texto, titulo, JOptionPane.PLAIN_MESSAGE);
        if (!a[0].equals("administradornoretorno") && !a[0].equals("servidor")) {
            comu.confirmarLecturaMensaje(a[0]);
        }
    }

    String arreglaTicket(String ticket) {
        try {
            Pattern regexp = Pattern.compile("([A-Z]*)[\\W]*([0-9]*)");
            Matcher match = regexp.matcher(ticket);
            if (match.matches()) {
                return match.group(1) + "-" + match.group(2);
            }
        } catch (Exception exc) {
        }
        return ticket;
    }

    public void pedirTicket() {
        try {
            String dir = Global.miPath() + "\\Notas";
            File saveDir = new File(dir);
            if (!saveDir.exists()) {
                saveDir.mkdirs();
            }
            for (File file : saveDir.listFiles()) {
                if (!file.isDirectory()) {
                    file.delete();
                }
            }
            if (!comu.estaAbierto()) {
                return;
            }
            String ticket = JOptionPane.showInputDialog("Introduzca Identificación fiscal / ticket del que se solicitarán datos al servidor");
            if (ticket != null) {
                ticket = ticket.trim().toUpperCase();
                if (ticket.length() < 8) {
                    ticket = arreglaTicket(ticket);
                }
                if (ticket.length() > 0) {
                    comu.pedirTicket(ticket);
                }
            }
        } catch (Exception ex) {
        }
    }

    public void pedirListaTiempos() {
        if (!comu.estaAbierto()) {
            return;
        }
        DefaultTableModel modelo = new DefaultTableModel() {

            @Override
            public boolean isCellEditable(int row, int col) {
                return false;
            }
        };
        modelo.addColumn(" Cola ");
        modelo.addColumn(" Descripcion ");
        modelo.addColumn("<html>Tiempo<BR>(minutos)</html>");

        for (int i = 0; i < colColas.size(); i++) {
            RegistroCola cola = (RegistroCola) colColas.getRegistro(i);
            Object[] datosFila = new Object[3];
            datosFila[0] = cola.getId();
            datosFila[1] = cola.getDescripcion();
            datosFila[2] = String.valueOf(tiempoColas.get(cola.getId()) / 60);
            modelo.addRow(datosFila);
        }
        formInformacionAviso = new FormInformacionTiemposAviso();
        formInformacionAviso.nuevoModelo(modelo);
        formInformacionAviso.setSize(500, 480);
        formInformacionAviso.setLocationRelativeTo(this);
        formInformacionAviso.setVisible(true);
    }

    public void mostrarContadorCitas() {
        if (!comu.estaAbierto()) {
            return;
        }
        int numTickets = 0;
        for (Iterator it = colColas.iteradorValores(); it.hasNext();) {
            RegistroCola rc = (RegistroCola) it.next();
            numTickets += rc.getUltimoTicket();
        }
        int numTratados = 0;
        for (Iterator it = colMesas.iteradorValores(); it.hasNext();) {
            RegistroMesa rm = (RegistroMesa) it.next();
            numTratados += rm.numeroCitas;
        }
        String msj = "<html><U>Resumen de citas tratadas</U><BR><BR>"
                + "Tiques emitidos:&nbsp;&nbsp;&nbsp;" + numTickets + "<BR>"
                + "Citas atendidas:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + numTratados;
        String titulo = "";
        Global.MsgBox(msj, titulo);
    }

    public void pedirHistoricoTickets() {
        if (!comu.estaAbierto()) {
            return;
        }
        try {
            String dir = Global.miPath() + "\\Notas";
            File saveDir = new File(dir);
            if (!saveDir.exists()) {
                saveDir.mkdirs();
            }
            for (File file : saveDir.listFiles()) {
                if (!file.isDirectory()) {
                    file.delete();
                }
            }

            String nif = JOptionPane.showInputDialog("Introduzca la Identificación fiscal del que se solicitarán datos al servidor");
            if (nif == null) {
                return;
            }
            nif = nif.trim().toUpperCase();
            comu.pedirHistoricoTicket(nif);
        } catch (Exception ex) {
        }
    }
    File fichCerti = null;

    public void comienzaEnvioCertificado() {
    }

    public void enviarCertificado() {
        try {
            FileInputStream fis = new FileInputStream(fichCerti);
            comu.enviar(fis);
            fis.close();
        } catch (Exception exc) {
            // TODO CUIDADO CON ESTA EXCEPCION. PUEDE DEJAR COLGADO AL SERVIDOR...
        }

    }

    public void cerrarGestionCitas() {
        gestionCitas = null;
    }

    void mostrarGestioncitas() {
        if (!comu.estaAbierto()) {
            return;
        }

        if (this.gestionCitas == null) {
            gestionCitas = new FormGestionCitas(this);
            gestionCitas.setVisible(true);
        } else {
            gestionCitas.setVisible(true);
            gestionCitas.requestFocusInWindow();
        }
    }

    void mostrarDatosTicket(String datos) {
        if (datos.equals("TIQUE NO ENCONTRADO")) {
            Global.MsgBox("La Identificación /tique solicitado no está registrado en el servidor");
            return;
        }
        String[] sregs = datos.split("##");
        RegistroCandidatos[] regs = new RegistroCandidatos[sregs.length];
        for (int i = 0; i < sregs.length; i++) {
            regs[i] = new RegistroCandidatos(sregs[i]);
        }
        MostrarFichaInformacion(regs);
    }

    void fichaRecibidas() {
        if (comu.estaAbierto()) {
            if (servidorSql == null) {
                return;
            }
            if (recepcionForm == null) {
                recepcionForm = new FormTransmisiones(this, 2);
            }
            recepcionForm.setLocationRelativeTo(this);
            recepcionForm.setVisible(true);
        }
    }

    void fichaEnviadas() {
        if (comu.estaAbierto()) {
            if (servidorSql == null) {
                return;
            }
            if (envioForm == null) {
                envioForm = new FormTransmisiones(this, 3);
            }
            envioForm.setLocationRelativeTo(this);
            envioForm.setVisible(true);
        }
    }

    void fichaOtrosDatos() {
        if (comu.estaAbierto()) {
            if (servidorSql == null) {
                return;
            }
            if (otrosDatosForm == null) {
                otrosDatosForm = new FormOtrosDatos(this, 4);
            }
            otrosDatosForm.setLocationRelativeTo(this);
            otrosDatosForm.setVisible(true);
        }
    }

    public void cerradaVentana(int cual) {
        if (cual == 4) {
            otrosDatosForm = null;
            return;
        }
        if (cual == 3) {
            envioForm = null;
        } else {
            recepcionForm = null;
        }
    }

    public String pedirPresentes(String cola) {
        for (Iterator it = colColas.iteradorValores(); it.hasNext();) {
            RegistroCola reg = (RegistroCola) it.next();
            if (reg.getId().equalsIgnoreCase(cola)) {
                if (reg.getPresentes() == 0) {
                    return "0";
                }
                int p = reg.getPresentes();
                String hora = reg.getHoraCalculada2();
                String[] horaPart = Global.split(hora, ' ');
                return p + "  Ultimo presente: " + horaPart[1].substring(0, 5);
            }
        }
        return "";
    }

    public java.util.Date pedirHoraValida(String cola) {
        for (Iterator it = colColas.iteradorValores(); it.hasNext();) {
            RegistroCola reg = (RegistroCola) it.next();
            if (reg.getId().equalsIgnoreCase(cola)) {
                if (reg.getPresentes() == 0) {
                    return null;
                }
                String hora = reg.getHoraCalculada2();
                return Fecha.convertirHora(hora);
            }
        }
        return null;
    }

    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        popupMenuGrid = new javax.swing.JPopupMenu();
        menuMensaje = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JSeparator();
        menuCapacidad = new javax.swing.JMenuItem();
        popupMenuSuperior = new javax.swing.JPopupMenu();
        menuMostrarOperadores = new javax.swing.JMenuItem();
        menuCerrarCola = new javax.swing.JMenuItem();
        menuCambiarTiempo = new javax.swing.JMenuItem();
        menuCambiarUmbral = new javax.swing.JMenuItem();
        panelSuperior = new javax.swing.JPanel();
        btConectar = new javax.swing.JButton();
        ckbSoloConectados = new javax.swing.JCheckBox();
        lbPresentes = new javax.swing.JLabel();
        lbRetraso = new javax.swing.JLabel();
        lbPresentesU = new javax.swing.JLabel();
        lbModo = new javax.swing.JLabel();
        btCapacidades = new javax.swing.JButton();
        btColasFavoritas = new javax.swing.JButton();
        btGestionCitas = new javax.swing.JButton();
        panelCentral = new javax.swing.JPanel();
        jSplitPane1 = new javax.swing.JSplitPane();
        tabPanelSuperior = new javax.swing.JTabbedPane();
        tabColas = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        gridUbac = new javax.swing.JTable();
        scroll2 = new javax.swing.JScrollPane();
        gridTiempos = new javax.swing.grid.JGrid();

        menuMensaje.setText("Enviar mensaje a la mesa");
        menuMensaje.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuMensajeActionPerformed(evt);
            }
        });
        popupMenuGrid.add(menuMensaje);
        popupMenuGrid.add(jSeparator1);

        menuCapacidad.setText("Capacidad Operador");
        menuCapacidad.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                MostrarCapacidad(evt);
            }
        });
        popupMenuGrid.add(menuCapacidad);

        menuMostrarOperadores.setText("Mostrar operadores");
        menuMostrarOperadores.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuMostrarOperadoresActionPerformed(evt);
            }
        });
        popupMenuSuperior.add(menuMostrarOperadores);

        menuCerrarCola.setText("Cerrar cola");
        menuCerrarCola.setEnabled(false);
        menuCerrarCola.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuCerrarColaActionPerformed(evt);
            }
        });
        popupMenuSuperior.add(menuCerrarCola);

        menuCambiarTiempo.setText("Modificar tiempo de alerta");
        menuCambiarTiempo.setEnabled(false);
        menuCambiarTiempo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuCambiarTiempoActionPerformed(evt);
            }
        });
        popupMenuSuperior.add(menuCambiarTiempo);

        menuCambiarUmbral.setText("Cambiar Umbral Operadores");
        menuCambiarUmbral.setEnabled(false);
        menuCambiarUmbral.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuCambiarUmbralActionPerformed(evt);
            }
        });
        popupMenuSuperior.add(menuCambiarUmbral);

        setLayout(new java.awt.BorderLayout());

        panelSuperior.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        panelSuperior.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 10, 4));

        btConectar.setText("Conectar");
        btConectar.setIconTextGap(2);
        btConectar.setMargin(new java.awt.Insets(2, 12, 2, 12));
        btConectar.setMaximumSize(new java.awt.Dimension(85, 28));
        btConectar.setMinimumSize(new java.awt.Dimension(85, 28));
        btConectar.setPreferredSize(new java.awt.Dimension(105, 28));
        btConectar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btConectarActionPerformed(evt);
            }
        });
        panelSuperior.add(btConectar);

        ckbSoloConectados.setSelected(true);
        ckbSoloConectados.setText("Mostrar sólo activos");
        ckbSoloConectados.setEnabled(false);
        ckbSoloConectados.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ckbSoloConectadosActionPerformed(evt);
            }
        });
        panelSuperior.add(ckbSoloConectados);

        lbPresentes.setText("No Conectado");
        panelSuperior.add(lbPresentes);

        lbRetraso.setText("Retraso");
        panelSuperior.add(lbRetraso);

        lbPresentesU.setForeground(new java.awt.Color(51, 51, 51));
        lbPresentesU.setText("No Conectado");
        panelSuperior.add(lbPresentesU);

        lbModo.setText("Modo ????");
        panelSuperior.add(lbModo);

        btCapacidades.setText("Gestion Capacidades");
        btCapacidades.setEnabled(false);
        btCapacidades.setMargin(new java.awt.Insets(2, 4, 2, 4));
        btCapacidades.setPreferredSize(new java.awt.Dimension(125, 23));
        btCapacidades.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btCapacidadesActionPerformed(evt);
            }
        });
        panelSuperior.add(btCapacidades);

        btColasFavoritas.setText("Colas Favoritas");
        btColasFavoritas.setMargin(new java.awt.Insets(2, 4, 2, 4));
        btColasFavoritas.setPreferredSize(new java.awt.Dimension(125, 23));
        btColasFavoritas.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btColasFavoritasActionPerformed(evt);
            }
        });
        panelSuperior.add(btColasFavoritas);

        btGestionCitas.setText("Gestión Citas");
        btGestionCitas.setEnabled(false);
        btGestionCitas.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btGestionCitasActionPerformed(evt);
            }
        });
        panelSuperior.add(btGestionCitas);

        add(panelSuperior, java.awt.BorderLayout.NORTH);

        panelCentral.setLayout(new java.awt.BorderLayout());

        jSplitPane1.setDividerSize(3);
        jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        jSplitPane1.setResizeWeight(0.5);

        tabPanelSuperior.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                tabPanelSuperiorStateChanged(evt);
            }
        });

        tabColas.setLayout(new java.awt.BorderLayout());

        gridUbac.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String [] {
                "Title 1", "Title 2", "Title 3", "Title 4"
            }
        ));
        gridUbac.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                gridUbacMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                gridUbacMouseReleased(evt);
            }
        });
        jScrollPane1.setViewportView(gridUbac);

        tabColas.add(jScrollPane1, java.awt.BorderLayout.CENTER);

        tabPanelSuperior.addTab("UBAC", tabColas);

        jSplitPane1.setLeftComponent(tabPanelSuperior);

        gridTiempos.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        gridTiempos.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String [] {
                "Title 1", "Title 2", "Title 3", "Title 4"
            }
        ));
        gridTiempos.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
        gridTiempos.setCabeceraPulsable(true);
        gridTiempos.addCabeceraPulsadaListener(new javax.swing.grid.CabeceraPulsadaListener() {
            public void cabeceraPulsada(javax.swing.grid.CeldaPulsadaEvent evt) {
                gridTiemposCabeceraPulsada(evt);
            }
        });
        gridTiempos.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                gridTiemposMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                gridTiemposMouseReleased(evt);
            }
        });
        scroll2.setViewportView(gridTiempos);

        jSplitPane1.setRightComponent(scroll2);

        panelCentral.add(jSplitPane1, java.awt.BorderLayout.CENTER);

        add(panelCentral, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents
    private void btColasFavoritasActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btColasFavoritasActionPerformed
        mostrarSeleccionColas();
    }//GEN-LAST:event_btColasFavoritasActionPerformed

    private void gridTiemposCabeceraPulsada(javax.swing.grid.CeldaPulsadaEvent evt) {//GEN-FIRST:event_gridTiemposCabeceraPulsada
        cambiarOrdenGridTiempos(evt.getColumna());
    }//GEN-LAST:event_gridTiemposCabeceraPulsada

    private void menuCambiarTiempoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuCambiarTiempoActionPerformed
        cambiarTiempoCola();
    }//GEN-LAST:event_menuCambiarTiempoActionPerformed

    private void gridUbacMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_gridUbacMousePressed
        seleccionarFilaGridUbac(gridUbac, evt.getPoint());
    }//GEN-LAST:event_gridUbacMousePressed

    private void menuCerrarColaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuCerrarColaActionPerformed
        cambiarEstadoCola();
    }//GEN-LAST:event_menuCerrarColaActionPerformed

    private void gridUbacMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_gridUbacMouseReleased
        if (evt.getButton() == java.awt.event.MouseEvent.BUTTON3) {
            mostrarMenuSuperior(gridUbac, evt.getPoint().x, evt.getPoint().y);
        }
    }//GEN-LAST:event_gridUbacMouseReleased

    private void menuMostrarOperadoresActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuMostrarOperadoresActionPerformed
        mostrarOperadoresPorCola();
    }//GEN-LAST:event_menuMostrarOperadoresActionPerformed

    private void MostrarCapacidad(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_MostrarCapacidad
        MostrarCapacidades();
    }//GEN-LAST:event_MostrarCapacidad

   private void btCapacidadesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btCapacidadesActionPerformed
       mostrarGestionCapacidades();
   }//GEN-LAST:event_btCapacidadesActionPerformed

   private void tabPanelSuperiorStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabPanelSuperiorStateChanged
       cambiadoGrid();
   }//GEN-LAST:event_tabPanelSuperiorStateChanged

   private void gridTiemposMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_gridTiemposMousePressed
       seleccionarFilaGrid(gridTiempos, evt.getPoint());
   }//GEN-LAST:event_gridTiemposMousePressed

   private void menuMensajeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuMensajeActionPerformed
       enviarMensajeALaMesa();
   }//GEN-LAST:event_menuMensajeActionPerformed

   private void gridTiemposMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_gridTiemposMouseReleased
       if (evt.getButton() == java.awt.event.MouseEvent.BUTTON3) {
           mostrarMenuPopupGrid(gridTiempos, evt.getPoint().x, evt.getPoint().y);
       }
   }//GEN-LAST:event_gridTiemposMouseReleased

   private void ckbSoloConectadosActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ckbSoloConectadosActionPerformed
       mostrarConectados();
   }//GEN-LAST:event_ckbSoloConectadosActionPerformed

   private void btConectarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btConectarActionPerformed
       pulsadoConectar();
   }//GEN-LAST:event_btConectarActionPerformed

   private void menuCambiarUmbralActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuCambiarUmbralActionPerformed
       cambiarUmbralSutitutos();
   }//GEN-LAST:event_menuCambiarUmbralActionPerformed

   private void btGestionCitasActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btGestionCitasActionPerformed
       mostrarGestioncitas();
}//GEN-LAST:event_btGestionCitasActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btCapacidades;
    private javax.swing.JButton btColasFavoritas;
    private javax.swing.JButton btConectar;
    private javax.swing.JButton btGestionCitas;
    private javax.swing.JCheckBox ckbSoloConectados;
    private javax.swing.grid.JGrid gridTiempos;
    private javax.swing.JTable gridUbac;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JLabel lbModo;
    private javax.swing.JLabel lbPresentes;
    private javax.swing.JLabel lbPresentesU;
    private javax.swing.JLabel lbRetraso;
    private javax.swing.JMenuItem menuCambiarTiempo;
    private javax.swing.JMenuItem menuCambiarUmbral;
    private javax.swing.JMenuItem menuCapacidad;
    private javax.swing.JMenuItem menuCerrarCola;
    private javax.swing.JMenuItem menuMensaje;
    private javax.swing.JMenuItem menuMostrarOperadores;
    private javax.swing.JPanel panelCentral;
    private javax.swing.JPanel panelSuperior;
    private javax.swing.JPopupMenu popupMenuGrid;
    private javax.swing.JPopupMenu popupMenuSuperior;
    private javax.swing.JScrollPane scroll2;
    private javax.swing.JPanel tabColas;
    private javax.swing.JTabbedPane tabPanelSuperior;
    // End of variables declaration//GEN-END:variables

    public MapaOperadores getMapaOperadores() {
        return mapaOperadores;
    }

    public ColeccionRegistros getColeccionMesas() {
        return colMesas;
    }

    public ColeccionRegistros getColeccionColas() {
        return colColas;
    }

    @Override
    public void cerrar() {
        cerrarConexion();
    }

    class renderCeldaEstado extends javax.swing.table.DefaultTableCellRenderer {

        public renderCeldaEstado() {
            super();
            this.setIconTextGap(15);
        }

        @Override
        public java.awt.Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column) {
            RegistroMesa reg = (RegistroMesa) colMesas.getRegistro(row);
            if (reg == null) {
                return null;
            }
            try {
                int estado = reg.estado.charAt(0) - '0';
                setText(textoEstados[estado]);
                setIcon(Global.principal.getIconoEstado(estado));
                return this;
            } catch (Exception exc) {
                exc.printStackTrace();
                return null;
            }
        }
    }

    public class renderCeldaRojaFecha extends javax.swing.table.DefaultTableCellRenderer {

        public renderCeldaRojaFecha() {
            super();
        }
        boolean rojo;
        int lapso;

        void compruebaRojo(JTable table, int row) {
        }

        @Override
        public java.awt.Component getTableCellRendererComponent(javax.swing.JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column) {
            if (value == null) {
                return null;
            }
            try {
                if (((String) value).equals("")) {
                    lapso = 0;
                } else {
                    java.sql.Timestamp ts = java.sql.Timestamp.valueOf((String) value);
                    lapso = ahora - (int) (ts.getTime() / 1000);
                }
                setText(Global.segundosAsString(lapso));
                compruebaRojo(table, row);
                this.setForeground(rojo ? java.awt.Color.RED : java.awt.Color.BLACK);
                if (isSelected) {
                    this.setBackground(table.getSelectionBackground());
                } else {
                    this.setBackground(table.getBackground());
                }

                return this;
            } catch (Exception exc) {
                exc.printStackTrace();
                return null;
            }
        }
    }

    public class renderCeldaGrisTiempos extends javax.swing.table.DefaultTableCellRenderer {

        @Override
        public java.awt.Component getTableCellRendererComponent(javax.swing.JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column) {
            try {
                if (value == null) {
                    return null;
                }
                RegistroMesa reg = (RegistroMesa) colMesas.getRegistro(row);
                MapaOperadores.RegistroOperador regOp = mapaOperadores.get(reg.codigo);
                if (regOp.sinCapacidades()) {
                    this.setForeground(java.awt.Color.lightGray);
                } else {
                    this.setForeground(java.awt.Color.BLACK);
                }
                setText((String) value);

                if (isSelected) {
                    this.setBackground(table.getSelectionBackground());
                } else {
                    this.setBackground(table.getBackground());
                }
                return this;
            } catch (Exception exc) {
                exc.printStackTrace();
                return null;
            }
        }
    }

    public class renderCeldaRojaTiempos extends renderCeldaRojaFecha {

        public renderCeldaRojaTiempos() {
            super();
        }

        @Override
        void compruebaRojo(JTable table, int row) {
            String estado = (String) table.getValueAt(row, 0);
            rojo = false;
            String cola = (String) table.getValueAt(row, 9);
            if (cola == null || cola.equals(" ") || cola.equals("")) {
                return;
            }
            int maximo = tiempoColas.get(cola);
            if (lapso > maximo && (estado.equals("1") || estado.equals("4"))) {
                rojo = true;
                return;
            }
            if (estado.equals("5") && (lapso > (Configuracion.instanciaUnica().tiempoAlerta + (30 * 60)))) {
                rojo = true;
            }
        }
    }

    public class renderCeldaRojaUbac extends renderCeldaRojaFecha {

        public renderCeldaRojaUbac() {
            super();
        }

        @Override
        void compruebaRojo(JTable table, int row) {
            rojo = false;
            String cola = (String) table.getValueAt(row, 0);
            int maximo = tiempoColas.get(cola);
            if (lapso > maximo) {
                rojo = true;
            }
        }
    }

    public class renderCeldaRojaCola extends javax.swing.table.DefaultTableCellRenderer {

        public renderCeldaRojaCola() {
            super();
        }

        @Override
        public java.awt.Component getTableCellRendererComponent(javax.swing.JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column) {
            try {
                if (value == null) {
                    return null;
                }
                boolean rojo = false;
                int presentes = 0;
                int operadores = 0;
                try {
                    RegistroCola reg = (RegistroCola) colColas.getRegistro(row);
                    presentes = reg.getPresentes();
                    operadores = reg.operadores + reg.operadoresSup;
                } catch (Exception exc) {
                    exc.printStackTrace();
                }
                if (presentes > 0 && operadores == 0) {
                    rojo = true;
                }
                setText((String) value);
                this.setForeground(rojo ? java.awt.Color.RED : java.awt.Color.BLACK);
                if (isSelected) {
                    this.setBackground(table.getSelectionBackground());
                } else {
                    this.setBackground(table.getBackground());
                }
                return this;
            } catch (Exception exc) {
                exc.printStackTrace();
                return null;
            }
        }
    }
}
