using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.IO;

using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.GeoDatabaseUI;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.ADF.COMSupport;
using ESRI.ArcGIS.Output;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Framework;

namespace OliviaAddIn
{
    public class Maqueta
    {
        public String err_str = "";
        public String nomb_plantilla = "Plantilla.mxd";

        /**
        * Crea una capa en la GDB de trabajo con el municipio que contiene la capa de ámbitos de la que se ha realizado la sectorización.
         * De modo que se pueda incorporar en el mapa de localización.
        */
        public IDatasetName municipio(string dir_shp, string capa, out string muni)
        {
            int campo, numero;
            IWorkspace ws = null;
            IQueryFilter filt = null;
            IDataset data, grupo, element;
            ESRI.ArcGIS.esriSystem.IName name;
            IWorkspaceName ws_name;
            IWorkspaceFactory wsf;
            IFeatureWorkspace fws;
            IFeatureClass fc1, fc2;
            IFeatureClassName gdb_clase_lin = null, shp_clase;
            IFeatureWorkspace feat_ws_nw;
            IDatasetName gdb_data_name_lin, shp_data_name_lin, data_entrada, dname_gdb;
            IFeatureDatasetName fdn_gdb;
            ISpatialFilter filtro_espacial;
            ITable tab;
            IFeature f1, registro;
            IFeatureCursor cursor;
            ITopologicalOperator union;
            IGeometry geometria;
            IFeatureDataConverter convertidor = null;
            IEnumInvalidObject invalido = null;
            IEnumDataset grupos, elementos;
            IWorkspaceFactory wsf_nw;
            
            wsf_nw = new FileGDBWorkspaceFactoryClass();
            feat_ws_nw = (IFeatureWorkspace)wsf_nw.OpenFromFile(OliviaGlob.Paths.PathGdbNw, 0);
            gdb_clase_lin = new FeatureClassNameClass();
            gdb_data_name_lin = (IDatasetName)gdb_clase_lin;
            gdb_data_name_lin.Name = OliviaGlob.Capas.ftclass_muni;

            gdb_data_name_lin.WorkspaceName = FunGDB.abre_wsn(OliviaGlob.Paths.PathGdbNw);
            fc1 = feat_ws_nw.OpenFeatureClass(gdb_data_name_lin.Name);
            //se unen todos los elementos (polilineas) que conforman el shapefile de ámbitos para generar el mapa.
            //Esto se hace para que considere como una geometría todas las polilineas que intersecará con la capa de municipios
            wsf = new FileGDBWorkspaceFactoryClass();
            ws = wsf.OpenFromFile(dir_shp, 0);
            fws = (IFeatureWorkspace)ws;
            data = (IDataset)ws;
            name = data.FullName;
            ws_name = (IWorkspaceName)name;
            fc2 = fws.OpenFeatureClass(capa);
            tab = fws.OpenTable(capa);
            f1 = fc2.GetFeature(1);//se coge un úico elemento de la capa ya que bastará con comprobar a qué municipio pertenece esa carretera.
            union = (ESRI.ArcGIS.Geometry.ITopologicalOperator)f1.Shape;
            geometria = f1.Shape;

            //INTERSECCIÓN ESPACIAL ENTRE LA GEOMETRÍA DEL SHAPEFILE DE ENTRADA Y LA CAPA DE MUNICIPIOS EXTRAÍDA DE LA GDB DE TOMTOM
            //se consigue el municpio sobre el que se está trabajando
            filtro_espacial = new SpatialFilterClass();
            filtro_espacial.Geometry = geometria;
            filtro_espacial.GeometryField = fc1.ShapeFieldName;
            filtro_espacial.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
            filt = (IQueryFilter)filtro_espacial;

            //se recoge el nombre del municipio que interseca con los ambitos y que se incorporará al mapa de localización
            cursor = fc1.Search(filt, false);
            registro = cursor.NextFeature();
            tab = feat_ws_nw.OpenTable(gdb_data_name_lin.Name);
            campo = tab.FindField("NAME");
            muni = (string)registro.get_Value(campo);

            //cREAR EL NOMBRE DEL GRUPO EN EL QUE SE GUARDAN LAS CAPAS DE MUNICIPIOS QUE INTERVIENEN EN LA MAQUETACIÓN
            fdn_gdb = new FeatureDatasetNameClass();
            dname_gdb = (IDatasetName)fdn_gdb;
            dname_gdb.WorkspaceName = ws_name;
            dname_gdb.Name = OliviaGlob.gdb.municipio;
            //se pone  el espacio de trabajo para la capa que se quiere importar a la GDB. Será el mismo que el del grupo donde irá la capa importada
            shp_clase = new FeatureClassNameClass();
            shp_data_name_lin = (IDatasetName)shp_clase;
            shp_data_name_lin.Name = muni;
            shp_data_name_lin.WorkspaceName = ws_name;

            //comprueba si existe la capa referente al municipio en la GDB
            grupos = ws.get_Datasets(esriDatasetType.esriDTFeatureDataset);
            grupo = grupos.Next();
            while (grupo != null)
            {
                if (grupo.Name == OliviaGlob.gdb.municipio)
                {
                    elementos = grupo.Subsets;
                    element = elementos.Next();
                    while (element != null)
                    {
                        if (element.Name == muni)
                        {
                            //si ya existe la capa se vuelve sin importarla de nuevo
                            return shp_data_name_lin;
                        }
                        element = elementos.Next();
                    }
                    break;
                }
                grupo = grupos.Next();
            }
            //EXPORTACIÓN DEL MUNICIPIO/S QUE INTERSECA CON LA CAPA DE ÁMBITOS (SHAPEFILE DE ENTRADA)
            numero = tab.RowCount(filt);
            if (numero > 0)
            {
                data_entrada = (IDatasetName)gdb_clase_lin;
                try
                {
                    //se crea el convertidor y se aplica la conversión.
                    convertidor = new FeatureDataConverterClass();
                    invalido = convertidor.ConvertFeatureClass(gdb_clase_lin, filt, fdn_gdb, shp_clase, null, null, "", 1000, 0);
                }
                catch (Exception except)
                {
                    MessageBox.Show(except.Message);
                    throw;
                }
            }
            else
            {
                err_str = "No se encuentra el municipio sobre el que se está realizando el estudio";
                return null;
            }
            return shp_data_name_lin;
        }        

        /**
        * Carga la plantilla para la creación de mapas y activa el modo de vista de diseño (Layout) 
        */
        public IPageLayout pon_plantilla(out string name_plant)
        {
            ESRI.ArcGIS.ArcMapUI.IMxDocument mx_doc;
            IMap map;

            //SE CARGA LA PLANTILLA DE MAPA Cartela_Valoriza.mxd
            name_plant = "";
            string plant;
            ESRI.ArcGIS.Catalog.IGxFile pGxFile;
            pGxFile = new ESRI.ArcGIS.Catalog.GxMapClass();
            plant = OliviaGlob.Paths.PathCartela;//OliviaGlob.mapa.selec_plantilla();
            if (plant == null)
                return null;
            pGxFile.Path = plant;
            name_plant = pGxFile.Path;
            ESRI.ArcGIS.Catalog.IGxMapPageLayout pGxPageLayout;
            pGxPageLayout = (ESRI.ArcGIS.Catalog.IGxMapPageLayout)pGxFile;
            ESRI.ArcGIS.Carto.IPageLayout pPageLayout;
            pPageLayout = pGxPageLayout.PageLayout;

            /////////////////////////////////////////////////////////////
            //pone las opciones de impresión a  A3 y horizontal            
            pPageLayout.Page.Orientation = 2;
            pPageLayout.Page.PutCustomSize(42,29.7);
            ///////////////////////////////////////////

            //COGE EL FOCO DE LA VISTA DEL MAPA EL MODO DE VISTA LAYOUT (EL MODO DE VISTA CON LA PLANTILLA INCORPORADA)
            mx_doc = (ESRI.ArcGIS.ArcMapUI.IMxDocument)(ArcMap.Application.Document);
            map = mx_doc.FocusMap;
            mx_doc.PageLayout = pPageLayout;
                     
            //////////////////

            return pPageLayout;
        }

        /**
        * Carga la imagen que corresponde al cliente(modo 0) o al licitador(modo1) que precisa de la limpieza viaria, recogida de residuos, etc
         * tipo 0 (cartela IGT)
         * tipo 1 (cartela Formato tipo_Limpieza_DatosInformativos)
        */
        public string pon_imag(string title, int modo, int tipo)
        {
            string foto = null;
            double ratio, ancho, alto;
            IElement elem;
            IEnvelope env;
            ESRI.ArcGIS.ArcMapUI.IMxDocument mx_docu;
            IPictureElement pic_elem;
            IActiveView vista_activa;
            IPoint pto;

            mx_docu = (ESRI.ArcGIS.ArcMapUI.IMxDocument)ArcMap.Application.Document;
            // Displays an OpenFileDialog so the user can select a Cursor.
            System.Windows.Forms.OpenFileDialog openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
            openFileDialog1.Filter = "Imágenes(*.jpg)|*.jpg|Imágenes(*.bmp)|*.bmp|Imágenes(*.tiff)|*.tiff|Imágenes(*.png)|*.png";
            openFileDialog1.Title = title;

            // Show the Dialog.
            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                foto = openFileDialog1.FileName;
                pic_elem = new JpgPictureElementClass();
                pic_elem.ImportPictureFromFile(foto);
                ratio = pic_elem.PictureAspectRatio;
                env = new EnvelopeClass();
                if (tipo == 0)
                {
                    if (modo == 0)
                    {
                        //se incorpora la imagen manteniendo las proporciones de ancho y alto para que no se deformen al incorporarlas
                        pto = new PointClass();
                        pto.X = 9.5;
                        pto.Y = 7.4;
                        env.PutCoords(8.3, 6.7, 10.7, 8.1);
                        ancho = env.Width;
                        alto = env.Height;
                        if (ratio < 1)
                        {
                            env.Width = env.Height * ratio;
                            if (env.Width > ancho)
                            {
                                env.Width = ancho;
                                env.Height = env.Width / ratio;
                            }
                        }
                        else
                        {
                            env.Height = env.Width / ratio;
                            if (env.Height > alto)
                            {
                                env.Height = alto;
                                env.Width = env.Height * ratio;
                            }
                        }
                        env.CenterAt(pto);
                    }
                    else
                    {
                        //se incorpora la imagen manteniendo las proporciones de ancho y alto para que no se deformen al incorporarlas
                        pto = new PointClass();
                        pto.X = 9.6;
                        pto.Y = 6.2;
                        env.PutCoords(9, 5.6, 10.3, 6.8);
                        ancho = env.Width;
                        alto = env.Height;
                        if (ratio < 1)
                        {
                            env.Width = env.Height * ratio;
                            if (env.Width > ancho)
                            {
                                env.Width = ancho;
                                env.Height = env.Width / ratio;
                            }
                        }
                        else
                        {
                            env.Height = env.Width / ratio;
                            if (env.Height > alto)
                            {
                                env.Height = alto;
                                env.Width = env.Height * ratio;
                            }
                        }
                        env.CenterAt(pto);
                    }
                }
                else if (tipo == 1)
                {
                    if (modo == 0)
                    {
                        //se incorpora la imagen manteniendo las proporciones de ancho y alto para que no se deformen al incorporarlas
                        pto = new PointClass();
                        pto.X = 37.9;
                        pto.Y = 26.9;
                        env.PutCoords(36.2, 24.7, 39.5, 28.6);
                        ancho = env.Width;
                        alto = env.Height;
                        if (ratio < 1)
	                    {
                            env.Width = env.Height * ratio;
                            if (env.Width > ancho)
                            {
                                env.Width = ancho;
                                env.Height = env.Width / ratio;
                            }
	                    }
                        else
                        {
                            env.Height = env.Width / ratio;
                            if (env.Height > alto)
                            {
                                env.Height = alto;
                                env.Width = env.Height * ratio;
                            }
                        }
                        env.CenterAt(pto);
                    }
                    else
                    {
                        //se incorpora la imagen manteniendo las proporciones de ancho y alto para que no se deformen al incorporarlas
                        pto = new PointClass();
                        pto.X = 37.6;
                        pto.Y = 22.8;
                        env.PutCoords(34.3, 21.4, 40.9, 24.1);
                        ancho = env.Width;
                        alto = env.Height;
                        if (ratio < 1)
                        {
                            env.Width = env.Height * ratio;
                            if (env.Width > ancho)
                            {
                                env.Width = ancho;
                                env.Height = env.Width / ratio;
                            }
                        }
                        else
                        {
                            env.Height = env.Width / ratio;
                            if (env.Height > alto)
                            {
                                env.Height = alto;
                                env.Width = env.Height * ratio;
                            }
                        }
                        env.CenterAt(pto);
                    }
                }
                pic_elem.MaintainAspectRatio = true;
                elem = (IElement)pic_elem;
                elem.Geometry = env;
                ESRI.ArcGIS.Carto.IGraphicsContainer graph;
                graph = (IGraphicsContainer)mx_docu.PageLayout;
                graph.AddElement(elem, 0);
                if (modo == 1)
                {
                    IGraphicsContainerSelect graphicsSelection = (IGraphicsContainerSelect)graph;
                    graphicsSelection.UnselectAllElements();
                    graphicsSelection.SelectElement(elem);
                    graph.SendToBack(graphicsSelection.SelectedElements);
                    graphicsSelection.UnselectElement(elem);
                }

                vista_activa = (IActiveView)graph;
                vista_activa.PartialRefresh(esriViewDrawPhase.esriViewGraphics, elem, env);
                return foto;
            }
            return foto;
        }

        /**
        * Rellena la plantilla con aquellos elementos dinámicos que varía en cada mapa que se quiera exportar.
        * Los elementos dinámicos son: 
        * - Título del mapa: compuesto por el tipo de tratmiento y ámbitos que intervienen
        * - Fecha de la creación del mapa
        * - Numeración en hojas de los mapas impresos. Se crea un mapa general con toda la sectorización y luego uno específico para cada sector.ç
        * - Escala gráfica
        * - Escala en formato texto
        * - Nombre del municipio al que pertenecen los ámbitos estudiados
        */
        public bool rellena_plantilla(ESRI.ArcGIS.Carto.IPageLayout pPageLayout, IDatasetName shp_data_name_lin, string name_plantilla, int i)
        {
            IWorkspaceFactory wsf;
            IActiveView vista_activa, vis_act;
            IRgbColor color;
            EditTxtPlant txtplant;

            wsf = new FileGDBWorkspaceFactoryClass();            
            vista_activa = ArcMap.Document.ActiveView;
            if (vista_activa is IPageLayout)
            {
                //Reusable color object  
                color = new RgbColorClass();
                color.Red = 0;
                color.Green = 0;
                color.Blue = 0;

                try
                {
                    pon_escala_txt(pPageLayout, vista_activa);

                    //SE CONSIGUE EL NOMBRE DEL MUNICIPIO SOBRE EL QUE SE HACE LA LIMPIEZA VIARIA PARA 
                    //PONERLO EN UNA CAJA DE TEXTO SOBRE EL MAPA Y PARA LLAMAR A LA CAPA CORRESPONDIENTE IGUAL.
                    txtplant = new EditTxtPlant();
                    txtplant.ShowDialog();

                    if (txtplant.DialogResult != DialogResult.OK)
                    {
                        err_str = "Se ha forzado la salida del editor";
                        return false;
                    }

                    for (int k = 0; k < EditTxtPlantProps.N_CAMPOS_PLANT; k++)
                        pon_txt_prop(shp_data_name_lin.Name, vista_activa, k,
                            txtplant.props.campos_plant[k], txtplant.props.fonts[k]);


                    //AÑADE EL TEXTO DE LA FECHA DE CREACIÓN DEL MAPA
                    pon_fecha(color, vista_activa);

                    ////AÑADE LA LEYENDA RESPECTO A LAS CAPAS A MOSTRAR
                    ESRI.ArcGIS.ArcMapUI.IMxDocument pMxDoc = (ESRI.ArcGIS.ArcMapUI.IMxDocument)ArcMap.Application.Document;
                    vis_act = (IActiveView)pMxDoc.PageLayout;
                    vis_act.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
                    vis_act.Refresh();

                    return true;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                
            }

            return false;
        }

        /*
         * Añade la fecha de creación del mapa
         */
        private void pon_fecha(IRgbColor color, IActiveView vista_activa)
        {
            ITextElement text_el, txt_el;
            IFrameProperties frameProperties;
            IElement elm;
            ISimpleTextSymbol txt_smb;
            Font fuent;
            IEnvelope envolv;

            color.Red = 0;
            color.Green = 0;
            color.Blue = 0;

            text_el = new ParagraphTextElementClass();
            txt_el = (ITextElement)text_el;
            elm = (IElement)text_el;
            frameProperties = (IFrameProperties)text_el;
            frameProperties.Background = null;
            frameProperties.Border = null;
            txt_smb = new TextSymbolClass();
            fuent = new Font("Arial Narrow", 8, FontStyle.Regular);
            txt_smb.Font = (stdole.IFontDisp)OLE.GetIFontDispFromFont(fuent);
            txt_smb.Color = color;
            txt_smb.HorizontalAlignment = esriTextHorizontalAlignment.esriTHACenter;
            txt_smb.VerticalAlignment = esriTextVerticalAlignment.esriTVACenter;
            //se incorpora al elemento de texto la simbologia creada
            txt_el.Symbol = txt_smb;
            txt_el.Text = DateTime.Today.ToString("MMMM/yyyy").ToUpper();
            //Se pone  el tamaño y la ubicación de la caja de texto (ie. inches)  
            envolv = new ESRI.ArcGIS.Geometry.EnvelopeClass();
            envolv.PutCoords(34, 0.6, 37, 1.3);
            elm.Geometry = envolv;
            //añadir la caja de texto a la plantilla del mapa
            pon_grafico(elm, vista_activa);
        }

        /**
        * Crea el mapa de localización sobre la plantilla del mapa. Estará compuesto por la cpaa de ámbitos sectorizados y el municipio sobre el que se sitúan dichos ámbitos.
        */
        public void mapa_localizacion(IMap map,IFeatureWorkspace feat_wrk,string ambitos, string municipio, string path_gdb, string ftclass_nom)
        {
            ESRI.ArcGIS.ArcMapUI.IMxDocument mx_doc;
            
            try
            {
                mx_doc = (ESRI.ArcGIS.ArcMapUI.IMxDocument)(ArcMap.Application.Document);
                //se añade la capa del municipio
                ESRI.ArcGIS.Geodatabase.IFeatureClass fCl;
                fCl = feat_wrk.OpenFeatureClass(ambitos);
                ESRI.ArcGIS.Carto.IFeatureLayer lyr1;
                lyr1 = new FeatureLayer();
                lyr1.FeatureClass = fCl;
                lyr1.Name = municipio;
                map.AddLayer(lyr1);
                //se añade la capa de ámbitos sobre la del municipio agregada anteriormente
                OliviaGlob.gdb.pinta_sectores(path_gdb, ftclass_nom, 3);
                //actualiza vista
                mx_doc.UpdateContents();
                mx_doc.ActiveView.Refresh();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }

        }


        /**
        * A partir de un nombre indicado, imprime la vista actual que exista en ArcGIS en formato .pdf. Esta función se empleará cuando se ahaya cargado la plantilla de mapas correspondiente.
        */
        public void print_map(string nombre)
        {
            string path;
            IActiveView vista_activa;
            ESRI.ArcGIS.esriSystem.tagRECT export_rect;
            System.Int32 hdc;
            IEnvelope envelope;
            ESRI.ArcGIS.Output.IExport export;
            path = OliviaGlob.Paths.DirData + nombre + ".pdf";
            vista_activa = ArcMap.Document.ActiveView;
            try
            {
                //parameter check
                if (vista_activa == null || !(path.EndsWith(".pdf")))
                {
                    return;
                }
                export = new ESRI.ArcGIS.Output.ExportPDFClass();
                export.ExportFileName = path;

                // Microsoft Windows default DPI resolution
                export.Resolution = 96;
                export_rect = vista_activa.ExportFrame;
                envelope = new ESRI.ArcGIS.Geometry.EnvelopeClass();
                envelope.PutCoords(export_rect.left, export_rect.top, export_rect.right, export_rect.bottom);
                export.PixelBounds = envelope;
                hdc = export.StartExporting();
                vista_activa.Output(hdc, (System.Int16)export.Resolution, ref export_rect, null, null);

                //Termina de escribir el archivo exportado y limpia cualquier archivo intermedio que se haya creado
                export.FinishExporting();
                export.Cleanup();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        /*
        * Guarda archivo de trabajo en formato .mxd
        */
        public void guarda_mxd(string title)
        {
            System.Windows.Forms.SaveFileDialog dlg;
            ESRI.ArcGIS.ArcMapUI.IMxDocument mxdoc;
            IDocumentInfo2 doc_info;
            try
            {
                mxdoc = (ESRI.ArcGIS.ArcMapUI.IMxDocument)ArcMap.Application.Document;
                doc_info = (IDocumentInfo2)mxdoc;
                doc_info.Author = "VSM";
                doc_info.Comments += "Guardado en " + DateTime.Now.ToLongTimeString() + "\r\n";
                doc_info.Subject = "Maquetado";
                doc_info.RelativePaths = true;
                doc_info.DocumentTitle = title;
                //Se abre el dialogo para guardar un archivo .mxd
                dlg = new System.Windows.Forms.SaveFileDialog();
                dlg.Title = "Guardar Documento de Mapa Como";
                dlg.Filter = "Documentos de Mapa (*.mxd)|*.mxd";
                dlg.FileName = title;
                dlg.ShowDialog();
                //Si no se ha seleecionado un nombre de guardado para el .mxd se sale de la función
                string sFilePath = dlg.FileName;
                if (sFilePath == "")
                    return;
                
                ArcMap.Application.SaveAsDocument(sFilePath);
                doc_info.DocumentTitle = sFilePath;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                throw;
            }
        }

        /*
        * Con una Toolbox ya generada se arranca el proceso de python para generar mapas ordenados según Data Driven Pages
        */
        public void print_map_py()
        {
            ESRI.ArcGIS.Geoprocessing.IGeoProcessor2 gp = new ESRI.ArcGIS.Geoprocessing.GeoProcessorClass();
            gp.AddToolbox(@"C:\olivia\Maqueta.tbx");
            ESRI.ArcGIS.esriSystem.IVariantArray parameters = new ESRI.ArcGIS.esriSystem.VarArrayClass();
            object sev = null;

            try
            {
                gp.Execute("DDP", parameters, null);
                Console.WriteLine(gp.GetMessages(ref sev));
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                string errorMsgs = gp.GetMessages(ref sev);
                Console.WriteLine(errorMsgs);
            }
        }

        /*
        * Dilogo que permite seleccionar la plantilla de interés para la maquetación
        */
        public string selec_plantilla()
        {
            System.Windows.Forms.OpenFileDialog openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
            openFileDialog1.InitialDirectory = OliviaGlob.Paths.DirData;
            openFileDialog1.Filter = "Plantillas(*.mxd)|*.mxd";
            openFileDialog1.Title = "Selecciona la plantilla para la maquetación";

            //Muestra el diálogo para abri una plantilla que viene en formato .mxd
            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                //comprueba que sea del tipo valido
                if (openFileDialog1.SafeFileName == nomb_plantilla)
                {
                    return openFileDialog1.FileName;
                }
                else
                {
                    err_str = "No se ha seleccionado una plantilla válida" ;
                    return null;
                }
            }
            else
            {
                err_str = "No se ha seleccionado ninguna plantilla";
                return null;
            }
        }

        /*
         * Añade la escala de texto a la cartela seleccionada en la maquetación
         */
        public void pon_escala_txt(ESRI.ArcGIS.Carto.IPageLayout pPageLayout, IActiveView vista_activa)
        {
            int escala;
            IElement element;
            ITextSymbol txtsimb = null;
            IEnvelope envelope;
            IGraphicsContainer graphics;
            IMapDocument map_doc;
            IFrameElement frame_elm;
            IMapFrame map_frame;
            IMapSurroundFrame map_sf;
            IMapSurround map_surround;
            ESRI.ArcGIS.esriSystem.UID carto_uid;
            IScaleText2 scale_txt;
            Font font;
            ESRI.ArcGIS.Geometry.IPoint pto;
            ESRI.ArcGIS.esriSystem.INumericFormat numeric_format;
            IMap map = ((ESRI.ArcGIS.ArcMapUI.IMxDocument)(ArcMap.Application.Document)).FocusMap;

            //INCORPORA LAS ESCALAS A LA PLANTILLA DEL MAPA
            map_doc = (IMapDocument)ArcMap.Application.Document;
            graphics = (IGraphicsContainer)pPageLayout;
            frame_elm = graphics.FindFrame(map);
            map_frame = (IMapFrame)frame_elm;

            carto_uid = new ESRI.ArcGIS.esriSystem.UID();
            carto_uid.Value = "esriCarto.ScaleText";
            map_sf = map_frame.CreateSurroundFrame(carto_uid, null); //Crear el nuevo MapSurroundFrame asociado con el MapFrame
            map_surround = map_sf.MapSurround;

            //AÑADE LA ESCALA EN FORMATO TEXTO. LA ESCALA HAY QUE REDONDEARLA POR LO QUE LO PIRMERO ES CONOCER LA ESCALA DE VISUALIZACION Y REDONDEARLA. SE MODIFICARÁ TAMBIÉN LA ESCALA DE VISUALIZACIÓN.
            //se redondea la escala en formato texto.
            if (map.MapScale < 1000)
            {
                escala = ((int)(map.MapScale + 100) / 100) * 100;//se utiliza la cifra 100 porque es el numero al que se redondea (ej de escalas: 100, 300,400,500...900)
                map.MapScale = escala;
            }
            else if (map.MapScale < 10000)
            {
                escala = ((int)(map.MapScale + 500) / 500) * 500;//se utiliza la cifra 500 porque es el numero al que se redondea (ej de escalas: 1500, 2000, 2500, 3000...9500)
                map.MapScale = escala;
            }
            else if (map.MapScale < 100000)
            {
                escala = ((int)(map.MapScale + 5000) / 5000) * 5000;//se utiliza la cifra 5000 porque es el numero al que se redondea (ej de escalas: 50000, 55000, 60000, 65000...95000)
                map.MapScale = escala;
            }
            else if (map.MapScale < 1000000)
            {
                escala = ((int)(map.MapScale + 50000) / 50000) * 50000;//se utiliza la cifra 50000 porque es el numero al que se redondea (ej de escalas: 150000, 200000, 250000, 300000...950000)
                map.MapScale = escala;
            }
            //SE AÑADE LA ESCALA DE TEXTO
            scale_txt = (IScaleText2)map_surround;
            scale_txt.Name = "Scale Text";
            numeric_format = new ESRI.ArcGIS.esriSystem.NumericFormatClass();
            numeric_format.UseSeparator = true;
            numeric_format.RoundingValue = 0;
            //se indican las características que tiene la escala de texto
            scale_txt.Style = esriScaleTextStyleEnum.esriScaleTextAbsolute;
            scale_txt.NumberFormat = (ESRI.ArcGIS.esriSystem.INumberFormat)numeric_format; //se indica formato numérico.
            scale_txt.Separator = "/";
            txtsimb = scale_txt.Symbol;
            font = new Font("Arial Narrow", 10, FontStyle.Regular);
            txtsimb.Font = (stdole.IFontDisp)OLE.GetIFontDispFromFont(font);
            txtsimb.HorizontalAlignment = esriTextHorizontalAlignment.esriTHACenter;
            txtsimb.VerticalAlignment = esriTextVerticalAlignment.esriTVACenter;
            scale_txt.Symbol = txtsimb;
            scale_txt.Refresh();

            element = (IElement)map_sf;
            envelope = new ESRI.ArcGIS.Geometry.EnvelopeClass();
            pto = new ESRI.ArcGIS.Geometry.PointClass();
            pto.PutCoords(36.1, 1.8);
            envelope.PutCoords(35.2, 1.6, 37, 2);
            envelope.CenterAt(pto);
            element.Geometry = envelope; //poner la geometría del map surround frame

            pon_grafico(element, vista_activa);
        }

        /*
        * Añade a la plantilla seleccionada el texto correpondiente del propertygrid del editor de textos
        */
        public void pon_txt_prop(string capa, IActiveView vista_activa, int modo, String texto, Font fuente)
        {
            ITextElement txt_elm;
            IFrameProperties frameProperties;
            ITextElement textElement;
            IElement element;
            ISimpleTextSymbol txt_simb;
            IEnvelope envelope;                        
            
            txt_elm = new ParagraphTextElementClass();
            //castear
            frameProperties = (IFrameProperties)txt_elm;
            textElement = (ITextElement)txt_elm;
            element = (IElement)txt_elm;
            frameProperties.Background = null;
            frameProperties.Border = null;
            //se pone la simbologia que se ha indicado en el dialogo. 
            //Si no se ha modificado la simbología se pone la por defecto para cada caso.
            txt_simb = new TextSymbolClass();
            txt_simb.Font = (stdole.IFontDisp)OLE.GetIFontDispFromFont(fuente);
            if (modo < 3)
                txt_simb.HorizontalAlignment = esriTextHorizontalAlignment.esriTHACenter;
            else if (modo > 2)
                txt_simb.HorizontalAlignment = esriTextHorizontalAlignment.esriTHALeft;

            txt_simb.VerticalAlignment = esriTextVerticalAlignment.esriTVACenter;
            //se incorpora al elemento de texto la simbologia creada
            textElement.Symbol = txt_simb;
            textElement.Text = "- " + texto;
            //Se pone  el tamaño y la ubicación de la caja de texto (ie. inches)  
            envelope = new ESRI.ArcGIS.Geometry.EnvelopeClass();
            if (modo == 0)
                envelope.PutCoords(33.9, 19.4, 41.3, 21.1);
            else if (modo == 1)
                envelope.PutCoords(33.9, 18.2, 41.3, 19.3);
            else if (modo == 2)
                envelope.PutCoords(33.9, 16.4, 41.3, 18.3);
            else if (modo == 3) //frecuencia
                envelope.PutCoords(35.08, 14.20, 35.08 + 3.1, 14.20 + 0.75);
            else if (modo == 4) //turno
                envelope.PutCoords(35.08, 13.36, 35.08 + 3.1, 13.36 + 0.75);
            else if (modo == 5) //equipo        
                envelope.PutCoords(37.52, 14.20, 37.52 + 3.1, 14.20 + 0.75);
            else if (modo == 6) //info adi
                envelope.PutCoords(37.52, 13.36, 37.52 + 3.1, 13.36 + 0.75);
            element.Geometry = envelope;

            //añadir la caja de texto a la plantilla del mapa
            pon_grafico(element, vista_activa);            
        }

        /*
        * añade a la plantilla seleccionada un recuadro donde se situarán la Frecuencia del servicio, el turno y el Equipo encragado
        */
        public void pon_recuadro(IRgbColor color, IActiveView vista_activa)
        {
            IElement elme;
            ILineElement lineElement;
            ISimpleLineSymbol simpleLineSymbol;
            IPolyline pPolyline;
            IPoint p1, p2, p3, p4, p5;
            IPointCollection pPointColl;
            //se marcan las coordenadas donde irá el recuadro
            p1 = new PointClass();
            p1.X = 34.1; p1.Y = 10.1;
            p2 = new PointClass();
            p2.X = 34.1; p2.Y = 15.5;
            p3 = new PointClass();
            p3.X = 41.2; p3.Y = 15.5;
            p4 = new PointClass();
            p4.X = 41.2; p4.Y = 10.1;
            p5 = new PointClass();
            p5.X = 34.1; p5.Y = 10.1;
            //se añade a una coleccion de puntos
            pPolyline = new PolylineClass();
            pPointColl = (IPointCollection)pPolyline;
            pPointColl.AddPoint(p1);
            pPointColl.AddPoint(p2);
            pPointColl.AddPoint(p3);
            pPointColl.AddPoint(p4);
            pPointColl.AddPoint(p5);
            //se indica la simbología con la que se representará el recuadro
            elme = new LineElement();
            lineElement = (ILineElement)elme;
            simpleLineSymbol = new SimpleLineSymbolClass();
            color.Red = 0;
            color.Green = 38;
            color.Blue = 115;
            simpleLineSymbol.Color = color;
            simpleLineSymbol.Width = 1;
            lineElement.Symbol = simpleLineSymbol;
            //Se pone  el tamaño y la ubicación del recuadro (ie. inches)  
            elme.Geometry = pPolyline;
            //añadir el recuadro la plantilla del mapa
            pon_grafico(elme, vista_activa);
        }

        /*
         * Añade en la plantilla los distintos elemenots que sae quieren incorporar (titulo, escala, fecha, etc)
         */
        public void pon_grafico(IElement element, IActiveView vista_activa)
        {
            IGraphicsContainer grafico;
            IGraphicsContainerSelect graph_sel;

            grafico = (IGraphicsContainer)ArcMap.Document.PageLayout;
            grafico.AddElement(element, 0);
            graph_sel = (IGraphicsContainerSelect)grafico;
            graph_sel.UnselectAllElements();
            vista_activa.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
        }

        /*
         * Realiza el proceso completo de maquetación. Permite la selección de las capas que se quieren maquetar, la plantilla que se va a utlizar, los t´tilos e informaciones adicionales que se quieren añadir, etc.
         */
        public bool maqueta(IntPtr handle)
        {
            int seleccionados, n_mapas, i;
            string muni, foto, dir_plant, name_plant;
            IPageLayout pPageLayout;
            IUniqueValueRenderer valor_unico;
            IDatasetName shp_dname;
            IWorkspace wspace;
            IWorkspaceFactory wsf;
            IEnumDatasetName grupos;
            ListCapasMaqueta lista;
            IMapDocument map_doc;
            IApplication app;
            IFeatureWorkspace feat_wrk = null;
            IMap map;
            
            app = ArcMap.Application;
            //se importa algún shape si fuera necesario a la GDB de interés
            //se seleeciona la GDB de donde se extraerán las capas que se quieren maquetar
            string text_reint = "¿Desea cancelar el proceso de maquetación?";
            wspace = FunGDB.selec_gdb("Seleccionar GDB que contiene las capas a maquetar", handle.ToInt32(), text_reint);
            if (wspace == null)
            {
                err_str = "No se ha seleccionado ninguna GDB. Se cancela el proceso de maquetación.";
                return false;
            }
            //se genera un listado con los grupos de la GDB existentes
            lista = new ListCapasMaqueta();
            grupos = wspace.get_DatasetNames(esriDatasetType.esriDTFeatureDataset);
            //se muestra un listado con las capas que pertenecen a la GDB que terminan por "_Sector" o "_Ruta"
            lista.inicia(grupos);
            lista.ShowDialog();
            if ((lista.capas_maquetar == null) || (lista.capas_maquetar.Length == 0))
            {
                err_str = "No se ha seleccionado ninguna capa para la maquetación";
                return false;
            }
            else
            {
                //se maqueta cada capa seleccionada
                seleccionados = lista.capas_maquetar.Length;
                for (i = 0; i < seleccionados; i++)
                {
                    try
                    {
                        //hay que eliminar las posibles capas que se encuentren abiertas para realizar bien la maquetación
                        limpia_vista();

                        shp_dname = OliviaGlob.mapa.municipio(wspace.PathName, lista.capas_maquetar[i], out muni);
                        wsf = new FileGDBWorkspaceFactoryClass();
                        feat_wrk = (IFeatureWorkspace)wsf.OpenFromFile(wspace.PathName, 0);

                        pPageLayout = OliviaGlob.mapa.pon_plantilla(out dir_plant);
                        if (pPageLayout == null)
                            return false;
                                                
                        valor_unico = OliviaGlob.gdb.pinta_sectores(wspace.PathName, lista.capas_maquetar[i], 2);
                        if (valor_unico == null)
                        {
                            limpia_vista();
                            return false;
                        }

                        //si es capa de ruta, pinta los puntos de control
                        if (lista.capas_maquetar[i].EndsWith(OliviaGlob.gdb.name_ruta_out))
                        {
                            //se abre la capa de puntos de control y se pintan por el sector al que pertenecen.
                            string shape = lista.capas_maquetar[i].Substring(0, lista.capas_maquetar[i].IndexOf(OliviaGlob.gdb.name_ruta_out));
                            OliviaGlob.gdb.ptos_control(wspace.PathName + "\\" + shape + OliviaGlob.gdb.name_control_out);
                        }

                        name_plant = System.IO.Path.GetFileName(dir_plant);
                        //INSERTAR IMAGEN DEL CLIENTE
                        foto = OliviaGlob.mapa.pon_imag("Selecciona la imagen del cliente", 0, 1);
                        foto = OliviaGlob.mapa.pon_imag("Selecciona la imagen del licitador", 1, 1);
                        
                        //RELLENA LOS ELEMENTOS DE LA CARTELA
                        if (!OliviaGlob.mapa.rellena_plantilla(pPageLayout, shp_dname, name_plant, 0))
                        {
                            limpia_vista();
                            return false;
                        }

                        //SE AÑADEN LAS CAPAS QUE CONFORMAN EL MAPA DE SITUACIÓN (CAPA CON EL MUNICIPIO AL QUE PERTENECEN LOS ÁMBITOS Y LA CAPA DE ÁMBITOS SUPERPUESTA
                        ESRI.ArcGIS.ArcMapUI.IMxDocument mx_doc = (ESRI.ArcGIS.ArcMapUI.IMxDocument)(ArcMap.Application.Document);
                        n_mapas = mx_doc.Maps.Count;
                        //se pasa el foco al grupo de capas (Data Frame) del mapa de situación
                        //Así cuando añadamos nuevas capas se añadirán al marco de datos que compone el mapa de situación.
                        map = ((ESRI.ArcGIS.ArcMapUI.IMxDocument)(ArcMap.Application.Document)).FocusMap;
                        for (int j = 0; j < n_mapas; j++)
                        {
                            map = mx_doc.Maps.get_Item(j);
                            if ((map.Name == OliviaGlob.df_secund) || (map.Name == OliviaGlob.df_secund1))
                                break;
                        }
                        OliviaGlob.mapa.mapa_localizacion(map, feat_wrk, shp_dname.Name, muni, wspace.PathName, lista.capas_maquetar[i]);

                        map_doc = (IMapDocument)app.Document;

                        guarda_mxd(lista.capas_maquetar[i]);

                    }
                    catch (Exception ex)
                    {
                        OliviaGlob.borra_files();
                        MessageBox.Show(ex.Message);
                        limpia_vista();
                        FunGDB.libera(feat_wrk);
                        return false;
                    }
                }
            }
            FunGDB.libera(feat_wrk);
            return true;
        }

        /*
         * Elimina las capas que se puedan encontrar abiertas en el espacio de trabajo
         */
        public void limpia_vista()
        {
            int nmapas;
            ESRI.ArcGIS.ArcMapUI.IMxDocument mx_doc;
            IApplication app;
            IMap map;

            app = ArcMap.Application;
            mx_doc = (ESRI.ArcGIS.ArcMapUI.IMxDocument)(app.Document);

            nmapas = mx_doc.Maps.Count;
            for (int j = 0; j < nmapas; j++)
            {
                map = mx_doc.Maps.get_Item(j);
                if ((map.Name == OliviaGlob.df_secund) || (map.Name == OliviaGlob.df_secund1))
                {
                    map.ClearLayers();
                    //actuliza la vista del mapa para que se visualice 
                    mx_doc.UpdateContents();
                    mx_doc.ActiveView.Refresh();
                }
                else if (map.Name == OliviaGlob.df_princip)
                {
                    map.ClearLayers();
                    //actuliza la vista del mapa para que se visualice 
                    mx_doc.UpdateContents();
                    mx_doc.ActiveView.Refresh();
                }
            }
        }

    }
}
