// 
// 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.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.Threading;
using ateneo.utiles;
using SHDocVw;

namespace operador.iexplorer
{
    public enum ESTADO_NAVEGADOR {TERMINADA,CANCELADA,ENCURSO,TIMEOUT,CERRADO};

    public delegate void IECerrandoHandler();
    public delegate void IECerradoHandler(IEControl sender);

    public class IEControl
    {
        InternetExplorer ie;
        List<IEControl> ieSec = new List<IEControl>();
        string paginaEsperada = "";
        public event IECerrandoHandler OnIeCerrando;
        public event IECerradoHandler OnIeCerrado;
        public bool OK = true;
        public ESTADO_NAVEGADOR estadoNav;
        Object nulo = null;
        public uint processId;
        ManualResetEvent eventoFinNavegacion = new ManualResetEvent(false);
        public IEControl() {
            ie = new InternetExplorer();
            ie.OnQuit += new DWebBrowserEvents2_OnQuitEventHandler(ie_OnQuit);
            ie.NewWindow2 += new DWebBrowserEvents2_NewWindow2EventHandler(ie_NewWindow2);
            ie.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(ie_DocumentComplete);
            mostrar(false);
        }

        public int HWND {
            get { return ie.HWND; }
        }

        void ie_DocumentComplete(object pDisp, ref object URL) {
            string paginaAlcanzada = (string)URL;
            if (paginaEsperada == null || paginaAlcanzada == paginaEsperada)
            {
                estadoNav = ESTADO_NAVEGADOR.TERMINADA;
                eventoFinNavegacion.Set();
                paginaEsperada = null;
            }
        }

        public void desconectarOnQuit() {
            OnIeCerrando = null;
            OnIeCerrado = null;
        }

        void ie_OnQuit() {
            cerrarVentanaSec();
            if (estadoNav == ESTADO_NAVEGADOR.ENCURSO) {
                estadoNav = ESTADO_NAVEGADOR.CERRADO;
            }
            if(OnIeCerrando != null) {
                operador.Principal.yo.Invoke(OnIeCerrando);
            }
            if(OnIeCerrado != null) {
                operador.Principal.yo.BeginInvoke(OnIeCerrado, new object[] { this });
            }
        }

        public static void matarProcesosIExplorer(bool conMensaje) {
            Process[] procesos = Process.GetProcessesByName("iexplore");
            if(procesos.Length == 0) return;
            if (conMensaje) {
                MessageBox.Show("Se van a cerrar TODAS las ventanas de INTERNET EXPLORER");
            }
            foreach(Process p in procesos) {
                try {
                    p.Kill();
                } catch (Exception) { }
            }
        }

        public void navegar(string url) {
            Win32Apis.ignorarAlertasDeExplorer(processId);
            ie.Navigate(url, ref nulo, ref nulo, ref nulo, ref nulo);
        }

        public void stop() {
            ie.Stop();
            estadoNav =  ESTADO_NAVEGADOR.CANCELADA ;
            eventoFinNavegacion.Set();
        }

        public void mostrar(bool v) {
            ie.Visible = v;
        }

        public void cerrar() {
            Win32Apis.ignorarAlertasDeExplorer(processId);
            ie.Quit();
        }

        public void esperarEstadocompleto() {
            try {
                for(int totalTiempo = 0; totalTiempo < 5000; totalTiempo += 200) {
                    int estado = (int)ie.ReadyState;
                    if (estado == 4 || estado==0) break;
                    System.Threading.Thread.Sleep(200);
                }
            } catch (Exception exc) {
                LogExcepcion.guardar("Excepcion esperando ESTADO_COMPLETO", exc);
            }
        }

        public IEDocument documento {
            get {
                return new IEDocument((mshtml.HTMLDocument)ie.Document);
            }
        }

        public int cargarPagina(string paginaDestino, string pagEsperada, int timeOut) {
            if (estadoNav == ESTADO_NAVEGADOR.ENCURSO) {
                stop();
            }
            estadoNav = ESTADO_NAVEGADOR.ENCURSO;
            mostrar(true);
            paginaEsperada = pagEsperada;
            navegar(paginaDestino);
            Application.DoEvents();
            if (timeOut > 0) {
                int r = esperarIE(timeOut);
                return r;
            }
            return (int)estadoNav;
        }

        public void navegarHome() {
            Win32Apis.ignorarAlertasDeExplorer(processId);
            ie.GoHome();
        }

        public void setPaginaEsperada(String pagina) {
            estadoNav = ESTADO_NAVEGADOR.ENCURSO;
            paginaEsperada = pagina;
        }

        public int esperarIE(int timeOut) {
            if (estadoNav == ESTADO_NAVEGADOR.TERMINADA || estadoNav == ESTADO_NAVEGADOR.CANCELADA) {
                return (int)ESTADO_NAVEGADOR.TERMINADA;
            }
            eventoFinNavegacion.Reset();
            eventoFinNavegacion.WaitOne(timeOut, false);
            if (estadoNav == ESTADO_NAVEGADOR.CERRADO) {
                return (int)estadoNav;
            }
            if (estadoNav == ESTADO_NAVEGADOR.ENCURSO) {
                return (int)ESTADO_NAVEGADOR.TIMEOUT;
            }
            return (int)ESTADO_NAVEGADOR.TERMINADA;
        }

        void ie_NewWindow2(ref object ppDisp, ref bool Cancel) {
            try {
                IEControl ie2 = new IEControl();
                ie2.OnIeCerrado += new IECerradoHandler(ie2_OnIeSecCerrado);
                ie2.mostrar(true);
                ppDisp = ie2.ie.Application;
                ieSec.Add(ie2);
            } catch (Exception exc) {
                LogExcepcion.guardar("Error en evento NewWindow2 (ventana emergente)", exc);
            }
        }

        void ie2_OnIeSecCerrado(IEControl sender) {
            if (ieSec.Contains(sender)) {
                ieSec.Remove(sender);
            }
        }

        public void cerrarVentanaSec() {
            Win32Apis.ignorarAlertasDeExplorer(processId);
            if (ieSec.Count > 0) {
                foreach(IEControl ie2 in ieSec) {
                    try {
                        ie2.desconectarOnQuit();
                        ie2.cerrar();
                    } catch (Exception) {
                        //operador.Principal.yo.logException("Error en CerrarVentanaSec", ex);
                    }
                }
                ieSec.Clear();
            }
        }
    }
}
