using System;
using System.Configuration;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Text;
using System.Xml;
using System.Windows.Forms;
using GMLC01HerramientasCad.Logica;
using NEGOCIO = GMLC01HerramientasCad.Negocio;
using DAO = GMLC01HerramientasCad.DAO;

[assembly: CLSCompliant(true)]
namespace GMLC01HerramientasCad.Logica
{
    /// <summary>
    /// <c>ModComun</c> implementa el módulo común en la aplicación de inventario.
    /// </summary>
    /// <remarks>
    /// Contiene los puntos de entrada para activar cada uno de los formularios comunes:
    /// <list type="bullet">
    /// <item><description><see cref="ActivarConsulta"/></description></item>
    /// <item><description><see cref="ActivarTematicos"/></description></item>
    /// <item><description><see cref="ActivarEtiquetado"/></description></item>
    /// <item><description><see cref="ActivarBuscar"/></description></item>
    /// <item><description><see cref="ActivarExportarGML"/></description></item>
    /// <item><description><see cref="ActivarImportarGML"/></description></item>
    /// </list>
    /// Tambien expone ciertas propiedades y metodos para gestionar la aplicación:
    /// <list type="bullet">
    /// <item><description><see cref="CargarXSD"/></description></item>
    /// <item><description><see cref="XSD"/></description></item>
    /// <item><description><see cref="Version"/></description></item>
    /// <item><description><see cref="Idioma"/></description></item>
    /// </list>
    /// Se definen las interfaces que han de implementarse en los módulos CAD
    /// para responder a las peticiones hechas desde este módulo.
    /// <list type="bullet">
    /// <item><description><see cref="IConsultar"/></description></item>
    /// <item><description><see cref="IEtiquetado"/></description></item>
    /// <item><description><see cref="ITematicos"/></description></item>
    /// <item><description><see cref="IBuscar"/></description></item>
    /// <item><description><see cref="IGML"/></description></item>
    /// </list>
    /// <para>
    /// Esta clase implementa el módulo común usando el patrón Singleton. Dadas
    /// las características de ejecución de la aplicación, el uso de este patrón
    /// es seguro ya que la clase se instancia una sola vez, al arrancar el módulo
    /// CAD y en un entorno "single user"
    /// </para>
    /// </remarks>
    public sealed class ModComun
    {
#region Propiedades

        private static readonly ModComun iInstance = new ModComun();
        private static TematicosForm iFrmTematicos;
        private static BuscarForm iFrmBuscar;
        internal static Collection<Atributo> iPortaPapeles;
        private static String iDirectorioConfiguracion;
        private static String iIdioma;


        /// <summary>
        /// Constructor de la clase, privado para cumplir con el patrón Singleton
        /// </summary>
        private ModComun(){}
        
        /// <summary>
        /// Refleja la estructura del XSD necesaria para el módulo CAD
        /// </summary>
        public static XSDInfo XSD { get; internal set;}

        public static ConfigGmlParser ConfigGml { get; internal set; }

        /// <summary>
        /// Idioma en el que se deben mostrar los textos
        /// </summary>
        public static String Idioma
        {
            get
            {
                return iIdioma;
            }
            set
            {
                try
                {
                    Localizador.Instance.NombreCultura = value + "-ES";
                    iIdioma = value;
                }
                catch (ExcepcionGMLC)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw new ExcepcionGMLC(e.Message);
                }
            }
        }

        /// <summary>
        /// Directorio de instalación de la aplicación GMLC.
        /// </summary>
        public static String DirectorioGMLC { get; internal set; }

        /// <summary>
        /// Directorio donde se encuentran los ficheros GML por defecto
        /// </summary>
        public static String DirectorioGMLDefault { get; internal set; }

        /// <summary>
        /// Ubicación del fichero XSD.
        /// </summary>
        public static String UbicacionXSD { get; internal set; }

        /// <summary>
        /// Ubicación del fichero de configuración de GML.
        /// </summary>
        public static int MaxEntidadesAutoconsulta { get; internal set; }

        /// <summary>
        /// Ubicación del fichero de configuración de GML.
        /// </summary>
        public static String ConfigGmlPath { get; internal set; }

        /// <summary>
        /// Idioma por defecto
        /// </summary>
        public static String IdiomaDefault { get; internal set; }

        /// <summary>
        /// Centrado por defecto al consultar un elemento
        /// </summary>
        public static bool CentrarDefault { get; internal set; }

        /// <summary>
        /// Resaltado por defecto al consultar un elemento
        /// </summary>
        public static bool ResaltarDefault { get; internal set; }

        /// <summary>
        /// Sufijo por defecto para creación de capas de rotulación
        /// </summary>
        public static String SufijoRotulacionDefault { get; internal set; }

        /// <summary>
        /// Directorio de configuración del módulo común. Lee las propiedades de la aplicación.
        /// </summary>
        public static String DirectorioConfiguracion
        {
            get
            {
                return iDirectorioConfiguracion;
            }
            set
            {
                try
                {
                    iDirectorioConfiguracion = value;
                    Configuration iCfg = ConfigurationManager.OpenExeConfiguration(iDirectorioConfiguracion + "\\GMLC01HerramientasCad.Logica.dll");

                    if (iCfg == null || !iCfg.HasFile)
                        throw new ExcepcionGMLC(Properties.Resources.NoSeHaAbiertoElFicheroDeConfiguracion);

                    if (iCfg.AppSettings.Settings["DirectorioGMLC"] != null)
                        DirectorioGMLC = iCfg.AppSettings.Settings["DirectorioGMLC"].Value;
                    else
                        throw new ExcepcionGMLC(Properties.Resources.NoSeHaDefinidoLaVariableDeConfiguracionDirectorioGMLC);

                    UbicacionXSD = iCfg.AppSettings.Settings["UbicacionXSD"] == null ?
                                            DirectorioGMLC + "\\config\\entidades.XSD" :
                                            iCfg.AppSettings.Settings["UbicacionXSD"].Value;

                    MaxEntidadesAutoconsulta = iCfg.AppSettings.Settings["MaxEntidadesAutoconsulta"] == null ?
                                            1 :
                                            Convert.ToInt32(iCfg.AppSettings.Settings["MaxEntidadesAutoconsulta"].Value, CultureInfo.InvariantCulture);

                    ConfigGmlPath = iCfg.AppSettings.Settings["ConfigGML"] == null ?
                                            DirectorioGMLC + "\\config\\configGML.xml" :
                                            iCfg.AppSettings.Settings["ConfigGML"].Value;

                    IdiomaDefault = iCfg.AppSettings.Settings["IdiomaDefault"] == null ?
                                            "" :
                                            iCfg.AppSettings.Settings["IdiomaDefault"].Value;


                    CentrarDefault = iCfg.AppSettings.Settings["CentrarDefault"] == null ?
                                            false :
                                            iCfg.AppSettings.Settings["CentrarDefault"].Value.ToUpper(CultureInfo.InvariantCulture) == "TRUE";

                    ResaltarDefault = iCfg.AppSettings.Settings["ResaltarDefault"] == null ?
                                            false :
                                            iCfg.AppSettings.Settings["ResaltarDefault"].Value.ToUpper(CultureInfo.InvariantCulture) == "TRUE";

                    SufijoRotulacionDefault = iCfg.AppSettings.Settings["SufijoRotulacionDefault"] == null ?
                                            "_rotulos" :
                                            iCfg.AppSettings.Settings["SufijoRotulacionDefault"].Value;

                    DirectorioGMLDefault = iCfg.AppSettings.Settings["DirectorioGMLDefault"] == null ?
                                            DirectorioGMLC + "\\GML" :
                                            iCfg.AppSettings.Settings["DirectorioGMLDefault"].Value;
                }
                catch (ExcepcionGMLC)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw new ExcepcionGMLC(e.Message);
                }
            }
        }

        /// <summary>
        /// Instancia singleton
        /// </summary>
        public static ModComun Instance
        {
            get { return iInstance; }
        }
#endregion

#region Metodos
        private static void DummyFxCop()
        {
            new NEGOCIO.Dummy().Value = new DAO.Dummy().Value;
        }

        /// <summary>
        /// <c>CargarXSD</c> lee el fichero indicado en la variable de configuración <c>UbicacionXSD</c> y genera la
        /// estructura necesaria en <c>XSD</c>
        /// </summary>
        /// <param name="VersionCAD">Versión del modelo usado en el fichero CAD</param>
        public static void CargarXSD (String versionCAD)
        {
            try
            {
                DummyFxCop();
                XSD = new XSDInfo(UbicacionXSD, versionCAD);
                // Carga del XSD.
                if (!String.IsNullOrEmpty(IdiomaDefault))
                    Idioma = IdiomaDefault;
                ConfigGml = new ConfigGmlParser(ConfigGmlPath);
            }
            catch (ExcepcionGMLC)
            {
                throw;
            }
            catch (Exception e)
            {
                Log.RegisterError(e);
                throw new ExcepcionGMLC(e.Message, e);
            }
        }

        /// <summary>
        /// <c>ActivarConsultar</c> abre el formulario de consulta, edición y copiado de atributos alfanuméricos.
        /// </summary>
        /// <param name="consultarIF">Recibe la implementación de los métodos que se usan desde el formulario</param>
        /// <param name="elementos">Recibe la coleccion de elementos con los que trabajará el formulario</param>
        public static void ActivarConsulta(IConsultar consultarIF, Collection<Elemento> elementos)
        {
            try
            {
                ConsultarForm f = new ConsultarForm(consultarIF, elementos);
                f.ShowDialog();
                f.Dispose();
            }
            catch (ExcepcionGMLC)
            {
                throw;
            }
            catch (Exception e)
            {
                Log.RegisterError(e);
                throw new ExcepcionGMLC(e.Message, e);
            }
        }

        /// <summary>
        /// <c>ActivarTematicos</c> abre el formulario de gestión de temáticos.
        /// </summary>
        /// <param name="tematicosIF">Recibe la implementación de los métodos que se usan desde el formulario</param>
        /// <param name="entidad">Recibe la entidad sobre la que se quiere realizar el temático</param>
        public static void ActivarTematicos(ITematicos tematicosIF, TematicoDatosInput datosInput)
        {
            try
            {
                if (iFrmTematicos == null || (iFrmTematicos != null && iFrmTematicos.IsDisposed))
                    iFrmTematicos = new TematicosForm(tematicosIF, datosInput);

                iFrmTematicos.ShowDialog();
                iFrmTematicos.Dispose();
            }
            catch (ExcepcionGMLC)
            {
                throw;
            }
            catch (Exception e)
            {
                Log.RegisterError(e);
                throw new ExcepcionGMLC(e.Message, e);
            }
        }

        /// <summary>
        /// <c>ActivarEtiquetado</c> abre el formulario de gestión de etiquetado.
        /// </summary>
        /// <param name="etiquetadoIF">Recibe la implementación de los métodos que se usan desde el formulario</param>
        public static void ActivarEtiquetado(IEtiquetado etiquetadoIF)
        {
            try
            {
                new EtiquetadoForm(etiquetadoIF).ShowDialog();
            }
            catch (ExcepcionGMLC)
            {
                throw;
            }
            catch (Exception e)
            {
                Log.RegisterError(e);
                throw new ExcepcionGMLC(e.Message, e);
            }
        }

        /// <summary>
        /// <c>ActivarBuscar</c> abre el formulario de selección de elementos por criterio alfanumérico.
        /// </summary>
        /// <param name="buscarIF">Recibe la implementación de los métodos que se usan desde el formulario</param>
        /// <param name="entidad">Entidad sobre la que se va a realizar la búsqueda</param>
        /// <returns>Devuelve el formulario abierto</returns>
        public static Form ActivarBuscar(IBuscar buscarIF, Entidad entidad)
        {
            try
            {
                if (iFrmBuscar == null || (iFrmBuscar != null && iFrmBuscar.IsDisposed))
                    iFrmBuscar = new BuscarForm(buscarIF, entidad);

                iFrmBuscar.Show();

                return iFrmBuscar;
            }
            catch (ExcepcionGMLC)
            {
                throw;
            }
            catch (Exception e)
            {
                Log.RegisterError(e);
                throw new ExcepcionGMLC(e.Message, e);
            }
        }

        /// <summary>
        /// <c>ActivarExportarGML</c> abre el formulario de exportación a fichero GML.
        /// </summary>
        /// <param name="exportarIF">Recibe la implementación de los métodos que se usan desde el formulario</param>
        public static void ActivarExportarGML(IGML exportarIF)
        {
            try
            {
                new GMLForm(false, exportarIF).ShowDialog();
            }
            catch (ExcepcionGMLC)
            {
                throw;
            }
            catch (Exception e)
            {
                Log.RegisterError(e);
                throw new ExcepcionGMLC(e.Message, e);
            }
        }

        /// <summary>
        /// <c>ActivarImportarGML</c> abre el formulario de importación de fichero GML.
        /// </summary>
        /// <param name="importarIF">Recibe la implementación de los métodos que se usan desde el formulario</param>
        public static void ActivarImportarGML(IGML importarIF)
        {
            try
            {
                new GMLForm(true, importarIF).ShowDialog();
            }
            catch (ExcepcionGMLC)
            {
                throw;
            }
            catch (Exception e)
            {
                Log.RegisterError(e);
                throw new ExcepcionGMLC(e.Message, e);
            }
        }

        /// <summary>
        /// <c>ActivarIdioma</c> abre el formulario de selección de idioma.
        /// </summary>
        public static void ActivarIdioma()
        {
            try
            {
                if (ModComun.XSD == null)
                    throw new ExcepcionGMLC(Properties.Resources.ElFicheroXSDNoHaSidoCargado);

                IdiomaForm f = new IdiomaForm();
                f.ShowDialog();
                f.Close();
                f.Dispose();
            }
            catch (ExcepcionGMLC)
            {
                throw;
            }
            catch (Exception e)
            {
                Log.RegisterError(e);
                throw new ExcepcionGMLC(e.Message, e);
            }
        } 
        #endregion
    }
#region Interfaces
    /// <summary>
    /// Interfaz que se debe implementar para cumplir con las peticiones del formulario de consulta.
    /// </summary>
    public interface IConsultar
    {
        /// <summary>
        /// Graba los atributos alfanuméricos en el fichero CAD
        /// </summary>
        /// <param name="elementos">Lista de los elementos con los atributos alfanuméricos a guardar</param>
        void Guardar(Collection<Elemento> elementos);
        /// <summary>
        /// Resalta un elemento en la pantalla
        /// </summary>
        /// <param name="elemento">Elemento a resaltar</param>
        void Resaltar(Elemento elemento);
        /// <summary>
        /// Centra un elemento en la pantalla
        /// </summary>
        /// <param name="elemento">Elemento a centrar</param>
        void Centrar(Elemento elemento);
    }

    /// <summary>
    /// Interfaz que se debe implementar para cumplir con las peticiones del formulario de etiquetado.
    /// </summary>
    public interface IEtiquetado
    {
        /// <summary>
        /// Etiqueta los elementos seleccionados segun el criterio seleccionado
        /// </summary>
        /// <param name="criterio">Criterio de etiquetado</param>
        void Etiquetar(CriterioEtiquetado criterio);
    }

    /// <summary>
    /// Interfaz que se debe implementar para cumplir con las peticiones del formulario de temáticos.
    /// </summary>
    public interface ITematicos
    {
        /// <summary>
        /// Realiza el temático discreto según el criterio escogido
        /// </summary>
        /// <param name="criterio">Criterio de temático</param>
        void TematicoDiscreto(CriterioTematicos criterio);
        /// <summary>
        /// Realiza el temático discreto según el criterio escogido
        /// </summary>
        /// <param name="criterio">Criterio de temático</param>
        void TematicoContinuo(CriterioTematicos criterio);
    }

    /// <summary>
    /// Interfaz que se debe implementar para cumplir con las peticiones del formulario de búsqueda.
    /// </summary>
    public interface IBuscar
    {
        /// <summary>
        /// Selecciona los elementos que cumplan el criterio escogido
        /// </summary>
        /// <param name="criterio">Criterio de búsqueda</param>
        void Buscar(CriterioBusqueda criterio);
    }

    /// <summary>
    /// Interfaz que se debe implementar para cumplir con las peticiones de los formularios de 
    /// importación y exportación a GML.
    /// </summary>
    public interface IGML
    {
        /// <summary>
        /// Obtiene la lista de todos los elementos de inventario del fichero CAD
        /// </summary>
        /// <returns>Devuelve el conjunto de elementos encontrado</returns>
        Collection<Elemento> ObtenerElementos();
        /// <summary>
        /// Graba en ele fichero CAD los elementos proporcionados
        /// </summary>
        /// <param name="elementos">Conjunto de elementos a grabar</param>
        void GrabarElementos(Collection<Elemento> elementos);
    }
#endregion
}
