/* 
* 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.datos.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import gestor.utiles.*;

public final class PanelTactil extends javax.swing.JFrame {

    Configuracion conf;
    TablaColas colas;
    private javax.swing.Timer timerVueltaPanelPrincipal;
    public static Rectangle dimBoton;
    public static Font fuenteBoton = new java.awt.Font("Arial", 3, 17);
    public InfoServicios infoServicios;
    boolean preparado = false;
    PanelBotones[] subpaneles;
    PanelBotones subpanelActual = null;
    RelojDigital motorReloj;
    boolean enAsesores = false;
    Dimension dimBotonIdioma;
    DlgTecladoVirtual teclado = null;
    java.util.Timer timerOnTop;
    public String codigoColaBotoCitaPrevia = "#CP";
    LogGenerico logFracasoHueco = null;

    public boolean haUsadoDNIe = false;

    public PanelTactil(GraphicsConfiguration gc) {
        super(gc);
        try {
            com.birosoft.liquid.LiquidLookAndFeel lnf = new com.birosoft.liquid.LiquidLookAndFeel();
            com.birosoft.liquid.LiquidLookAndFeel.setStipples(false);
            UIManager.setLookAndFeel(lnf);
            UIManager.getLookAndFeelDefaults().put("ClassLoader", getClass().getClassLoader());
        } catch (Exception exc) {
            JOptionPane.showMessageDialog(this, "Error al cargar el gestor de 'Look And Feel'");
        }
        try {
            setIconImage(new javax.swing.ImageIcon(getClass().getResource("/recursos/ateneo32x32.gif")).getImage());
        } catch (Exception exc) {
        }

        conf = Configuracion.instanciaUnica();
        initComponents();
        iconoAeat.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        iconoAeat.setIcon(new javax.swing.ImageIcon(getClass().getResource("/recursos/logoAbombado.gif"))); // NOI18N
        iconoAeat.setDoubleBuffered(true);
        reloj.setVisible(true);
        motorReloj = new RelojDigital(reloj);
        infoServicios = Configuracion.instanciaUnica().infoServicios;
        colas = TablaColas.getTablaColas();
        // if (colas.ExisteColaDeProfesionales()) {
        //   cargarTablaProfesionales();
        // }
        preparaTimers();
        preparaPaneles();

        Global.gestorIdiomas.cargarAyudas(infoServicios);
        if (Global.gestorIdiomas.ayudas[0] == null || infoServicios.noHayVisibles()) {
            botonAyuda.setVisible(false);
        } else {
            botonAyuda.setVisible(true);
            botonAyuda.setText(Global.trad.valor("Ayuda"));
        }
        preparado = true;
    }

    public void ponerEnPrimerPlano() {
        timerOnTop = new java.util.Timer();
        timerOnTop.schedule(new TimerTask() {

            @Override
            public void run() {
                try {
                    Robot robot = new Robot();
                    robot.mouseMove(20, 20);
                    robot.mousePress(InputEvent.BUTTON1_MASK);
                    robot.mouseRelease(InputEvent.BUTTON1_MASK);
                    robot.mouseMove(Global.panel.getWidth() - 20, 20);
                    robot.mousePress(InputEvent.BUTTON1_MASK);
                    robot.mouseRelease(InputEvent.BUTTON1_MASK);
                } catch (Exception exc) {
                }
            }
        }, 1000);
    }

    void preparaTimers() {
        timerVueltaPanelPrincipal = new javax.swing.Timer(conf.segundosCierreVentanas * 1000, new java.awt.event.ActionListener() {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent e) {
                cambiarPanel(subpanelActual.panelRetorno);
                timerVueltaPanelPrincipal.stop();
            }
        });
    }

    void preparaPaneles() {
        PercentLayout pcly = new PercentLayout(PercentLayout.VERTICAL, 0);

        if (!conf.mostrarBotonCitaPrevia) {
            pcly.addLayoutComponent(panelSuperior, "9%");
            pcly.addLayoutComponent(panelCitaPrevia, "6%");
            this.btCitaPrevia.setVisible(false);
            pcly.addLayoutComponent(panelBotones, "76%");  // - 6%
            pcly.addLayoutComponent(panelInferior, "9%");
        } else if (infoServicios.noHayVisibles()) {
            pcly.addLayoutComponent(panelSuperior, "9%");
            pcly.addLayoutComponent(panelCitaPrevia, "55%");
            pcly.addLayoutComponent(panelBotones, "27%");
            pcly.addLayoutComponent(panelInferior, "9%");
        } else if (colas.ExisteColaDeCitaPrevia()) {
            pcly.addLayoutComponent(panelSuperior, "9%");
            pcly.addLayoutComponent(panelCitaPrevia, "12%");
            pcly.addLayoutComponent(panelBotones, "70%");
            pcly.addLayoutComponent(panelInferior, "9%");
        } else {
            pcly.addLayoutComponent(panelSuperior, "9%");
            pcly.addLayoutComponent(panelCitaPrevia, "6%");
            this.btCitaPrevia.setVisible(false);
            pcly.addLayoutComponent(panelBotones, "76%");   // -6%
            pcly.addLayoutComponent(panelInferior, "9%");
        }

        getContentPane().setLayout(pcly);

        if (conf.usandoSubmenus) {
            preparaPaneles_2(conf.ficheroSubmenu);
        } else {
            preparaPaneles_1();
            botonMas.setText(Global.trad.valor("masServicios"));
        }
        btCitaPrevia.setText(Global.trad.valor("SiTieneCita"));
        cambiarPanel(subpaneles[0]);
    }

    void cambiarPanel(PanelBotones panel) {
        if (panel == null) {
            return;
        }
        ((CardLayout) panelBotones.getLayout()).show(panelBotones, panel.nombre);
        if (panel.mostrarBotonSiguiente) {
            botonMas.setText(Global.trad.valor(panel.claveBotonSiguiente));
            botonMas.setVisible(true);
        } else {
            botonMas.setVisible(false);
        }
        subpanelActual = panel;
        timerVueltaPanelPrincipal.restart();
    }

    void insertarPanelBotones(PanelBotones panel) {
        panelBotones.add(panel, panel.nombre);
    }

    void preparaPaneles_1() {
        SubMenu unico = new SubMenu("principal");
        unico.crearServicios();
        int numBotonesVisibles = unico.numBotones();
        int numSubpaneles = ((numBotonesVisibles - 1) / conf.maxButons) + 1;
        subpaneles = new PanelBotones[numSubpaneles];
        for (int i = 0; i < numSubpaneles; i++) {
            subpaneles[i] = new PanelBotones("panel_" + i);
            insertarPanelBotones(subpaneles[i]);
            subpaneles[i].mostrarBotonSiguiente = numSubpaneles > 1;
            subpaneles[i].claveBotonSiguiente = "masServicios";
        }
        for (int i = 0; i < subpaneles.length - 1; i++) {
            subpaneles[i].panelSiguiente = subpaneles[i + 1];
        }
        subpaneles[subpaneles.length - 1].panelSiguiente = subpaneles[0];
        for (int i = 1; i < subpaneles.length; i++) {
            subpaneles[i].panelRetorno = subpaneles[0];
        }
        prepararBotones_1(unico, 0);
    }

    void crearSubPaneles(SubMenu menu, ArrayList<PanelBotones> listaPaneles) {
        int numBotonesVisibles = menu.numBotones();
        int numSubpaneles = ((numBotonesVisibles - 1) / conf.maxButons) + 1;
        menu.paneles = new PanelBotones[numSubpaneles];
        for (int i = 0; i < numSubpaneles; i++) {
            menu.paneles[i] = new PanelBotones(menu.nombre + "_" + i);
            insertarPanelBotones(menu.paneles[i]);
            if (!menu.nombre.equals("principal")) {
                menu.paneles[i].cambiaTitulo(menu.nombre);
            }
            if (menu.paneles.length > 1) {
                menu.paneles[i].claveBotonSiguiente = "masServicios";
                menu.paneles[i].panelSiguiente = (i == numSubpaneles - 1) ? menu.paneles[0] : menu.paneles[i + 1];
            } else {
            }
        }
        listaPaneles.addAll(Arrays.asList(menu.paneles));
        if (menu.paneles.length == 1) {
            menu.paneles[0].claveBotonSiguiente = "principal";
            menu.paneles[0].panelSiguiente = listaPaneles.get(0);
        } else {
            for (int i = 0; i < numSubpaneles - 1; i++) {
                menu.paneles[i].claveBotonSiguiente = "masServicios";
                menu.paneles[i].panelSiguiente = menu.paneles[i + 1];
            }
            menu.paneles[numSubpaneles - 1].panelSiguiente = menu.paneles[0];
            menu.paneles[numSubpaneles - 1].claveBotonSiguiente = "masServicios";
        }
        for (Iterator it = menu.menus.iterator(); it.hasNext();) {
            crearSubPaneles((SubMenu) it.next(), listaPaneles);
        }
    }

    void preparaPaneles_2(File ficheroConf) {
        GestorSubMenus gestorMenus = new GestorSubMenus();
        gestorMenus.cargar(ficheroConf);
        ArrayList<PanelBotones> paneles = new ArrayList<>();
        crearSubPaneles(gestorMenus.principal, paneles);
        subpaneles = new PanelBotones[paneles.size()];
        subpaneles = paneles.toArray(subpaneles);
        for (int i = 1; i < subpaneles.length; i++) {
            subpaneles[i].panelRetorno = subpaneles[0];
        }
        if (gestorMenus.principal.paneles.length == 1) {
            gestorMenus.principal.paneles[0].mostrarBotonSiguiente = false;
        }
        prepararBotones_2(gestorMenus.principal);
    }

    void prepararBotones_1(SubMenu menu, int primerPanel) {
        int maxBotones = conf.maxButons;
        int numPanel = primerPanel;
        for (InfoServicio infoserv : menu.servicios) {
            if (infoserv.cola.equals("hueco")) {
                subpaneles[numPanel].nuevoBoton(new BotonHueco());
            } else {
                subpaneles[numPanel].nuevoBoton(new BotonCola(infoserv));
            }
            if (subpaneles[numPanel].numBotones() == maxBotones) {
                numPanel++;
            }
        }
    }

    void prepararBotones_2(SubMenu menu) {
        int maxBotones = conf.maxButons;
        int numPanel = 0;
        for (SubMenu.ElementoOrdenado eo : menu.ordenados) {
            if (eo.hueco) {
                menu.paneles[numPanel].nuevoBoton(new BotonHueco());
                if (menu.paneles[numPanel].numBotones() == maxBotones) {
                    numPanel++;
                }
            } else if (eo.submenu != null) {
                SubMenu submenu = eo.submenu;
                BotonMenu boton = new BotonMenu(submenu);
                menu.paneles[numPanel].nuevoBoton(boton);
                menu.paneles[numPanel].tieneSubMenus = true;
                if (menu.paneles[numPanel].numBotones() == maxBotones) {
                    numPanel++;
                }
            } else if (eo.servicio != null) {
                InfoServicio infoserv = eo.servicio;
                menu.paneles[numPanel].nuevoBoton(new BotonCola(infoserv));
                if (menu.paneles[numPanel].numBotones() == maxBotones) {
                    numPanel++;
                }
            }
        }
        for (Iterator it = menu.menus.iterator(); it.hasNext();) {
            prepararBotones_2((SubMenu) it.next());
        }
    }

    void ajustarBotones() {
        int maxBotones = 0;
        for (PanelBotones subpanele : subpaneles) {
            if (subpanele.numBotones() > maxBotones) {
                maxBotones = subpanele.numBotones();
            }
        }
        if (maxBotones > 0) {
            dimBoton = DistribuidorBotones.calcularBotones(maxBotones, this.getWidth());
            calculaFuenteBoton();
            for (PanelBotones subpanele : subpaneles) {
                for (Iterator it = subpanele.botones.iterator(); it.hasNext();) {
                    ((BotonServicio) it.next()).ajusta();
                }
            }
        }
        int altoBotonCita = 20;
        int altoPanelCita = panelCitaPrevia.getHeight();
        if (maxBotones > 0) {
            altoBotonCita = dimBoton.height;
            if (altoBotonCita >= altoPanelCita && altoPanelCita > 0) {
                altoBotonCita = altoPanelCita * 90 / 100;
            }
        } else {
            if (altoPanelCita == 0) {
                altoPanelCita = 100;
            }
            altoBotonCita = altoPanelCita * 40 / 100;
        }
        btCitaPrevia.setSize(this.getWidth() / 2, altoBotonCita);
        btCitaPrevia.setFont(calculaFuenteBoton(btCitaPrevia.getText(), btCitaPrevia.getWidth() - 24, btCitaPrevia.getHeight() - 8));
        int x = (this.getWidth() - btCitaPrevia.getWidth()) / 2;
        int y = (panelCitaPrevia.getHeight() - btCitaPrevia.getHeight()) / 2;
        btCitaPrevia.setLocation(x, y);

//        int altoDnie = panelSuperior.getHeight() * 2 / 3;
//        int anchoDnie = (int) (altoDnie * 1.9);

//        lbIconoDNIe.setSize(anchoDnie, altoDnie);
//        lbIconoDNIe.setLocation(panelCitaPrevia.getWidth() - anchoDnie - (anchoDnie / 3), 0);
//        lbIconoDNIe.setEnabled(false);
//        if (conf.usarBotonDNI) {
//            try {
//                ResizedGif icon = new ResizedGif(getClass().getResource("/recursos/dnieAnimado.gif"));
//                icon.setSize(LogoDnieSize());
//                lbIconoDNIe.setIcon(icon);
//                lbIconoDNIe.setEnabled(true);
//            } catch (Exception exc) {
//            }
//        }
    }

    void calculaFuenteBoton() {
        int ancho = dimBoton.width - 24;
        int alto = dimBoton.height - 8;
        Font fuente;
        for (int i = 0; i < Global.gestorIdiomas.numeroIdiomas; i++) {
            if (conf.sizeFont == -1) {
                String texto = infoServicios.getDescripcionLarga(i);
                fuente = calculaFuenteBoton(texto, ancho, alto);
            } else {
                fuente = fuenteBoton.deriveFont((float) conf.sizeFont);
            }
            Global.gestorIdiomas.fuentes[i] = fuente;
        }
        fuenteBoton = Global.gestorIdiomas.fuentes[0];
    }

    public Font calculaFuenteBoton(String texto, int ancho, int alto) {
        float fontSize = 50f;
        int ancho2 = ancho - 30;
        Graphics2D g2 = (Graphics2D) this.getGraphics();
        FontRenderContext frc = g2.getFontRenderContext();
        TextLayout tly = null;
        Font fuente;
        Rectangle2D rec;
        while (true) {
            fuente = fuenteBoton.deriveFont(fontSize);
            tly = new TextLayout(texto, fuente, frc);
            rec = tly.getBounds();
            if (rec.getHeight() > alto || rec.getWidth() >= ancho2) {
                fontSize--;
            } else {
                break;
            }
        }
        return fuenteBoton.deriveFont(fontSize);
    }

    public void distribuir() {
        for (PanelBotones subpanele : subpaneles) {
            DistribuidorBotones.distribuir(subpanele);
            subpanele.ajustarBotonMenu();
        }
    }

    public void crearBandas() {
        // panel superior
        int altoPanelSuperior = (this.getHeight() * 9) / 100;
        int anchoPantalla = this.getWidth();
        int d = altoPanelSuperior - 6;
        int anchoReloj = (int) ((float) d * 1.8);
        reloj.setBounds(anchoPantalla - anchoReloj - 3, 6, anchoReloj, d);
        reloj.setFocusable(false);
        iconoAeat.setBounds(3, 3, d, d);
        Image imagen;
        if (conf.iconoBoton.length() > 4) {
            imagen = Toolkit.getDefaultToolkit().getImage(conf.iconoBoton);
        } else {
            imagen = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/recursos/ateneo.gif"));
        }
        iconoAeat.setIcon(new ImageIcon(imagen.getScaledInstance(d, d, Image.SCALE_SMOOTH)));
        int d2 = altoPanelSuperior / 4;
        rotulo.setBounds(d + 20, d2 + 2, anchoPantalla - (anchoReloj + 20) - (d + 8), d2 * 2);
        rotulo.setBackground(panelSuperior.getBackground());
        Global.gestorIdiomas.crearRotulos(rotulo);
        rotulo.setIcon(Global.gestorIdiomas.rotuloActual());

        reloj.setFont(reloj.getFont().deriveFont(GeneradorRotulo.fontSize * 0.80f));
        reloj.setForeground(conf.colorReloj);

        ajustarBotones();

        // panel inferior
        botonMas.setFont(fuenteBoton);
        botonMas.setForeground(Color.RED);
        int anchoBotonMas = (int) (anchoPantalla / 3.5);
        botonMas.setBounds(anchoPantalla - anchoBotonMas - 3, 3, anchoBotonMas, d);
        botonAyuda.setBounds(3, 3, anchoBotonMas, d);
        botonAyuda.setFont(fuenteBoton);
        botonAyuda.setFocusable(false);
        if (Global.gestorIdiomas.numeroIdiomas > 1) {
            crearPanelIdiomas(anchoPantalla, anchoBotonMas, d);
        }

        distribuir();
        prepararReloj();
    }

    void prepararReloj() {
        java.util.Date hora = Fecha.parseFecha(conf.horaApagadoMaquina);
        if (hora.after(Fecha.ahora())) {
            motorReloj.añadirAviso(hora, new RelojDigital.IRelojAvisable() {
                @Override
                public void avisar() {
                    Global.mainForm.apagarMaquina();
                }
            });
        }
        motorReloj.start();
    }

    void crearPanelIdiomas(int anchoPantalla, int anchoBotonMas, int altoPanel) {
        int yPanelIdioma = 0;
        int xPanelIdioma = 3 + anchoBotonMas;
        int anchoPanelIdioma = anchoPantalla - 3 - xPanelIdioma;
        if (botonMas.isVisible() || conf.usandoSubmenus) {
            anchoPanelIdioma -= botonMas.getWidth();
        }
        int altoPanelIdioma = altoPanel;
        int anchoBoton;
        if (dimBoton != null) {
            anchoBoton = dimBoton.width * 60 / 100;
        } else {
            anchoBoton = anchoPantalla * 25 / 100;
        }
        int altoBoton = altoPanelIdioma / 2 - 1;
        if ((anchoBoton + 5) * Global.gestorIdiomas.numeroIdiomas < anchoPanelIdioma) {
            altoPanelIdioma = altoPanel / 2;
            yPanelIdioma = altoPanelIdioma;
            altoBoton = altoPanelIdioma - 1;
        }
        dimBotonIdioma = new Dimension(anchoBoton, altoBoton);
        panelIdiomas.setBounds(xPanelIdioma, yPanelIdioma, anchoPanelIdioma, altoPanel);

        String rotuloIdioma = Global.gestorIdiomas.idiomaMasLargo();
        Font fuenteIdioma = calculaFuenteBoton(rotuloIdioma, anchoBoton, altoBoton);
        fuenteIdioma = fuenteIdioma.deriveFont((float) (fuenteIdioma.getSize() * 70 / 100));

        if (Global.gestorIdiomas.numeroIdiomas > 1) {
            for (int i = 0; i < Global.gestorIdiomas.numeroIdiomas; i++) {
                BotonIdioma bid = new BotonIdioma(Global.gestorIdiomas.idiomas[i], i, fuenteIdioma);
                panelIdiomas.add(bid);
            }
        }
    }

    String nif;
    String nombre;

    boolean pedirNifYNombre(boolean necesitaApellido) {
        if (Global.mainForm.lectorSC.hayTarjetaPresente()) {
            LectorSmartCard.DatosDNIe datos = Global.mainForm.lectorSC.leerDNIe();
            nombre = datos.nombre;
            nif = datos.nif;
            haUsadoDNIe = true;
        } else {
            if (teclado == null) {
                teclado = new DlgTecladoVirtual(this);
                teclado.setLocation(0, panelSuperior.getHeight());
                teclado.setSize(panelSuperior.getWidth(), this.getHeight() - panelSuperior.getHeight());
            }
            teclado.clear();
            teclado.setNecesitaApellido(necesitaApellido);
            teclado.dnie = false;
            teclado.setVisible(true);
            if (teclado.nifTecleado == null) {
                return false;
            }
            nombre = teclado.apellidoTecleado;
            nif = teclado.nifTecleado;
        }
        return true;
    }

    void ElegirOpcionCita(String colaCita, String rotulo) {
        // previos...
        haUsadoDNIe = false;
        //  colaCita = colaCita.substring(0, 1);
        RegistroCola cola = colas.buscar(colaCita);
        java.sql.Timestamp horaCita = Fecha.TimestampNulo;
        boolean ticketConfirmado = false;
        boolean ticketDiferido = false;
        if (cola == null) {
            return;
        }
        if (cola.cerrada) {
            ServicioCerrado(colaCita, rotulo);
            return;
        }

        if (colas.esProfesional(colaCita)) {
            PulsadoPedirNif(true, rotulo);
            return;
        }
        nombre = "Gestor Automatico";
        nif = "xxx";

        // proceso para colas con cita previa
        if (cola.citaPrevia) {
         // -1. previo pedido por Dlg. Barcelona
            // si está en la lista de excluidos de gestion de huecos, nos vamos al boton grande
            if (conf.excluirGestionHuecos.contains(colaCita)) {
                pulsadoCitaPrevia();
                return;
            }
            if (Global.mainForm.gestionHuecos) {
                // 1. comprobamos si hay alguna cita disponible
                RegistroHuecos[] regsHuecos = Global.mainForm.huecos.buscarDisponibles(cola.cola, Fecha.ahora(), conf.minutosMargenCita);
                if (regsHuecos == null || regsHuecos.length == 0) {
                    DlgMensajeGenerico msg = new DlgMensajeGenerico(this);
                    msg.setLineas(Global.trad.valor("Servicios con Cita Previa"), Global.trad.valor("NoHayCitasDisponibles"), Global.trad.valor("SiYaTieneCita"));
                    msg.centrarLineas(true, true, true);
                    msg.setVisible(true);
                    return;
                }
            }
            // 2. Si no hay DNIe insertado mostramos el teclado virtual para pedir el nif
            if (!pedirNifYNombre(true)) {
                return;
            }
            // 3. buscamos otras citas
            ArrayList<RegistroCandidatos> citas = new ArrayList<>();
            if (cola.citaPrevia && nif.length() > 8) {
                TablaCandidatos.getTablaCandidatos().buscarTodosConNif(nif, citas);
                if (TablaCandidatos.getTablaCandidatos().comprobarEstadoCitas(citas) != -1) {
                    if (TablaCandidatos.getTablaCandidatos().algunoEnHora(citas)) {
                        procesarNifSinMostrar(nif);
                        return;
                    }
                }
            }

            // 4. Volvemos a comprobar los huecos, por si...
            if (Global.mainForm.gestionHuecos) {
                RegistroHuecos[] regsHuecos = Global.mainForm.huecos.buscarDisponibles(cola.cola, Fecha.ahora(), conf.minutosMargenCita);
                if (regsHuecos == null || regsHuecos.length == 0) {
                    DlgMensajeGenerico msg = new DlgMensajeGenerico(this);
                    msg.setLineas(Global.trad.valor("Servicios con Cita Previa"), Global.trad.valor("NoHayCitasDisponibles"), "");
                    msg.centrarLineas(true, true, true);
                    msg.setVisible(true);
                    return;
                }

                // 5. Ofrecemos las citas disponibles
                DlgOfrecerCitas dlgOfrecer = new DlgOfrecerCitas(this);
                dlgOfrecer.cargar(regsHuecos, rotulo);
                RegistroHuecos regHueco = regsHuecos[0];
                horaCita = regHueco.horaCita;
                if (horaCita.getTime() < (System.currentTimeMillis() + conf.minutosTicketInmediato * 60000L)) {
                    dlgOfrecer.setpulsadorAutomatico(true);
                }
                dlgOfrecer.setVisible(true);
                if (dlgOfrecer.regSeleccionado == null) {
                    return;
                }
                regHueco = dlgOfrecer.regSeleccionado;
                dlgOfrecer.dispose();
                dlgOfrecer = null;
                Global.mainForm.resetMemoria();
                horaCita = regHueco.horaCita;
                if (horaCita.getTime() >= (System.currentTimeMillis() + conf.minutosTicketInmediato * 60000L)) {
                    ticketDiferido = true;
                }
                ticketConfirmado = true;
            }
        } // Si no hay gestion de huecos o la cola no es de cita previa, le damos el ticket y palante
        if (!cola.citaPrevia || !Global.mainForm.gestionHuecos) {
            if (cola.nifObligatorio && nif.equalsIgnoreCase("xxx")) {
                if (!pedirNifYNombre(cola.necesitaApellido())) {
                    return;
                }
            }
            DlgConfirmarTicket confirmacion = new DlgConfirmarTicket(this);
            confirmacion.setPregunta(Global.trad.valor("imprimirTicketPara"));
            confirmacion.setRotulo(rotulo.toUpperCase() + " ?");
            confirmacion.setVisible(true);
            if (confirmacion.emitirTicket) {
                ticketConfirmado = true;
            }
            confirmacion.dispose();
            confirmacion = null;
            Global.mainForm.resetMemoria();
        }

        if (ticketConfirmado) {
            if (!ticketDiferido) {
                Global.mainForm.mandarPeticion(colaCita, nif, nombre, horaCita);
            } else {
                Global.mainForm.mandarPeticionNoPresente(colaCita, nif, nombre, horaCita);
            }
            cambiarPanel(subpanelActual.panelRetorno);
        }
        enAsesores = false;
    }

    void procesarNifSinMostrar(String nif) {
        DlgPedirNif pedirnif = new DlgPedirNif(this, nif);
        pedirnif.dispose();
        pedirnif = null;
        Global.mainForm.resetMemoria();
    }

    public void huecoOcupado(String mensaje) {
        String[] params = Global.split(mensaje, '|');
        java.sql.Timestamp horaCita = java.sql.Timestamp.valueOf(params[0]);
        String cola = params[1];
        // Vamos a grabar los fracasos en la asignacion de huecos para depurar...
        if (logFracasoHueco == null) {
            logFracasoHueco = new LogGenerico("HuecosCancelados.log", "Huecos cancelados");
            logFracasoHueco.aligerar(10, 5);
        }
        logFracasoHueco.escribir(Fecha.formatoHoraHMS(new Date()) + " -> " + Fecha.formatoHoraHM(horaCita) + " " + cola);

        // Eliminamos los huecos para que no se repita el intento...
        // pero hay un error, pues esos huecos no deberían existir ya.
        TablaHuecos.getTablaHuecos().eliminarTodos(cola, horaCita);

        DlgMensajeGenerico msg = new DlgMensajeGenerico(this);
        msg.setLinea1(Global.trad.valor("Servicios con Cita Previa"));
        msg.setLinea2(Global.trad.valor("horaYaOcupada"));
        msg.setLinea3(Global.trad.valor("intenteloDeNuevo"));
        msg.centrarLineas(true, true, true);
        msg.setVisible(true);
    }

    void ServicioCerrado(String cola, String Rotulo) {
        Font fuente;
        fuente = new Font("Arial", Font.BOLD, 46);
        DlgAsesores servicioC = new DlgAsesores(this);
        servicioC.jLabel1.setText(Rotulo);
        RegistroCola regCola = colas.buscar(cola);
        String txt = regCola.textoCerrada.trim();
        if (txt.length() > 0) {
            txt = "<html>" + txt + "</html>";
            servicioC.jLabel2.setText(txt);
        } else {
            servicioC.jLabel2.setText(Global.trad.valor("servicioCerradoTemporalmente"));
        }
        servicioC.jLabel1.setFont(fuente);
        fuente = new Font("Arial", Font.BOLD, 40);
        servicioC.jLabel1.setFont(fuente);
        servicioC.timerCierraAviso.start();
        servicioC.ocultarBoton();
        Global.mainForm.desactivarSalvaPantalla();
        servicioC.setVisible(true);
        servicioC.dispose();
        servicioC = null;
        Global.mainForm.activarSalvaPantalla();
    }

    void pulsadoCitaPrevia() {
        if (conf.colasAyudaObligatoria.contains(codigoColaBotoCitaPrevia)) {
            mostrarAyuda(codigoColaBotoCitaPrevia);
        } else {
            if (Global.mainForm.lectorSC.hayTarjetaPresente()) {
                LectorSmartCard.DatosDNIe datos = Global.mainForm.lectorSC.leerDNIe();
                haUsadoDNIe = true;
                procesarNifSinMostrar(datos.nif);
                Global.mainForm.lectorSC.mostrarDialogoExtraerTarjeta(this);
            } else {
                PulsadoPedirNif(false, "");
            }
        }
    }

    void pulsadoBotonMas() {
        cambiarPanel(subpanelActual.panelSiguiente);
        if (subpanelActual.panelRetorno == null) {
            timerVueltaPanelPrincipal.stop();
        } else {
            timerVueltaPanelPrincipal.start();
        }
    }

    public void PulsadoPedirNif(boolean profesional, String textoRotulo) {
        DlgPedirNif pedirnif = new DlgPedirNif(this, profesional, textoRotulo);
        if (infoServicios.todosCitaPrevia) {
            pedirnif.cerrarSolo = false;
        }
        pedirnif.setVisible(true);
        pedirnif.dispose();
        pedirnif = null;
        Global.mainForm.resetMemoria();
        Global.mainForm.resetSalvaPantalla();
    }

    public void PulsadoAyuda() {
        mostrarAyuda(null);
    }

    void pedirPin(boolean eterno) {
        String pin = conf.codigoCerrado;
        DlgPedirPin pp = new DlgPedirPin(this, pin, eterno);
        Global.mainForm.desactivarSalvaPantalla();
        pp.setVisible(true);
        Global.mainForm.activarSalvaPantalla();
        if (pp.resultado) {
            Global.mainForm.cerrarAplicacion();
        }
    }

    void cambiarIdioma(int idioma) {
        if (Global.gestorIdiomas.idiomaActivo() == idioma) {
            return;
        }
        // guardar en el gestor de idiomas y cambiar el traductor
        Global.gestorIdiomas.cambiarIdioma(idioma);
        // cambiar el texto de los botones de colas
        fuenteBoton = Global.gestorIdiomas.fuentes[idioma];
        cambiarBotones();
        // cambiar otros botones
        botonMas.setText(Global.trad.valor(subpanelActual.claveBotonSiguiente));
        if (Global.gestorIdiomas.ayudas[idioma] == null || infoServicios.noHayVisibles()) {
            botonAyuda.setVisible(false);
        } else {
            botonAyuda.setVisible(true);
            botonAyuda.setText(Global.trad.valor("Ayuda"));
        }
        // cambiar el rotulo de cabecera
        rotulo.setIcon(Global.gestorIdiomas.rotuloActual());
        // cambiar textos del tiquet
        conf.textoSalaEspera = Global.trad.valor("Sala de espera");
        conf.textoAgenciaTributaria = Global.trad.valor("titulo");
        conf.textoCortoAgenciaTributaria = Global.trad.valor("tituloCorto");
        btCitaPrevia.setText(Global.trad.valor("SiTieneCita"));
    }

    void cambiarBotones() {
        for (PanelBotones panel : subpaneles) {
            for (Iterator it = panel.botones.iterator(); it.hasNext();) {
                ((BotonServicio) it.next()).cambiaTexto();
            }
        }
    }

    public void mostrarAyuda(String colaMostrar) {
        FormAyuda ayuda = new FormAyuda(this, fuenteBoton);
        if (colaMostrar == null) {
            ayuda.iniciar();
        } else {
            ayuda.iniciarEnColaEspecifica(colaMostrar);
        }
        String cola = ayuda.colaSolicitada;
        ayuda.dispose();
        ayuda = null;
        Global.mainForm.resetMemoria();
        if (cola != null) {
            if (cola.equalsIgnoreCase("#cp")) {
                PulsadoPedirNif(false, "");
            } else {
                ElegirOpcionCita(cola, infoServicios.get(cola).getDescripcion());
                Global.mainForm.lectorSC.mostrarDialogoExtraerTarjeta(this);
            }
        }
    }

//    public void mostrarAyudaDNIe() {
//        FormAyuda ayuda = new FormAyuda(this, fuenteBoton);
//        ayuda.iniciarEnColaEspecifica("DNIE");
//        ayuda.dispose();
//    }

    public void msgBox(String msg) {
        JOptionPane.showMessageDialog(this, msg);
    }
    
    ActionListener menuPulsado = new java.awt.event.ActionListener() {

        @Override
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            // poner aviso sonoro
            Global.mainForm.resetSalvaPantalla();
            BotonMenu boton = (BotonMenu) evt.getSource();
            cambiarPanel(boton.miPanel);
            timerVueltaPanelPrincipal.start();
        }
    };
    
    ActionListener botonPulsado = new java.awt.event.ActionListener() {

        @Override
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            // poner aviso sonoro
            BotonCola boton = (BotonCola) evt.getSource();
            //    String colaCita = boton.cola.substring(0, 1);
            String colaCita = boton.cola;

            if (conf.colasAyudaObligatoria.contains(colaCita)) {
                mostrarAyuda(colaCita);
            } else {
                String rotulo = boton.getText();
                ElegirOpcionCita(colaCita, rotulo);
                Global.mainForm.lectorSC.mostrarDialogoExtraerTarjeta(Global.panel);
            }
        }
    };

    void resetTimers() {
        Global.mainForm.resetSalvaPantalla();
        timerVueltaPanelPrincipal.restart();
    }

//    public Dimension LogoDnieSize() {
//        return lbIconoDNIe.getSize();
//    }
//
//    public Point LogoDniePosicion() {
//        return lbIconoDNIe.getLocation();
//    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jButton5 = new javax.swing.JButton();
        panelSuperior = new javax.swing.JPanel();
        iconoAeat = new javax.swing.JLabel();
        rotulo = new javax.swing.JLabel();
        reloj = new SmoothLabel();
        panelCitaPrevia = new javax.swing.JPanel();
        btCitaPrevia = new MiBoton();
        lbIconoDNIe = new javax.swing.JLabel();
        panelBotones = new javax.swing.JPanel();
        panelInferior = new javax.swing.JPanel();
        botonMas = new MiBoton();
        botonAyuda = new MiBoton();
        panelIdiomas = new javax.swing.JPanel();

        jButton5.setText("jButton2");

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Autoservicio ATENEO");
        setUndecorated(true);
        addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentShown(java.awt.event.ComponentEvent evt) {
                formComponentShown(evt);
            }
        });
        addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseMoved(java.awt.event.MouseEvent evt) {
                formMouseMoved(evt);
            }
        });
        addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                formKeyPressed(evt);
            }
        });
        getContentPane().setLayout(null);

        panelSuperior.setBackground(conf.colorPanel);
        panelSuperior.setLayout(null);

        iconoAeat.setIcon(new javax.swing.ImageIcon(getClass().getResource("/recursos/ateneo32x32.gif"))); // NOI18N
        iconoAeat.setDoubleBuffered(true);
        iconoAeat.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                iconoAeatMouseClicked(evt);
            }
        });
        panelSuperior.add(iconoAeat);
        iconoAeat.setBounds(0, 0, 60, 40);

        rotulo.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        rotulo.setText("Agencia Tributaria. Atención al ciudadano");
        panelSuperior.add(rotulo);
        rotulo.setBounds(70, 10, 1000, 45);

        reloj.setFont(new java.awt.Font("Lucida Console", 1, 18)); // NOI18N
        reloj.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        panelSuperior.add(reloj);
        reloj.setBounds(600, 10, 70, 30);

        getContentPane().add(panelSuperior);
        panelSuperior.setBounds(0, 0, 670, 40);

        panelCitaPrevia.setBackground(conf.colorPanel);
        panelCitaPrevia.setLayout(null);

        btCitaPrevia.setForeground(new java.awt.Color(255, 0, 51));
        btCitaPrevia.setText("Si tiene CITA CONCERTADA pulse aquí");
        btCitaPrevia.setFocusable(false);
        btCitaPrevia.setMargin(new java.awt.Insets(2, 12, 2, 12));
        btCitaPrevia.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btCitaPreviaActionPerformed(evt);
            }
        });
        panelCitaPrevia.add(btCitaPrevia);
        btCitaPrevia.setBounds(208, 12, 214, 32);

        lbIconoDNIe.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        lbIconoDNIe.setVerticalAlignment(javax.swing.SwingConstants.TOP);
        lbIconoDNIe.setFocusable(false);
        lbIconoDNIe.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
        lbIconoDNIe.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                lbDniePresionada(evt);
            }
        });
        panelCitaPrevia.add(lbIconoDNIe);
        lbIconoDNIe.setBounds(450, 0, 170, 50);

        getContentPane().add(panelCitaPrevia);
        panelCitaPrevia.setBounds(8, 48, 623, 52);

        panelBotones.setBackground(conf.colorPanel);
        panelBotones.setName("panelBotones"); // NOI18N
        panelBotones.setLayout(new java.awt.CardLayout());
        getContentPane().add(panelBotones);
        panelBotones.setBounds(0, 108, 670, 276);

        panelInferior.setBackground(conf.colorPanel);
        panelInferior.setLayout(null);

        botonMas.setFocusable(false);
        botonMas.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonMasActionPerformed(evt);
            }
        });
        panelInferior.add(botonMas);
        botonMas.setBounds(590, 10, 70, 20);

        botonAyuda.setForeground(new java.awt.Color(255, 0, 0));
        botonAyuda.setIcon(new javax.swing.ImageIcon(getClass().getResource("/recursos/help.gif"))); // NOI18N
        botonAyuda.setText(" Ayuda");
        botonAyuda.setDebugGraphicsOptions(javax.swing.DebugGraphics.NONE_OPTION);
        botonAyuda.setFocusable(false);
        botonAyuda.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonAyudaActionPerformed(evt);
            }
        });
        panelInferior.add(botonAyuda);
        botonAyuda.setBounds(10, 10, 103, 41);

        panelIdiomas.setBackground(conf.colorPanel);
        panelIdiomas.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 5, 2));
        panelInferior.add(panelIdiomas);
        panelIdiomas.setBounds(170, 0, 380, 30);

        getContentPane().add(panelInferior);
        panelInferior.setBounds(2, 384, 670, 40);

        pack();
    }// </editor-fold>//GEN-END:initComponents
    private void btCitaPreviaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btCitaPreviaActionPerformed
        pulsadoCitaPrevia();
    }//GEN-LAST:event_btCitaPreviaActionPerformed

    private void formComponentShown(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentShown
        // Parece que esto es necesario para que no se escachuflen los botones
    }//GEN-LAST:event_formComponentShown

    private void formKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_formKeyPressed
        resetTimers();
    }//GEN-LAST:event_formKeyPressed

    private void formMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseMoved
        resetTimers();
    }//GEN-LAST:event_formMouseMoved

    private void iconoAeatMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_iconoAeatMouseClicked
        if (evt.getClickCount() == 3) {
            pedirPin(false);
        }
    }//GEN-LAST:event_iconoAeatMouseClicked

    private void botonAyudaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonAyudaActionPerformed
        PulsadoAyuda();
    }//GEN-LAST:event_botonAyudaActionPerformed

   private void botonMasActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonMasActionPerformed
       pulsadoBotonMas();
   }//GEN-LAST:event_botonMasActionPerformed

   private void lbDniePresionada(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lbDniePresionada
//       if (conf.usarBotonDNI) {
//           mostrarAyudaDNIe();
//       }
   }//GEN-LAST:event_lbDniePresionada

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton botonAyuda;
    private javax.swing.JButton botonMas;
    private javax.swing.JButton btCitaPrevia;
    private javax.swing.JLabel iconoAeat;
    private javax.swing.JButton jButton5;
    private javax.swing.JLabel lbIconoDNIe;
    private javax.swing.JPanel panelBotones;
    private javax.swing.JPanel panelCitaPrevia;
    private javax.swing.JPanel panelIdiomas;
    private javax.swing.JPanel panelInferior;
    private javax.swing.JPanel panelSuperior;
    private javax.swing.JLabel reloj;
    private javax.swing.JLabel rotulo;
    // End of variables declaration//GEN-END:variables

    class BotonServicio extends gestor.utiles.MiBoton {

        InfoServicio info;

        public BotonServicio() {
            setFocusable(false);
        }

        public void ajusta() {
            setFont(fuenteBoton);
            setText(info.getDescripcionConFormato());
            setSize(dimBoton.width, dimBoton.height);
            this.setMargin(new Insets(4, 8, 4, 8));
        }

        public void cambiaTexto() {
            if (fuenteBoton != getFont()) {
                setFont(fuenteBoton);
            }
            setText(info.getDescripcionConFormato());
        }
    }

    class BotonHueco extends BotonServicio {

        @Override
        public void paint(Graphics g) {
        }

        @Override
        public void ajusta() {
            setSize(dimBoton.width, dimBoton.height);
            this.setMargin(new Insets(4, 8, 4, 8));
        }

        @Override
        public void cambiaTexto() {
        }
    }

    class BotonCola extends BotonServicio {

        String cola = "";

        public BotonCola(InfoServicio info) {
            super();
            this.info = info;
            cola = info.cola;
            addActionListener(botonPulsado);
        }
    }

    class BotonMenu extends BotonServicio {

        String[] textos;
        String nombrePanel;
        PanelBotones miPanel;
        SubMenu miMenu;

        public BotonMenu(SubMenu menu) {
            super();
            textos = new String[Global.gestorIdiomas.numeroIdiomas];
            nombrePanel = Global.limpiaHtml(menu.nombre);
            info = new InfoServicio(nombrePanel);
            for (int i = 0; i < textos.length; i++) {
                setDescripcion(menu.nombres[i], i);
            }
            miMenu = menu;
            miPanel = menu.paneles[0];
            addActionListener(menuPulsado);
        }

        public String subPanel() {
            return textos[Global.gestorIdiomas.idiomaActivo()];
        }

        public void setDescripcion(String texto, int idioma) {
            textos[idioma] = Global.limpiaHtml(texto);
            String desc;
            if (texto.toLowerCase().startsWith("<html>")) {
                desc = texto;
            } else {
                desc = "<html><center>" + texto + "  \u25ba</center></html>";
            }
            info.setDescripcion(desc, idioma);
        }

        @Override
        public void cambiaTexto() {
            super.cambiaTexto();
            for (PanelBotones panel : miMenu.paneles) {
                panel.cambiaTitulo(textos[Global.gestorIdiomas.idiomaActivo()]);
            }
        }
    }

    class BotonIdioma extends gestor.utiles.MiBoton {

        int idioma;

        public BotonIdioma(String texto, int numIdioma, Font fuente) {
            setFont(fuente);
            setPreferredSize(dimBotonIdioma);
            setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
            setText(arreglaTexto(texto));
            setForeground(Color.BLUE);
            setFocusable(false);
            setOpaque(false);
            if (Global.gestorIdiomas.banderas[numIdioma] != null) {
                setIcon(Global.gestorIdiomas.banderas[numIdioma]);
            }
            idioma = numIdioma;
            addActionListener(new java.awt.event.ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    Global.mainForm.resetSalvaPantalla();
                    cambiarIdioma(idioma);
                }
            });
        }

        String arreglaTexto(String txt) {
            return txt.substring(0, 1).toUpperCase() + txt.substring(1).toLowerCase();
        }
    }
}
