// 
// 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.
// 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using ateneo.utiles;
using ateneo;
using System.Reflection;
using System.Diagnostics;
using operador;

namespace operador
{
    public enum ESTADO_OPERADOR
    {
        PREVIO = 0,
        CONECTADO = 1,
        LIBRE = 2,
        ESPERANDO = 3,
        TRABAJANDO = 4,
        DESCANSANDO = 5,
        RECONECTANDO = 6,
        NO_RECUPERAR = -1
    }

    public partial class Principal : Form
    {
        Cargador cargador;
        public Comunicaciones comm;
        bool modoSinGestor = false;
        bool reenvioActivado = false;
        bool reenvioCondicionado = false;
        bool vinculacion = false;
        public ESTADO_OPERADOR estadoActual;
        ESTADO_OPERADOR estadoGuardado;
        ESTADO_OPERADOR estadoRecuperado = ESTADO_OPERADOR.NO_RECUPERAR;
        private ProcesoCliente cliente = null;

        Configuracion conf;
        private ColeccionColas colas = new ColeccionColas();
        public TablaCategoriasEstadisticas catEstadisticas = new TablaCategoriasEstadisticas();
        public string listaFavoritasCatEstadisticas = "";
        public static Principal yo;
        bool navegacionDisponible = false;
        bool pedirUsuario = false;
        private string idReenvio = null;
        private string idConTiket = null;
        private string segundaCola = null;
        private string ticketParaReenviar = null;
        private List<string> lista = new List<string>();
        private string ficheroRecuperacion = "recuperacionCitaActual.txt";
        Thread hiloStayAlive = null;
        System.Threading.Timer timerConexion;
        public string version = "operador.net";
        int ancho = 525;
        int altoMinimo = 190;
        int margenVentana = 10;
        const int altoFilaGrid = 18;
        Parametros parametros;
        bool cierreIrreversible = false;
        InvocadorMiniGestor miniGestor = null;
        bool miniGestorVisible = true;
        public string motivoIntranet = "Ateneo";

        bool usarAutoEnvioColaCero = true;
        public string colaCero = "";
        public bool nifColaCero = false;
        public int minutosCitaLarga = 0;
        ToolTip tooltip = new ToolTip();
        private bool ordenDeCierre = false;
        int fallidosBoton = 0;
        String huecoPedido = "";
        string appPath = "";
        FormReenvio fReenvio = null;
        String mesa = "";
        private int AvisoSegundaCola = 0;
        FormAvisoCitaLarga facl = null;


        public Principal(string[] args) {
            yo = this;
            parametros = new Parametros(args);
            conf = Configuracion.instanciaUnica();
            conf.cargar();
            comprobarArgs();
            if (conf.pedirUsuario == true) {
                pedirUsuario = true;
            }
            version = leerFechaEjecutable();
            InitializeComponent();
            comm = new Comunicaciones(this);
            comm.operador = "";
            comm.mesa = conf.numeroMesa;
            ponerEstado(ESTADO_OPERADOR.PREVIO);
            this.Text += " Vers. " + leerFechaEjecutable() + " - MESA " + conf.numeroMesa;
            timerEsperaCliente.Interval = conf.tiempoEspera * 1000;
            // timerConfirmarDescanso.Interval = conf.tiempoNoOperativo * 1000;
            minutosCitaLarga = (int)(conf.minutosCitaLarga);
            //  timerCitaLarga.Interval = (int)(conf.minutosCitaLarga * 60000);
            ancho = this.Width;
            preparaVisualizacion();
            if (parametros.contiene("conservarEstado")) {
                estadoRecuperado = (ESTADO_OPERADOR)Int32.Parse(parametros.valor("conservarEstado"));
                parametros.elimina("conservarEstado");
                ponerEstadoBotones(ESTADO_OPERADOR.NO_RECUPERAR);
            }
            fallidosBoton = 0;
            tooltip.BackColor = Color.Yellow;
            tooltip.SetToolTip(btEstadoColas, "Mostrar numero de presentes en las colas atendidas por este operador");
            tooltip.SetToolTip(btAutoEnviar, "Emitir y poner presente en esta mesa Tique de cola 0");
            tooltip.SetToolTip(btMiniGestor, "Conmutar la visibilidad del MiniGestor");
            tooltip.SetToolTip(btGrabarNota, "Grabar nota de esta cita");
        }

        String leerFechaEjecutable() {
            try {
                string archivo = System.Reflection.Assembly.GetExecutingAssembly().Location;
                return File.GetLastWriteTime(archivo).ToString();
            } catch (Exception) {
                return "";
            }
        }

        public ProcesoCliente clienteActual {
            get {
                return cliente;
            }
        }

        public void comprobarArgs() {
            if (parametros.contiene("usuario")) {
                pedirUsuario = true;
                return;
            }
            if (parametros.contieneNoNulo("u")) {
                conf.operador = parametros.valor("u");
            }
            if (parametros.contiene("passwordIntranet")) {
                conf.modoPrueba = true;
                conf.passwordIntranet = parametros.valor("passwordIntranet");
            }
        }

        public bool requiereCargador() {
            return !parametros.contiene("ejecutarsindescargar");
        }

        public void ejecutarCargador() {
            ConfiguracionCargador confCarg = new ConfiguracionCargador();
            confCarg.ipServidor = conf.ipServidor;
            confCarg.ipPort = conf.puerto;
            confCarg.ipServidorSec = conf.ipServidorSec;
            confCarg.ipPortSec = conf.puertoSec;
            confCarg.usandoUDP = conf.usandoUDP;
            confCarg.nombreServidor = conf.nombreServidor;
            cargador = new Cargador(confCarg, "operador");
            if (cargador.lanzar(parametros.ToString()) == DialogResult.Cancel) {
                Application.Run(this);
            }
        }

        void preparaVisualizacion() {
            margenVentana = SystemInformation.Border3DSize.Width * 2 + 2;
            // correcion para Windows Vista
            string version = Environment.OSVersion.VersionString.ToLower();
            if (version.Contains("nt 6.") || version.Contains("vista")) {
                margenVentana += 10;
                ancho += 10;
            }
            altoMinimo = grid.Top + SystemInformation.CaptionHeight + margenVentana;
            preparaGrid();
            this.Size = new Size(ancho, altoMinimo);
            this.StartPosition = FormStartPosition.CenterScreen;
        }

        void preparaGrid() {
            grid.Size = new Size(ancho - margenVentana, 10);
            grid.Columns[0].Width = grid.Width / 4;
            grid.Columns[1].Width = grid.Width / 2;
            grid.Columns[2].Width = grid.Width / 4;
            grid.ScrollBars = ScrollBars.None;
        }

        private void ajustarVisualizacion(int numFilas) {
            int alto;
            try {
                if (numFilas == 0) {
                    grid.Size = new Size(ancho - margenVentana, 0);
                    alto = altoMinimo;
                } else {
                    int altoGrid = altoFilaGrid * numFilas + 1;
                    grid.Size = new Size(ancho - margenVentana, altoGrid);
                    alto = altoMinimo + altoGrid + margenVentana / 2;
                }
                this.Size = new Size(ancho, alto);
            } catch (Exception ex) {
                LogExcepcion.guardar("Error en VentanaPrincipal.ajustarVisualizacion", ex);
            }
        }

        void inicia() {
            inicia(ESTADO_OPERADOR.PREVIO);
            int tiempoApagado = 1 * 60 * 1000;
            timerConexion = new System.Threading.Timer(new System.Threading.TimerCallback(tickTimerConexion), null, tiempoApagado, Timeout.Infinite);
        }

        private void tickTimerConexion(object state) {
            if (estadoActual == ESTADO_OPERADOR.PREVIO || estadoActual == ESTADO_OPERADOR.CONECTADO) {
                muerteSubita();
            }
            timerConexion.Dispose();
        }

        void muerteSubita() {
            pararStayAlive();
            cierreIrreversible = true;
            Application.Exit();
        }

        void inicia(ESTADO_OPERADOR estadoInicio) {
            comprobarDirectoriosYFicheros();
            if (comm.conectar()) {
                ponMensaje("Conectado al servidor en " + comm.host);
                identificaOperador();
                comm.solicitarConexion(estadoInicio);
                arrancarStayAlive();
                btConectar.Enabled = false;
                if (File.Exists(ficheroRecuperacion)) {
                    return;
                }
                //FAnuncio anuncio = new FAnuncio();
                //anuncio.ShowDialog();
                //anuncio.Dispose();
                //anuncio = null;
            } else {
                if (hiloStayAlive != null) {
                    pararStayAlive();
                }
                cierreIrreversible = true;
                MessageBox.Show("Error al conectar con el servidor en " + comm.host);
                Close();
            }
        }

        void ajustarModosEspeciales(string modo) {
            reenvioCondicionado = false;
            modoSinGestor = false;
            reenvioActivado = true;
            usarAutoEnvioColaCero = false;
            if (modo == "singestor") {
                modoSinGestor = true;
                reenvioActivado = false;
            } else if (modo == "colacero") {
                usarAutoEnvioColaCero = true;

            } else if (modo == "singestorcolacero") {
                modoSinGestor = true;
                reenvioActivado = false;
                usarAutoEnvioColaCero = true;
            }
        }

        internal void conexionAceptada(string msg) {
            colaCero = "";
            string[] pp = msg.Split('|');
            if (pp.Length > 6 && (pp[6] != null && pp[6].Length > 0)) {
                colaCero = pp[6].ToUpper();
            }
            if (pp.Length > 7 && (pp[7] != null && pp[7] == "0")) {
                conf.permitirNoiden = false;
            }

            ajustarModosEspeciales(pp[1].ToLower());
            ESTADO_OPERADOR nuevoEstado = (ESTADO_OPERADOR)Int32.Parse(pp[2]);
            ponerEstado(nuevoEstado);
            ponMensaje("Conexión creada por " + pp[0]);
            conf.nombreOperador = pp[0];
            btEstadoColas.Enabled = true;

            //if (conf.navegarIntranet) {
            //    comm.enviarEstadoNavegacion(true);
            //    if (estadoGuardado <= ESTADO_OPERADOR.LIBRE || estadoRecuperado > ESTADO_OPERADOR.NO_RECUPERAR) {
            //        IEControl.matarProcesosIExplorer(true);
            //        navegacionInicial(40000);
            //    }
            //} else {
            //    comm.enviarEstadoNavegacion(false);
            //}
            if (pp.Length > 3 && pp[3] == "0") {
                pararTemporizadores();
            }
            if (pp.Length > 4) {
                conf.nombreOficina = pp[4];
            }
            if (pp.Length > 5 && (pp[5] != null && pp[5].Length > 0)) {
                listaFavoritasCatEstadisticas = pp[5].Trim();
                if (catEstadisticas.completa) {
                    catEstadisticas.cargaFavoritas(listaFavoritasCatEstadisticas);
                }
            }
            if (usarAutoEnvioColaCero == false) {
                btAutoEnviar.Visible = false;
            }

            if (modoSinGestor) {
                btMiniGestor.Visible = true;
                arrancarGestor();
                pulsadoLibre();
            }

        }

        private void prepararAutoEnvioColaCero() {
            try {
                if (colaCero == null || colaCero == "") {
                    colaCero = "";
                    usarAutoEnvioColaCero = false;
                    return;
                }
                ColeccionColas.Registro reg = colas.buscarColaCero(colaCero);
                if (reg != null) {
                    //   colaCero = reg.cola;
                    nifColaCero = reg.nifObligatorio;
                    btAutoEnviar.Visible = true;
                } else {
                    colaCero = "";
                    usarAutoEnvioColaCero = false;
                }
            } catch (Exception e) {
                MessageBox.Show("Error al preparar ColaCero");
            }
        }

        private void comprobarDirectoriosYFicheros() {
            try {
                appPath = Path.GetDirectoryName(Application.ExecutablePath);
                string pathNotas = appPath + "\\Notas\\";
                if (!Directory.Exists(pathNotas)) {
                    Directory.CreateDirectory(pathNotas);
                }

                string pathProductos = appPath + "\\Productos\\";
                if (!Directory.Exists(pathProductos)) {
                    Directory.CreateDirectory(pathProductos);
                }
                string scriptsPath = appPath + "\\Scripts\\";
                if (!Directory.Exists(scriptsPath)) {
                    Directory.CreateDirectory(scriptsPath);
                }

            } catch (Exception) { }
        }

        private void identificaOperador() {
            string codUsuario = Environment.UserName;
            if (pedirUsuario) {
                conf.operador = Microsoft.VisualBasic.Interaction.InputBox("Introduzca identificador de Red para Ateneo", "Logon actual: " + codUsuario, codUsuario, -1, -1);
            }
            if (conf.operador == null || conf.operador == "") {
                conf.operador = codUsuario.Substring(0, Math.Min(12, codUsuario.Length));
            }
            conf.operador = conf.operador.ToUpper();
            if (conf.operador != null) {
                comm.mesa = conf.numeroMesa;
                comm.operador = conf.operador;
            }
        }

        bool venimosDeReleer = false;

        internal void iniciarRecepcionColas() {
            colas.marcarTodasNoActualizadas();
            venimosDeReleer = true;
        }

        internal void recibidoRegistroDeColas(string msg) {
            if (msg != "FIN_REGISTROS") {
                colas.add(msg);
            } else { // hemos recibido todas las colas, se puede recuperar estado si es el caso...
                if (venimosDeReleer) {
                    colas.borrarNoActualizadas();
                } else {
                    // recuperarConNavegacionDisponible = true;
                    if (navegacionDisponible || !conf.navegarIntranet) { // terminó antes NavegacionInicial que este método!
                        procesosDeRecuperacion();
                        //   recuperarConNavegacionDisponible = false;
                    }
                    if (usarAutoEnvioColaCero) {
                        prepararAutoEnvioColaCero();
                    }
                }
                venimosDeReleer = false;
            }
        }

        internal void recibidaCategoriaEstadistica(string msg) {
            if (msg != "FIN_REGISTROS") {
                catEstadisticas.nuevoRegistro(msg);
            } else {
                catEstadisticas.cargaFavoritas(listaFavoritasCatEstadisticas);
                catEstadisticas.completa = true;
            }
        }

        private void procesosDeRecuperacion() {
            if (estadoRecuperado == ESTADO_OPERADOR.NO_RECUPERAR) {
                // tratamos de recuperar una cita incorrectamente abortada
                if (File.Exists(ficheroRecuperacion)) {
                    if (esFicheroDeRecuperacionDeHoy()) {
                        recuperarCitaAbortada();
                    } else {
                        eliminarFicheroEstadoCliente();
                    }
                }
            } else {
                recuperarEstadoCliente();
            }
        }

        void reenvio(string colasValidas) {
            if (idConTiket == null || idConTiket == "") {
                MessageBox.Show("No es posible el reenvio");
                return;
            }
            if (cliente.ticket.Length < 3) {
                MessageBox.Show("No es posible el reenvio no hay No hay tique");
                return;

            }
            fReenvio = new FormReenvio(colas, cliente.ticket, cliente.colaActual.cola, segundaCola, colasValidas);
            if (fReenvio.ShowDialog() == DialogResult.OK) {
                if (fReenvio.colaSeleccionada.Trim() == "") {
                    reponerHueco();
                    mesa = "";
                    ticketParaReenviar = null;
                    AvisoSegundaCola = 0;
                } else {
                    string colaDestino = fReenvio.colaSeleccionada;
                    ticketParaReenviar = colaDestino + "|" + idConTiket;
                    mesa = fReenvio.mesa;
                    comprobarSihayHuecos(colas.get(colaDestino));
                    comprobarSalasEspera(cliente.colaActual, colas.get(colaDestino));
                    AvisoSegundaCola = 0;
                }
            }
            fReenvio.Dispose();
            fReenvio = null;
        }

        void reponerHueco() {
            if (huecoPedido != "") {
                comm.enviar(COD_ENVIADO.REPONER_HUECO, huecoPedido);
                huecoPedido = "";
                Application.DoEvents();
            }
        }

        void comprobarSihayHuecos(ColeccionColas.Registro colaDestino) {
            if (colaDestino.citaPrevia) {
                if (huecoPedido.StartsWith(colaDestino.cola + "|")) return;
                if (huecoPedido != "") {
                    MessageBox.Show("recuperar hueco" + huecoPedido);
                    reponerHueco();

                }
                comm.enviar(COD_ENVIADO.SOLICITO_HUECO, colaDestino.cola);
                return;

            }
            if (huecoPedido != "") {
                reponerHueco();
            }
        }

        internal void huecoAceptado(string msg) {
            huecoPedido = msg;
        }

        internal void huecoDenegado(string msg) {
            huecoPedido = "";
            if (!colas.get(msg).huecosOpe) {
                MessageBox.Show("Esta cola funciona con Huecos\nNO HAY HUECOS DISPONIBLES\n\nSE ANULA EL REENVIO\n\nContactar con el Administrador");
                ticketParaReenviar = null;
                return;
            }
            string mensaje = "Esta cola funciona con Huecos\nNO HAY HUECOS DISPONIBLES\n\nCONTINUAR CON EL REENVIO  ???";
            string caption = "Cola con HUECOS";
            MessageBoxButtons botones = MessageBoxButtons.YesNo;
            DialogResult resul = MessageBox.Show(mensaje, caption, botones);
            if (resul != DialogResult.Yes) {
                MessageBox.Show("SE ANULA EL REENVIO");
                ticketParaReenviar = null;
                return;
            }
        }

        private void comprobarSalasEspera(ColeccionColas.Registro colaActual, ColeccionColas.Registro colaDestino) {
            if (ticketParaReenviar == null) return; ;
            if (colaActual.salaEspera == null || colaDestino.salaEspera == null) {
                return;
            }
            if (colaActual.salaEspera != colaDestino.salaEspera && colaDestino.salaEspera.Trim().Length > 0) {
                string texto = "Advierta al contribuyente que debe dirigirse a la sala de espera" +
                        "- " + colaDestino.salaEspera;
                MessageBox.Show(texto, "* ATENCIÓN * ATENCIÓN * ATENCIÓN * ATENCIÓN *", MessageBoxButtons.OK,
                    MessageBoxIcon.Warning);
            }
        }

        private bool esFicheroDeRecuperacionDeHoy() {
            DateTime fecha = File.GetLastWriteTime(ficheroRecuperacion);
            return fecha.DayOfYear == DateTime.Now.DayOfYear;
        }

        private void recuperarCitaAbortada() {
            string[] reg = obtenerIdRegistroRecuperado();
            if (reg != null) {
                beep();
                if (MessageBox.Show("No se concluyó la cita de\n" +
                        reg[0] + " - " + reg[1] +
                        "\n¿ Quiere recuperarla ?",
                        "** ATENCIÓN : CITA NO FINALIZADA **",
                        MessageBoxButtons.YesNo) == DialogResult.Yes) {
                    estadoRecuperado = ESTADO_OPERADOR.TRABAJANDO;
                    procesoRecuperacionCitas();
                    if (cliente.ticket.Length > 2) {
                        idConTiket = cliente.Id;
                    }
                    return;
                }
            }
            eliminarFicheroEstadoCliente();
        }

        private string[] obtenerIdRegistroRecuperado() {
            StreamReader lector = new StreamReader(ficheroRecuperacion, Encoding.Default);
            string linea = lector.ReadLine();
            lector.Close();
            if (linea != null) {
                return linea.Split('|');
            }
            return null;
        }

        private void recuperarEstadoCliente() {
            ponerEstado((ESTADO_OPERADOR)estadoRecuperado);
            if (estadoRecuperado == ESTADO_OPERADOR.DESCANSANDO) {
                pulsadoDescanso();
            } else if (estadoRecuperado == ESTADO_OPERADOR.TRABAJANDO || estadoRecuperado == ESTADO_OPERADOR.ESPERANDO) {
                procesoRecuperacionCitas();
            }
        }

        private void procesoRecuperacionCitas() {
            string msgCliente = null;
            try {
                if (!File.Exists(ficheroRecuperacion)) {
                    return;
                }
                using (StreamReader lector = new StreamReader(ficheroRecuperacion, Encoding.Default)) {
                    string linea = lector.ReadLine();
                    if (linea != null) {
                        recibirCliente(linea, false);
                        msgCliente = linea;
                    }
                    lista.Clear();
                    while ((linea = lector.ReadLine()) != null) {
                        recibirVinculado(linea);
                    }
                }
                if (msgCliente != null) {
                    if (estadoRecuperado == ESTADO_OPERADOR.TRABAJANDO) {
                        pulsadoInicio();
                    }
                }
            } catch (Exception exc) {
                LogExcepcion.guardar("No se pudo recuperar estado\n" + msgCliente, exc);
            }
        }


        private void btMiniGestor_Click(object sender, EventArgs e) {
            if (miniGestor != null) {
                miniGestorVisible = !miniGestorVisible;
                miniGestor.cambiarVisibilidad(miniGestorVisible);
                if (miniGestorVisible) {
                    btMiniGestor.ImageKey = "miniGestorVisible";
                } else {
                    btMiniGestor.ImageKey = "miniGestorNoVisible";
                }
            }
        }

        private void arrancarGestor() {
            if (parametros.contiene("ejecutarSinDescargar") && !parametros.contiene("actualizarMiniGestor")) {
                lanzaGestor();
                return;
            }
            try {
                ConfiguracionCargador confCarg = new ConfiguracionCargador();
                confCarg.ipServidor = comm.host;
                confCarg.ipPort = comm.puerto;
                confCarg.ipServidorSec = conf.ipServidorSec;
                confCarg.ipPortSec = conf.puertoSec;
                confCarg.usandoUDP = conf.usandoUDP;
                confCarg.nombreServidor = conf.nombreServidor;
                Thread.Sleep(2000);
                cargador = new Cargador(confCarg, "minigestor");
                cargador.lanzar("");
                Thread.Sleep(2000);
                lanzaGestor();
            } catch (Exception exc) {
                LogExcepcion.guardar("ERROR AL CARGAR MINIGESTOR", exc);
            }
        }
        //Type tipoMiniGestor;
        //Object objetoMiniGestor = null;

        private void lanzaGestor() {
            try {
                if (miniGestor == null) {
                    miniGestor = new InvocadorMiniGestor();
                }
                miniGestor.lanzar();
            } catch { }
        }

        public void pararTemporizadores() {
            pararStayAlive();
            timerConfirmarDescanso.Stop();
        }

        //private void navegacionInicial(int timeout) {
        //    btNoNavegar.Enabled = true;
        //    ieControl = arrancarIE();
        //    if (ieControl == null) {
        //        return;
        //    }
        //    if (!conf.modoPrueba) {
        //        ieControl.cargarPagina("https://probdc2.www.aeat/ES98/L/GEN1GENPRO10", "about:home", timeout);
        //    } else {
        //        ieControl.cargarPagina("https://probdc2.www.aeat/ES98/L/GEN1GENPRO10",
        //                "https://probdc2.www.aeat/ES98/L/GEN1GENPRO10", 15000);
        //        IEDocument doc = ieControl.documento;
        //        doc.setCampoForm("Logon", "password", conf.passwordIntranet, "motiv", "depAteneo");
        //        doc.clickBoton("Logon", "Aceptar");
        //    }
        //    if (recuperarConNavegacionDisponible) {
        //        procesosDeRecuperacion();
        //        recuperarConNavegacionDisponible = false;
        //    }
        //    navegacionDisponible = true;
        //    motivoIntranet = ieControl.documento.motivo().Trim();

        //    if (motivoIntranet.Length < 3) motivoIntranet = "Ateneo";
        //    traerAlFrente();
        //}

        //private IEControl arrancarIE() {
        //    IEControl ieControlLocal = new IEControl();
        //    if (!ieControlLocal.OK) {
        //        Thread.Sleep(100);
        //        ieControlLocal = new IEControl();
        //        if (!ieControlLocal.OK) {
        //            return null;
        //        }
        //    }
        //    ieControlLocal.processId = Win32Apis.obtenerPidVentana(ieControlLocal.HWND);
        //    ieControlLocal.OnIeCerrando += new IECerrandoHandler(IeCerrando);
        //    ieControlLocal.OnIeCerrado += new IECerradoHandler(IeCerrado);
        //    return ieControlLocal;

        //}

        void salirDelTodo() {
            salirDelTodo(false);
        }

        void salirDelTodo(bool conReinicio) {
            //if (conf.navegarIntranet) {
            //    try {
            //        ieControl.desconectarOnQuit();
            //        ieControl.cerrar();
            //    } catch (Exception) { }
            //}
            cerrarMiniGestor();
            comm.desconectar();
            if (conReinicio) {
                Cargador.reiniciaCliente((int)estadoActual, "Operador.exe", parametros.ToString2());
            }

        }

        public void cerrarMiniGestor() {
            if (miniGestor != null) {
                miniGestor.cerrar();
            }
        }

        //void IeCerrando() {
        //    ieControlTemp = arrancarIE();
        //}

        //void IeCerrado(IEControl sender) {
        //    ieControl = ieControlTemp;
        //}

        //public void pararNavegacion() {
        //    ieControl.stop();
        //}

        //void commutarNavegacion() {
        //    if (conf.navegarIntranet) {
        //        if (conf.logNavegacion) LogExcepcion.guardarConmutarNavegacion(comm.operador + " ha pulsado NO NAVEGAR");
        //        try {
        //            ieControl.desconectarOnQuit();
        //            ieControl.cerrar();
        //        } catch (Exception ex) {
        //            LogExcepcion.guardar("Error en conmutarNavegacion", ex);
        //        }
        //        ieControl = null;
        //        ponerIconoNavegar();
        //        comm.enviarEstadoNavegacion(false);
        //    } else {
        //        if (conf.logNavegacion) LogExcepcion.guardarConmutarNavegacion(comm.operador + " ha pulsado VOLVER A NAVEGAR");
        //        IEControl.matarProcesosIExplorer(true);
        //        ponerIconoNoNavegar();
        //        comm.enviarEstadoNavegacion(true);
        //        navegacionInicial(40000);
        //    }
        //    conf.navegarIntranet = !conf.navegarIntranet;
        //    if (cliente != null && conf.navegarIntranet) {
        //        btRepetirNavegacion.Enabled = true;
        //        btNavegarConyuge.Enabled = cliente.hayConyuge();
        //    }
        //}

        //private void ponerIconoNoNavegar() {
        //    btNoNavegar.ImageKey = "PararExploracion";
        //}

        //private void ponerIconoNavegar() {
        //    btNoNavegar.ImageKey = "Explorar";
        //}

        private void ponerEstado(ESTADO_OPERADOR estado) {
            estadoActual = estado;
            ponerEstadoBotones(estado);
            if (estado == ESTADO_OPERADOR.ESPERANDO) {
                timerEsperaCliente.Start();
            }
            if (vinculacion) {
                ponerModoVinculado();
            }
            if (estado == ESTADO_OPERADOR.LIBRE ||
                estado == ESTADO_OPERADOR.DESCANSANDO) {
                cliente = null;
                //btRepetirNavegacion.Enabled = false;
                //btNavegarConyuge.Enabled = false;
            }
        }

        private void ponerModoVinculado() {
            cambiarFinalizar(false);
            foreach (string s in lista) {
                string[] ss = s.Split('|');
                string[] datos = new string[] { ss[0], ss[1], "SIGUIENTE" };
                int fila = grid.Rows.Add(datos);
                grid.Rows[fila].Height = altoFilaGrid;
            }
            ajustarVisualizacion(lista.Count);
        }

        internal void msgMesaYaConectada() {
            errorBox("Error en identificación de mesa.\nRevise su configuración");
            Application.Exit();
        }

        public void ponMensaje(string txt) {
            txt = txt.Replace("#", "\r\n");
            mensajes.Text = txt;
            mensajes.SelectionLength = 0;
            mensajes.SelectionStart = 0;
        }

        //public bool cargarPagina(string paginaDestino, string pagEsperada) {
        //    ieControl.cargarPagina(paginaDestino, pagEsperada, 20000);
        //    traerAlFrente();
        //    return ieControl.estadoNav == ESTADO_NAVEGADOR.TERMINADA;
        //}

        private void btIniciar_Click(object sender, EventArgs e) {
            pulsadoInicio();
        }

        private void btFinalizar_Click(object sender, EventArgs e) {
            pulsadoFinalizar(-1);
        }

        private void btLibre_Click(object sender, EventArgs e) {
            pulsadoLibre();
        }

        private void btDdescanso_Click(object sender, EventArgs e) {
            pulsadoDescanso();
        }

        void ponerEstadoBotones(ESTADO_OPERADOR estado) {
            btIniciar.Enabled = false;
            btFinalizar.Enabled = false;
            btLibre.Enabled = false;
            btDescanso.Enabled = false;
            btReenvio.Enabled = false;
            btGrabarNota.Enabled = false;
            switch (estado) {
                case ESTADO_OPERADOR.LIBRE:
                    btDescanso.Enabled = true;
                    break;
                case ESTADO_OPERADOR.CONECTADO:
                    btLibre.Enabled = true;
                    btDescanso.Enabled = true;
                    break;
                case ESTADO_OPERADOR.ESPERANDO:
                    btIniciar.Enabled = true;
                    break;
                case ESTADO_OPERADOR.TRABAJANDO:
                    btFinalizar.Enabled = true;
                    btDescanso.Enabled = true;
                    btGrabarNota.Enabled = true;
                    activaReenvio();
                    break;
                case ESTADO_OPERADOR.DESCANSANDO:
                    btLibre.Enabled = true;
                    break;
                case ESTADO_OPERADOR.RECONECTANDO:
                    break;
            }
        }

        private void activaReenvio() {
            if (reenvioActivado && !reenvioCondicionado) {
                btReenvio.Enabled = true;
            }
        }

        bool procesarCerradoVentana() {
            if (estadoActual == ESTADO_OPERADOR.ESPERANDO) {
                timerEsperaCliente.Stop();      // por si sirve para algo...
                MessageBox.Show("Espere a que se active el boton 'NO DISPONIBLE' y vuelva a intentar el cierre");
                timerEsperaCliente.Start();     // a veces se queda como muerto...
                return false;
            }
            if (estadoActual == ESTADO_OPERADOR.TRABAJANDO) {
                MessageBox.Show("Antes debe pulsar 'Finalizar'");
                return false;
            }
            if (MessageBox.Show("¿ Realmente quiere cerrar el programa? ", "ADVERTENCIA",
                MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No) {
                return false;
            }
            pararStayAlive();
            try {
                switch (estadoActual) {
                    case ESTADO_OPERADOR.DESCANSANDO:
                        pulsadoLibre();
                        break;

                    case ESTADO_OPERADOR.LIBRE:
                        pulsadoDescanso();
                        break;
                }
            } catch (Exception) { }
            return true;
        }


        private void btConectar_Click(object sender, EventArgs e) {
            pulsadoConectar();
        }

        private void pulsadoConectar() {
            identificaOperador();
            comm.solicitarConexion(ESTADO_OPERADOR.PREVIO);
            btConectar.Enabled = false;
        }

        private void btMensaje_Click(object sender, EventArgs e) {
            FormMensaje fm = new FormMensaje();
            if (fm.ShowDialog() == DialogResult.OK) {
                comm.enviar(fm.destino, fm.mensaje);
            }
        }

        //private void btRepetirNavegacion_Click(object sender, EventArgs e) {
        //    if (cliente != null) {
        //        cliente.navegar();
        //    }
        //}

        //private void btNoNavegar_Click(object sender, EventArgs e) {
        //    commutarNavegacion();
        //}

        private void Principal_FormClosing(object sender, FormClosingEventArgs e) {
            if (ordenDeCierre) return;
            if (!cierreIrreversible) {
                if (!procesarCerradoVentana()) {
                    e.Cancel = true;
                    return;
                }
            }
            salirDelTodo();
        }

        internal void procesoFinalizacionCliente() {
            string[] ficheros = Directory.GetFiles(appPath + "\\Productos", "*.ope");
            foreach (string f in ficheros) {
                try {
                    StringBuilder sb = new StringBuilder();
                    StreamReader sr = new StreamReader(f);
                    string linea;
                    while ((linea = sr.ReadLine()) != null) {
                        sb.Append(linea).Append("#");
                    }
                    if (sb.Length > 0) {
                        sb.Length = sb.Length - 1;
                    }
                    sr.Close();
                    string producto = nombreSinExtension(f);
                    comm.enviar(COD_ENVIADO.ENVIO_REG_PRODUCTOS, cliente.nif, producto, sb.ToString());
                } catch (Exception ex) {
                    LogExcepcion.guardar("Error enviando datos de cita", ex);
                }
                File.Delete(f);
            }
            if (File.Exists(appPath + "\\Notas\\Nota.rtf")) {
                try {
                    StringBuilder sb = new StringBuilder();
                    StreamReader sr = new StreamReader(appPath + "\\Notas\\Nota.rtf");
                    string linea;
                    while ((linea = sr.ReadLine()) != null) {
                        // sb.Append(linea).Append("#");
                        sb.Append(linea);
                    }
                    sr.Close();
                    if (sb.Length < 130) {
                        return;
                    }

                    comm.enviar(COD_ENVIADO.ENVIO_NOTA, cliente.Id, sb.ToString());
                } catch (Exception ex) {
                    LogExcepcion.guardar("Error enviando datos de cita", ex);
                }
                //  File.Delete(f);
            }

            btAutoEnviar.Enabled = true;
        }

        private string nombreSinExtension(string f) {
            return Path.GetFileNameWithoutExtension(f);
        }

        internal bool quedanEnLista() {
            return lista.Count > 0;
        }

        internal void msgOperadorNoIdentificado() {
            errorBox(conf.operador + " no identificado por el servidor");
            btConectar.Enabled = true;
        }

        void errorBox(string msg) {
            MessageBox.Show(msg, "* ERROR *", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        internal void peticionDeCierre(string msg) {
            if (msg != "silencioso") {
                MessageBox.Show("El servidor ha enviado una petición de cierre.\n" + msg);
            }
            ordenDeCierre = true;
            salirDelTodo();
            Close();
        }

        internal void nuevoClienteNoVinculado(string msg) {
            try {
                idReenvio = null;
                string[] pars = msg.Split('|');
                idConTiket = pars[5];
                ticketParaReenviar = null;
                segundaCola = null;
                lista.Clear();
                grid.Rows.Clear();
                ajustarVisualizacion(0);
                vinculacion = false;
                AvisoSegundaCola = 0;
            } catch (Exception exc) {
                LogExcepcion.guardar("Excepcion en NuevoClienteNoVinculado", exc);
            }
        }

        internal void recibirCliente(string msg, bool limpiadoPrevio) {
            try {
                if (limpiadoPrevio) {
                    limpiarProductos();
                }
                cliente = ProcesoCliente.crearCliente(this, msg);
                if (cliente == null) {
                    MessageBox.Show("Se produjo un error al procesar el mensaje de Nuevo Cliente");
                    return;
                }
                if (conf.scriptInicio != null) {
                    ProgramaExterno.run(conf.scriptInicio, cliente.ticket, cliente.nif, cliente.apellido);
                }
                int reintentos = 2;
                while (reintentos > 0) {
                    try {
                        cliente.procesoInicial();
                        reintentos = 0;
                    } catch (Exception exc) {
                        LogExcepcion.guardar("Error en Recibir cliente", exc);
                        //if (conf.navegarIntranet) {
                        //    IEControl.matarProcesosIExplorer(false);
                        //    navegacionInicial(20000);
                        //    reintentos--;
                        //    if (reintentos == 0) {
                        //        abandonarNavegacion();
                        //    }
                        //}
                    }
                }
                //  navegadoAConyuge = false;
                //if (conf.navegarIntranet) {
                //    btRepetirNavegacion.Enabled = true;
                //    btNavegarConyuge.Enabled = cliente.hayConyuge();
                //}

                if (modoSinGestor || cliente.gestor == conf.operador) {
                    ponMensaje("Atendiendo a " + cliente);
                    comm.enviarCambioEstado(COD_ENVIADO.LIBRE_A_INICIO, idCliente());
                    pulsadoInicio();
                    btAutoEnviar.Enabled = false;
                } else {
                    ponMensaje("Esperando a " + cliente);
                    bool estadoVinculacion = vinculacion;
                    vinculacion = false;
                    ponerEstado(ESTADO_OPERADOR.ESPERANDO);
                    vinculacion = estadoVinculacion;
                }
            } catch (Exception e) {
                LogExcepcion.guardar("Error en recibirCliente. Mensaje:\n" + msg, e);
                vinculacion = false;
                ponMensaje("Esperando a " + msg);
                ponerEstado(ESTADO_OPERADOR.ESPERANDO);
                lista.Clear();
            }
            try {
                traerAlFrente();
                if (!modoSinGestor && !usarAutoEnvioColaCero) {
                    comm.enviarCambioEstado(COD_ENVIADO.LIBRE_A_INICIO, idCliente());
                }
            } catch (Exception exc) {
                LogExcepcion.guardar("Error en recibirCliente(final)", exc);
            }
        }

        string idCliente() {
            return (cliente == null ? " " : cliente.Id);
        }

        private void pulsadoInicio() {
            if (cliente == null) {
                return;
            }
            cliente.horaInicio = DateTime.Now;

            ponMensaje("Atendiendo a " + cliente);
            copiarEnPortapapeles(cliente.nif);
            crearFicheroTXT();

            timerEsperaCliente.Stop();
            if (conf.recordarFinalizar) {
                activarRecordarFinalizar();
            }
            comm.enviarCambioEstado(COD_ENVIADO.INICIO, idCliente());
            ponerEstado(ESTADO_OPERADOR.TRABAJANDO);
            if (idReenvio != null && AvisoSegundaCola == 1) {
                MessageBox.Show("Contribuyente con varias citas concertadas\nDebe recordarle la posibilidad de reenvio\nAntes de Finalizar la cita se volvera a mostrar", "AVISO");
                AvisoSegundaCola = 2;
            }
            if (conf.scriptInicio != null) {
                ProgramaExterno.run(conf.scriptInicio, cliente.ticket, cliente.nif, cliente.apellido);
            }
            timerCitaLarga.Interval = cliente.tiempoMedioCita;
            timerCitaLarga.Start();
        }

        bool comprobarSiReenviar() {
            if (lista.Count == 0 && idReenvio != null && AvisoSegundaCola == 2) {
                DialogResult resultado = MessageBox.Show("Reenviarlo antes de Finalizar  ??",
                    "Contribuyente con varias citas concertadas",
                    MessageBoxButtons.YesNoCancel,
                    MessageBoxIcon.Question,
                    MessageBoxDefaultButton.Button2);
                if (resultado == DialogResult.Yes) {
                    comm.enviar(COD_ENVIADO.SOLICITAR_ESTADO_COLAS);
                    AvisoSegundaCola = 0;
                    return true;
                } else {
                    idReenvio = null;
                    AvisoSegundaCola = 0;
                }
            }
            return false;

        }

        void pulsadoFinalizar(int fila) {
            if (comprobarSiReenviar()) return;
            timerAvisarFinalizar.Stop();
            timerCitaLarga.Stop();
            if (vinculacion) {
                if (estadoActual == ESTADO_OPERADOR.TRABAJANDO) {
                    finalizarConCodigo(COD_ENVIADO.TRABAJO_A_TRABAJO);
                }
                if (fila >= 0 && lista.Count > 0) {
                    string msg = lista[fila];
                    lista.RemoveAt(fila);
                    grid.Rows.RemoveAt(fila);
                    ajustarVisualizacion(lista.Count);
                    recibirCliente(msg, true);
                    crearFicheroEstadoCliente();
                    pulsadoInicio();
                    if (lista.Count == 0) {
                        cambiarFinalizar(true);
                        grid.Rows.Clear();
                    }
                } else {
                    comm.enviarCambioEstado(COD_ENVIADO.LIBRE, idCliente());
                    ponerEstado(ESTADO_OPERADOR.LIBRE);
                    vinculacion = false;
                    eliminarFicheroEstadoCliente();
                }
            } else {    // no es vinculacion
                if (finalizarConCodigo(COD_ENVIADO.TRABAJO_A_LIBRE)) {
                    ponerEstado(ESTADO_OPERADOR.LIBRE);

                }
                eliminarFicheroEstadoCliente();
                reenvioCondicionado = false;
            }
        }

        void pulsadoDescanso() {
            if (comprobarSiReenviar()) return;
            timerAvisarFinalizar.Stop();
            timerCitaLarga.Stop();
            if (vinculacion) {
                ajustarVisualizacion(lista.Count);
                if (noCancelar()) {
                    return;
                }
                interrumpirVinculacion();
                finalizarConCodigo(COD_ENVIADO.TRABAJO_A_TRABAJO);
                comm.enviarCambioEstado(COD_ENVIADO.LIBRE_A_DESCANSO, idCliente());
            } else {
                if (estadoActual == ESTADO_OPERADOR.TRABAJANDO) {
                    if (!finalizarConCodigo(COD_ENVIADO.TRABAJO_A_DESCANSO)) {
                        return;
                    }
                } else {
                    comm.enviarCambioEstado(COD_ENVIADO.LIBRE_A_DESCANSO, idCliente());
                    if (estadoActual == ESTADO_OPERADOR.ESPERANDO) {
                        try {
                            cliente.procesoFinalizacion(true);
                        } catch (Exception ex) {
                            LogExcepcion.guardar("Error en PulsadoDescanso", ex);
                        }
                    }
                }
            }
            ponMensaje("Estado NO DISPONIBLE");
            ponerEstado(ESTADO_OPERADOR.DESCANSANDO);
            eliminarFicheroEstadoCliente();
            timerConfirmarDescanso.Start();
            reenvioCondicionado = false;
            idReenvio = null;
        }

        void pulsadoLibre() {
            try {
                timerConfirmarDescanso.Stop();
                if (vinculacion) {
                    ajustarVisualizacion(lista.Count);
                    if (noCancelar()) {
                        return;
                    }
                    if (estadoActual == ESTADO_OPERADOR.TRABAJANDO) {
                        finalizarConCodigo(COD_ENVIADO.TRABAJO_A_TRABAJO);
                    }
                    interrumpirVinculacion();
                }
                timerEsperaCliente.Stop();
                if (estadoActual == ESTADO_OPERADOR.DESCANSANDO) {
                    comm.enviarCambioEstado(COD_ENVIADO.DESCANSO_A_LIBRE, idCliente());
                } else {
                    comm.enviar(COD_ENVIADO.LIBRE, "0");
                    if (estadoActual == ESTADO_OPERADOR.ESPERANDO) {
                        try {
                            cliente.procesoFinalizacion(true);
                        } catch (Exception ex) {
                            LogExcepcion.guardar("Error en PulsadoLibre", ex);
                        }
                    }
                }
                ponMensaje("Estado LIBRE");
                ponerEstado(ESTADO_OPERADOR.LIBRE);
            } catch (Exception exc) {
                LogExcepcion.guardar("Excepcion en PulsadoLibre", exc);
            }
        }

        private void interrumpirVinculacion() {
            lista.Clear();
            grid.Rows.Clear();
            ajustarVisualizacion(0);
            vinculacion = false;
        }

        private bool noCancelar() {
            if (lista.Count > 0) {
                DialogResult res = MessageBox.Show(
                    "Se trata de una cita vinculada y quedan citas por atender\n" +
                    "Pulse SI para continuar atendiéndolas pulsando SIGUIENTE\n" +
                    "Pulse NO para dejar el resto de citas como NO PRESENTES EN EL PUESTO",
                    "CITAS PENDIENTES",
                    MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                if (res == DialogResult.Yes || res == DialogResult.Cancel) {
                    return true;
                }
            }
            return false;
        }

        private void eliminarFicheroEstadoCliente() {
            if (File.Exists(ficheroRecuperacion)) {
                File.Delete(ficheroRecuperacion);
            }
        }

        private bool finalizarConCodigo(COD_ENVIADO codigo) {
            try {
                cliente.procesoFinalizacion(false);
            } catch (Exception ex) {
                LogExcepcion.guardar("Error en finalizarConCodigo cod:" + codigo.ToString(), ex);
            }
            comm.enviarFinalizacion(codigo, cliente.Id, cliente.getMensajeFinalizacion());
            ponMensaje("Estado actual: " + (codigo == COD_ENVIADO.TRABAJO_A_DESCANSO ? "NO DISPONIBLE" : "LIBRE"));
            if (ticketParaReenviar != null) {
                ejecutarReenvio();
            }
            if (conf.scriptFinal != null && codigo != COD_ENVIADO.TRABAJO_A_TRABAJO) {
                ProgramaExterno.run(conf.scriptFinal, cliente.ticket, cliente.nif, cliente.apellido, cliente.colaActual.cola);
            }
            return true;
        }

        private void ejecutarReenvio() {
            if (idReenvio != null && segundaCola != null && ticketParaReenviar.StartsWith(segundaCola)) {
                comm.enviar(COD_ENVIADO.REENVIO_SEGUNDA_COLA, cliente.ticket, idReenvio);
                ticketParaReenviar = null;
            } else {
                comm.enviar(COD_ENVIADO.REENVIO_COLA, ticketParaReenviar, mesa);
                ticketParaReenviar = null;
                idConTiket = null;
                mesa = "";
            }
            huecoPedido = "";
        }

        private void activarRecordarFinalizar() {
            int tm = cliente.colaActual.tiempoMedio;
            if (tm == 0) {
                return;
            }
            timerAvisarFinalizar.Interval = tm * 1500;
            timerAvisarFinalizar.Start();
        }

        private void crearFicheroTXT() {
            string ficheroDatos = appPath + "\\DatosCita.txt";
            try {
                using (StreamWriter sw =
                    new StreamWriter(ficheroDatos, false, Encoding.Default)) {
                    DateTime fecha = DateTime.Now;
                    sw.WriteLine("Nombre=" + cliente.apellido);
                    sw.WriteLine("Nif=" + cliente.nif);
                    sw.WriteLine("NifConyuge=" + cliente.nifConyuge);
                    sw.WriteLine("NombreConyuge=" + cliente.apeConyuge);
                    sw.WriteLine("UsuarioUnico=" + conf.operador);
                    sw.WriteLine("NombreOperador=" + conf.nombreOperador);
                    sw.WriteLine("Cola=" + cliente.colaActual.descripcion);
                    sw.WriteLine("LetraCola=" + cliente.colaActual.cola);
                    sw.WriteLine("Tique=" + cliente.ticket);
                    sw.WriteLine("FCita=" + Fecha.formatoFechaCorta(fecha));
                    sw.WriteLine("Hora=" + Fecha.formatoHoraHM(fecha));
                    sw.WriteLine("Mesa=" + conf.numeroMesa);
                    sw.WriteLine("NombreOficina=" + conf.nombreOficina);
                }
            } catch (IOException) {
                MessageBox.Show("No se pudo escribir en " + ficheroDatos + "\n¡ No se podrá emitir documentos !");
            }
        }

        private void copiarEnPortapapeles(string p) {
            try {
                Clipboard.SetText(p);
            } catch { }
        }

        //private void abandonarNavegacion() {
        //    conf.navegarIntranet = false;
        //    comm.enviarEstadoNavegacion(false);
        //    btNoNavegar.Enabled = false;
        //    btRepetirNavegacion.Enabled = false;
        //    btNavegarConyuge.Enabled = false;
        //    MessageBox.Show("Al no poder conectar con Internet Explorer se cancela la navegación");
        //}

        private void limpiarProductos() {
            string[] files = Directory.GetFiles(appPath + "\\Productos");
            foreach (string f in files) {
                File.Delete(f);
            }
            string[] files2 = Directory.GetFiles(appPath + "\\Notas");
            foreach (string f in files2) {
                File.Delete(f);
            }
        }

        internal void crearFicheroEstadoCliente() {
            using (StreamWriter sw = new StreamWriter(ficheroRecuperacion, false, Encoding.Default)) {
                sw.WriteLine(cliente.msgOriginal);
                if (lista.Count > 0) {
                    foreach (string s in lista) {
                        sw.WriteLine(s);
                    }
                }
            }
        }

        internal void recibirVinculado(string msg) {
            lista.Add(msg);
            vinculacion = true;
        }

        internal void cambiarFinalizar(bool activar) {
            btFinalizar.Enabled = activar;
            btLibre.Enabled = !activar;
        }

        private void grid_CellClick(object sender, DataGridViewCellEventArgs e) {
            if (e.ColumnIndex == 2) {
                pulsadoFinalizar(e.RowIndex);
            }
        }

        //private void btNavegarConyuge_Click(object sender, EventArgs e) {
        //    if (!navegadoAConyuge && MessageBox.Show(
        //        "   ¡¡ ATENCIÓN !!\n Pulsar cuando el contribuyente esté presente o actúe mediante representación",
        //        "CONFIRMACIÓN", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK) {
        //        return;
        //    }
        //    if (cliente != null) {
        //        cliente.navegarConyuge();
        //        navegadoAConyuge = true;
        //    }
        //}

        internal void mensajeRecibidodelAdministrador(string msg) {
            mensajeRecibido(msg, "Administrador");
        }

        internal void mensajeRecibidodelGestor(string msg) {
            mensajeRecibido(msg, "Gestor");
        }

        void mensajeRecibido(string msg, string nomOrigen) {
            string[] pars = msg.Split('|');
            string origen = pars[0];
            string texto = pars[1];
            traerAlFrente();
            MessageBox.Show(texto.Replace("#", "\n"), "Mensaje del " + nomOrigen, MessageBoxButtons.OK, MessageBoxIcon.Information);
            if (nomOrigen != "NoRetorno") {
                comm.enviar(COD_ENVIADO.MENSAJE_RECIBIDO, origen);
            }
        }

        internal void confirmaMensajeRecibido() {
            MessageBox.Show("EL MENSAJE HA SIDO RECIBIDO");
        }

        internal void recibirCuentaPendientes(string msg) {
            try {
                if (msg == "CerrarBoton") {
                    btEstadoColas.Enabled = false;
                    return;
                }
                if (msg == "") {
                    MessageBox.Show("No hay Presentes para las colas atendidas por este operador", "PRESENTES EN ESPERA");
                    return;
                }
                DlgEstadoColas dec = new DlgEstadoColas();
                dec.cargar(msg);
                dec.ShowDialog(this);
            } catch (Exception exc) {
                LogExcepcion.guardar("Error al recibir cuenta de pendientes", exc);
            }

        }

        internal void ejecutaScript(string msg) {
        }

        internal void prepararSegundasCitas(string msg) {
            string[] ss = msg.Split('|');
            idReenvio = ss[0];
            segundaCola = ss[1];
            AvisoSegundaCola = 1;
        }

        internal void reiniciarConEstado() {
            if (estadoActual == ESTADO_OPERADOR.TRABAJANDO || estadoActual == ESTADO_OPERADOR.ESPERANDO) {
                idReenvio = null;
                crearFicheroEstadoCliente();
            }
            parametros.elimina("conservarEstado");
            cierreIrreversible = true;
            salirDelTodo(true);
            Application.Exit();
        }

        private void timerEsperaCliente_Tick(object sender, EventArgs e) {
            if (estadoActual == ESTADO_OPERADOR.ESPERANDO) {
                btLibre.Enabled = true;
                btDescanso.Enabled = true;
                traerAlFrente();
                beep();
            } else {
                timerEsperaCliente.Stop();
            }
        }

        public void traerAlFrente() {
            if (this.WindowState == FormWindowState.Minimized) {
                this.WindowState = FormWindowState.Normal;
            }
            Win32Apis.bringToFront(this);
        }

        private void beep() {
            System.Media.SystemSounds.Beep.Play();
        }

        private void timerConfirmarDescanso_Tick(object sender, EventArgs e) {
            timerConfirmarDescanso.Stop();
            comm.enviar(COD_ENVIADO.CONFIRMAR_DESCANSO);
        }

        private void timerAvisarFinalizar_Tick(object sender, EventArgs e) {
            traerAlFrente();
            MessageBox.Show("Recuerde pulsar FINALIZAR al terminar con la cita en curso");
            timerAvisarFinalizar.Stop();
        }

        #region StayAlive

        private void arrancarStayAlive() {
            hiloStayAlive = new Thread(new ThreadStart(enviarEstoyVivo));
            hiloStayAlive.Name = "ALIVE";
            hiloStayAlive.Start();
        }

        void enviarEstoyVivo() {
            while (true) {
                comm.enviarEstoyVivo();
                Thread.Sleep(10000);
            }
        }

        void pararStayAlive() {
            if (hiloStayAlive != null) {
                hiloStayAlive.Abort();
            }
        }
        #endregion

        private void Principal_Shown(object sender, EventArgs e) {
            inicia();
        }

        internal void arrancarConfirmarDescanso() {
            timerConfirmarDescanso.Start();
        }

        internal ESTADO_OPERADOR reconexionRealizada(bool conExito) {
            if (conExito) {
                arrancarStayAlive();
                if (estadoActual != ESTADO_OPERADOR.RECONECTANDO) {
                    estadoGuardado = estadoActual;
                }
                estadoActual = ESTADO_OPERADOR.RECONECTANDO;
                ponerEstado(ESTADO_OPERADOR.RECONECTANDO);
                ponMensaje("Reconectado al servidor en " + comm.host);
            } else {
                pararStayAlive();
                if (modoSinGestor) {
                    //FormDesconexion fdx = new FormDesconexion(ventana);
                    //fdx.setSize(420, 240);
                    //fdx.setLocationRelativeTo(null);
                    //fdx.setVisible(true);
                } else {
                    MessageBox.Show("Se ha perdido la conexión con el servidor. Se cierra el programa");
                    cierreIrreversible = true;
                    Application.Exit();
                }
            }
            return estadoGuardado;
        }

        private void btEstadoColas_Click(object sender, EventArgs e) {
            pedirResumenColas();
        }

        private void pedirResumenColas() {
            comm.enviar(COD_ENVIADO.ENVIAR_RESUMEN_COLAS);
        }

        private void btReenvio_Click(object sender, EventArgs e) {
            comm.enviar(COD_ENVIADO.SOLICITAR_ESTADO_COLAS);
        }

        private void btAutoEnviar_Click(object sender, EventArgs e) {

            if (estadoActual != ESTADO_OPERADOR.LIBRE) {
                MessageBox.Show("El Operador debe estar en Estado LIBRE");

                return;
            }
            if (estadoActual != ESTADO_OPERADOR.LIBRE) {
                pulsadoLibre();
            }
            if (colaCero == null) {
                MessageBox.Show("No hay definida una cola con categoría estadística CERO");
                return;
            }
            // Si se utiliza TipoNavegacion habrá que pedir AQUI el NIF del cliente y enviarlo en el mensaje
            string nif = "XXX";
            string nombre = " ";
            if (nifColaCero) {
                comm.enviarCambioEstado(COD_ENVIADO.LIBRE_A_DESCANSO, idCliente());
                //pulsadoDescanso();
                DlgIdentificacion dlg = new DlgIdentificacion();
                if (dlg.ShowDialog() == DialogResult.Cancel) {
                    MessageBox.Show("No se solicitará tique sin datos identificativos", "OPERACIÓN CANCELADA");
                    pulsadoLibre();
                    return;
                }
                comm.enviar(COD_ENVIADO.LIBRE, "0");
                //pulsadoLibre();
                Thread.Sleep(700);
                nif = dlg.nif;
                nombre = dlg.nombre;

            }
            btReenvio.Enabled = false;
            reenvioCondicionado = true;
            comm.enviar(COD_ENVIADO.SOLICITO_AUTOENVIO_COLACERO, nif, nombre, colaCero);
        }

        internal void reeenviar(string msg) {
            if (msg == "NO AUTORIZADO") {
                MessageBox.Show("No está autorizado al reenvio");
            } else {
                reenvio(msg);
            }
        }

        internal void prepararBotoncolaCeroADM(string msg) {
            MessageBox.Show("Solo se puede utilizar en estado LIBRE y SIN CAPACIDADES ACTIVAS\nContacte con el Administrador");
            fallidosBoton = fallidosBoton + 1;
            if (fallidosBoton > 3) {
                this.btAutoEnviar.Visible = false;
                MessageBox.Show("Autoenvio  Desactivado");
            }

        }

        void testCategorias() {
            FormOperacionRealizada fop = new FormOperacionRealizada();
            fop.ShowDialog();
        }

        internal void enviarFavoritasEstadisticas(string favoritasAhora) {
            comm.enviar(COD_ENVIADO.ENVIO_FAVORITAS_ESTADISTICAS, favoritasAhora);
        }

        internal void enviarModificacionCategoriaCandidato(string id, string nuevaCategoria) {
            comm.enviar(COD_ENVIADO.ENVIO_MODIFICACION_CAT_REGISTRO, id, nuevaCategoria);
        }

        internal bool comprobarReentrada() {
            try {
                if (!conf.bloquearCliente)
                    return true;
                Process esteProceso = Process.GetCurrentProcess();
                int estaSesion = esteProceso.SessionId;

                Process[] procesos = Process.GetProcesses();
                foreach (Process proc in procesos) {
                    if (proc.ProcessName.Equals("operador", StringComparison.CurrentCultureIgnoreCase)) {
                        if (proc.Id != esteProceso.Id) {
                            if (proc.SessionId != estaSesion) {
                                MessageBox.Show("El módulo Operador.exe está ejecutandose en otra sesión de ususario en esta misma máquina (Id ses: "
                                    + proc.SessionId.ToString() +
                                    ")\n¿Ha utilizado 'Cambiar de usuario' en vez de cerrar la sesión anterior?",
                                    "ERROR: ejecución simultánea de Operador.exe");
                            }
                            return false;
                        }
                    }
                }
            } catch (Exception) { }
            return true;
        }

        public void mostrarOperadoresEnFicha(string listaOPE) {
            if (fReenvio == null) return;
            fReenvio.mostrarOperadores(listaOPE);
        }

        private void timerCitaLarga_Tick(object sender, EventArgs e) {
            if (facl == null) {
                facl = new FormAvisoCitaLarga(this);
                facl.Show(this);
            }
        }

        public void fichaAvisoCitaLargaCerrada(bool conMensaje) {
            facl = null;
            if (conMensaje) {
                TimeSpan transcurrido = DateTime.Now - cliente.horaInicio;
                string mensaje = string.Format("-- Cita Demasiado Larga --# La mesa {0} lleva {1} minutos atendiendo una cita",
                    comm.mesa, ((int)transcurrido.TotalMinutes).ToString());
                comm.enviar(COD_ENVIADO.MENSAJE_AL_ADMINISTRADOR, mensaje);
                timerCitaLarga.Stop();
                timerCitaLarga.Interval = 360000;
                timerCitaLarga.Start();

            }
        }

        private void btGrabarNota_Click(object sender, EventArgs e) {
            FomNota1 fn = new FomNota1();
            fn.Show();
        }
    }

    class InvocadorMiniGestor
    {
        Assembly dll;
        Type tipoMiniGestor;
        Object objetoMiniGestor = null;

        public InvocadorMiniGestor() {
            dll = Assembly.LoadFrom("minigestor.dll");
            tipoMiniGestor = dll.GetType("minigestor.MiniGestor");
            objetoMiniGestor = Activator.CreateInstance(tipoMiniGestor);
        }

        public void lanzar() {
            object[] args = new object[0];
            tipoMiniGestor.InvokeMember("lanzarCliente", BindingFlags.Default | BindingFlags.InvokeMethod,
                            null, objetoMiniGestor, args);
        }

        public void cerrar() {
            object[] args = new object[0];
            tipoMiniGestor.InvokeMember("cerrarCliente", BindingFlags.Default | BindingFlags.InvokeMethod,
                            null, objetoMiniGestor, args);
        }

        public void cambiarVisibilidad(bool v) {
            try {
                object[] args = new object[1];
                args[0] = v;
                tipoMiniGestor.InvokeMember("cambiarVisibilidad", BindingFlags.Default | BindingFlags.InvokeMethod,
                                null, objetoMiniGestor, args);
            } catch {}
        }
    }
}