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

using OliviaDef;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.DataSourcesGDB;
using System.Diagnostics;
using ESRI.ArcGIS.Geometry;

namespace OliviaAddIn
{
    /**
    *	@file LimpiezaDlg.cs
    *	Clase de la ventana de configuración de la herramienta de Limpieza Viaria.
    *	Contiene el manejo de sus eventos como el Click o la actualización de su estado.
    */
    /**
    *	Clase de la ventana de configuración de la herramienta de Limpieza Viaria.
    *	Contiene el manejo de sus eventos como el Click o la actualización de su estado.
    */
    public partial class LimpiezaDlg : Form
    {
        //*************************************************************************************
        //Variables 
        /**
         *	Modos de selección de los niveles y zonas.
         */
        public enum ModosNiv
        {
            ModTodos,               //<Selecciona todos los niveles
            ModSel,                 //<Deja seleccionar al usuario los niveles
            ModNing,                //<No selecciona ningún nivel
        };
        /**
         * 
         */
        public static string vel_nodef = "Def. Vías";            
        /**
        * Clase para la lista de ámbitos, relaciona el tipo de ámbito con su texto
        */
        class AmbitsList
        {
            private LimpiezaDef.AmbitsTra mi_amb_i;
            private string mi_amb_str;

            public AmbitsList(LimpiezaDef.AmbitsTra amb_i, string amb_str)
            {
                this.mi_amb_i = amb_i;
                this.mi_amb_str = amb_str;
            }
            public LimpiezaDef.AmbitsTra amb_i
            {
                get { return mi_amb_i; } 
                set { mi_amb_i = value; }
            }
            public string amb_str
            {
                get { return mi_amb_str; }
                set { mi_amb_str = value; }
            }
        }   
        bool hay_alguno_des =false;
        /**
        *	Clase para el checklistbox de ámbitos
        */
        class CheckedListBoxEx : CheckedListBox
        {
            public AmbitsList[] m_ambs_list = null;
            public bool[] m_ambs_gdb = null;
            public void pon_ambs_list(AmbitsList[] ambs)
            {
                m_ambs_list = ambs;
            }
            public void pon_ambs_gdb(bool[] gdb)
            {
                m_ambs_gdb = gdb;
            }
            protected override void OnDrawItem(DrawItemEventArgs e)
            {
                if ((m_ambs_list != null) && (m_ambs_gdb != null) && (e.Index < m_ambs_list.Length) && 
                    ((int)m_ambs_list[e.Index].amb_i < m_ambs_gdb.Length) && ((int)m_ambs_list[e.Index].amb_i >= 0) &&
                    (!m_ambs_gdb[(int)m_ambs_list[e.Index].amb_i]))
                {
                    System.Windows.Forms.VisualStyles.CheckBoxState state = System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedDisabled;
                    Size glyphSize = CheckBoxRenderer.GetGlyphSize(e.Graphics, state);
                    CheckBoxRenderer.DrawCheckBox(
                        e.Graphics,
                        new System.Drawing.Point(e.Bounds.X + 1, e.Bounds.Y + 1), // add one pixel to align the check gliph properly
                        new Rectangle(
                            new System.Drawing.Point(e.Bounds.X + glyphSize.Width + 3, e.Bounds.Y), // add three pixels to align text properly
                            new Size(e.Bounds.Width - glyphSize.Width, e.Bounds.Height)),
                        m_ambs_list[e.Index].amb_str,
                        this.Font,
                        TextFormatFlags.Left, // text is centered by default
                        false,
                        state);
                }
                else
                {
                    base.OnDrawItem(e);
                }
            }
        }
        /**
        * Array de variables de tipo AmbitsList para mostrar en la lista, se rellena al elegir el tipo de tratamiento
        */
        ArrayList ambs_list = null;
        /**
        * Array de variables de tipo AmbitsList para mostrar en la lista, para la opción editable (puedes elegir cualquier ámbito)
        */
        ArrayList ambs_list_tod_lin = null;
        /**
        * Array de variables de tipo AmbitsList para mostrar en la lista, para la opción editable (puedes elegir cualquier ámbito)
        */
        ArrayList ambs_list_tod_pto = null;
        /**
        * Array de variables de tipo AmbitsList para mostrar en la lista, para la opción genérica (puedes elegir los ejes de las calles)
        */
        ArrayList ambs_list_eje = null;
        /**
         * Matriz que da true aquellos ámbitos de trabajo que están contemplados en .gdb una vez leida
         */
        bool[] amb_tra_gdb = null;        
        /**
         *	Instancia que contiene las variables de la clase
         */
        public Limpieza limp = null;
        /**
        * Cadena general para indicar los errores
        */
        public String err_str = "";
        //*************************************************************************************
        //Métodos
        public LimpiezaDlg()
        {            
            InitializeComponent();
            limp = new Limpieza();
            inicia();
        }

        /**
         * Inicializa los elementos de la ventana: rellena los boxes etc
         */
        private bool inicia()
        {          
            try
            {   
                //rellena los checkboxes y listboxes
                LimpiezaDef.rellena_matrs();
                if (OliviaGlob.demo_id == true)
                {
                    LimpiezaDef.tipos_tto_str = new string[1];
                    LimpiezaDef.tipos_tto_str[0] = "Vaciado de papeleras";
                }
                comboBox_tto.Items.Clear();
                comboBox_tto.Items.AddRange(LimpiezaDef.tipos_tto_str);
                checkedListBox_amb.Items.Clear();
                amb_tra_gdb = OliviaGlob.gdb_limp.lee_amb_gdb(limp);
                checkedListBox_amb.pon_ambs_gdb(amb_tra_gdb);
                
                //habilita y deshabilita botones
                textBox_v_despl.Enabled = false;
                //no permite visualizar los elementos del ancho de vía que se acivará cuando se seleccione la opción genérica de ejes de calle
                label_ancho_medio.Visible = false;
                textBox_ancho_medio.Visible = false;
                label_uds_anch_med.Visible = false;
                //no permite visualizar los elementos del umbral de recogida de basuras
                label_umbral_recog.Visible = false;
                tbox_umbral_recog.Visible = false;
                //pone el numero de sectores por defecto
                numericUpDown_sectores.Value = (decimal)limp.n_secdef;
                //rellena los tiempos 
                inicia_timepickers();
                //rellena el factor de tráfico
                textBox_traf.Text = limp.trafico.ToString();
                textBox_buff.Text = OliviaGlob.buff_export.ToString();
                
                ////////////////////////////////////////////////////////////////
                //pone los textos iniciales
                instal_sel.Text = limp.text_selec_instal;
                label_niv.Text = limp.text_selec_nive;
                label_restric.Text = limp.text_selec_rest;
                label_zon.Text = limp.text_selec_zonas;
                label_capa_limp.Text = limp.text_capa_limp;

                if (!OliviaGlob.gdb_limp.comprueba_campos_limp(limp))
                {
                    MessageBox.Show(limp.err_st, "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return false;
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Error al iniciar la ventana de Limpieza", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            return true;
        }  

        /**
         * Inicializa los controles de los tiempos
         */
        public void inicia_timepickers()
        {
            int[] hm;
            DateTime tmin = new DateTime(2017,01,01,0,0,0);
            DateTime tmax = new DateTime(2017,01,02,0,0,0);

            //t tratamiento
            cambia_tiempo_tto();

            //t convenio
            hm = OliviaGlob.dame_h_m(limp.t_conv);
            dateTimePicker_t_conv.MinDate = tmin;
            dateTimePicker_t_conv.MaxDate = tmax;
            dateTimePicker_t_conv.Value = new DateTime(2017,01,01,hm[0],hm[1],0);

            //t descanso del personal
            hm = OliviaGlob.dame_h_m(limp.t_descan);
            dateTimePicker_t_desc.MinDate = tmin;
            dateTimePicker_t_desc.MaxDate = tmax;
            dateTimePicker_t_desc.Value = new DateTime(2017, 01, 01, hm[0], hm[1], 0);

            //t carga y descarga
            hm = OliviaGlob.dame_h_m(limp.t_descarg);
            dateTimePicker_carg.MinDate = tmin;
            dateTimePicker_carg.MaxDate = tmax;
            dateTimePicker_carg.Value = new DateTime(2017, 01, 01, hm[0], hm[1], 0);

            //t desplazamiento inicio/fin
            hm = OliviaGlob.dame_h_m(limp.t_despl_insta);
            dateTimePicker_despl.MinDate = tmin;
            dateTimePicker_despl.MaxDate = tmax;
            dateTimePicker_despl.Value = new DateTime(2017, 01, 01, hm[0], hm[1], 0);

            //hora de inicio de la jornada
            hm = OliviaGlob.dame_h_m(limp.h_ini);
            dateTimePicker_h_inicio.MinDate = tmin;
            dateTimePicker_h_inicio.MaxDate = tmax;
            dateTimePicker_h_inicio.Value = new DateTime(2017, 01, 01, hm[0], hm[1], 0);
        }

        /**Pone en la lista los ámbitos de trabajo en función del tipo de tratamiento
         * Los comunes y no comunes a sus opciones. Luego checkea los correspondientes a la opción
         */
        private ArrayList pon_ambitos()
        {
            ArrayList lista = null;
            try
            {
                if (limp.tipo_tto == (int)LimpiezaDef.TiposTto.TtoNoDef)
                {
                    checkedListBox_amb.Items.Clear();
                    return lista;
                }

                rellena_amb_list();
                if ((comboBox_amb.SelectedIndex == 0) && ((limp.tipo_tto < (int)LimpiezaDef.TiposTto.TtoPapeVaci) || (limp.tipo_tto >= (int)LimpiezaDef.TiposTto.TtoCustom)))
                {
                    checkedListBox_amb.DataSource = ambs_list_tod_lin;
                    checkedListBox_amb.DisplayMember = "amb_str";
                    lista = ambs_list_tod_lin;
                }
                else if ((comboBox_amb.SelectedIndex == 0) && (limp.tipo_tto > (int)LimpiezaDef.TiposTto.TtoCaidaHoja))
                {
                    checkedListBox_amb.DataSource = ambs_list_tod_pto;
                    checkedListBox_amb.DisplayMember = "amb_str";
                    lista = ambs_list_tod_pto;
                }
                else if (comboBox_amb.SelectedIndex == 1)
                {
                    checkedListBox_amb.DataSource = ambs_list_eje;
                    checkedListBox_amb.DisplayMember = "amb_str";
                    lista = ambs_list_eje;
                }
                else
                {
                    checkedListBox_amb.DataSource = ambs_list;
                    checkedListBox_amb.DisplayMember = "amb_str";
                    lista = ambs_list;
                }
                checkedListBox_amb.Enabled = false; //se inicia deshabilitado
                check_ambitos(-1, lista); //para resetear los checks

                //comprueba si están en la gdb, avisa al listbox para que pinte los que no
                hay_alguno_des = false;
                checkedListBox_amb.pon_ambs_list(lista.Cast<AmbitsList>().ToArray());
                for (int i = 0; i < lista.Count; i++)
                {
                    if (!amb_tra_gdb[(int)((AmbitsList)lista[i]).amb_i])
                    {
                        hay_alguno_des = true;
                        break;
                    }
                }
                //si hay algún ámbito que no está en la gdb, pone el tooltip
                if (hay_alguno_des)
                {
                    label_checkambs.ForeColor = System.Drawing.SystemColors.HotTrack;
                    toolTip.SetToolTip(label_checkambs, "Aparecen deshabilitados los ámbitos que no tienen entidades en la base de datos");
                }
                else
                {
                    label_checkambs.ForeColor = System.Drawing.SystemColors.Control;
                    toolTip.SetToolTip(label_checkambs, "");
                }
                return lista;
            }
            catch (Exception)
            {
                MessageBox.Show("Error al poner los ámbitos", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }

        }

        /**
         * Rellena una lista con los ámbitos comunes y no comunes para mostrar en el listbox en función del tipo de tratamiento
         */
        private void rellena_amb_list()
        {
            bool[] amb_val;
            bool[] amb_val_tod;
            bool[] amb_val_eje;

            //lo hace para todos los tratamientos excepto para el Customizble ya que sólo se quieren mostrar las opciones alternaitvas al tratamiento
            if (limp.tipo_tto < (int)LimpiezaDef.TiposTto.TtoCustom)
            {
                //pide un array de booleanos donde es true en las posiciones de los ámbitos comunes
                amb_val = limp.dame_amb(limp.tipo_tto);
                //crea un array con el número de elementos del array anterior que sean true
                ambs_list = new ArrayList(amb_val.Count(x => x));//cuenta los trues
                //rellena el array apuntando los índices y los textos correspondientes a los trues
                for (int i = 0; i < amb_val.Length; i++)
                {
                    if (amb_val[i])
                    {
                        ambs_list.Add(new AmbitsList((LimpiezaDef.AmbitsTra)i,LimpiezaDef.ambits_tra_str[i]));
                    }
                }
            }

            //se hace lo mismo para la opción que da la posibilidad de seleccionar cualquier ámbito lineal
            amb_val_tod = limp.ambs_val[(int)LimpiezaDef.TiposTto.TtoCustom].ambs_ops[0].ambs;
            ambs_list_tod_lin = new ArrayList(amb_val_tod.Count(x => x));
            for (int i = 0; i < amb_val_tod.Length; i++)
            {
                if (amb_val_tod[i])
                {
                    ambs_list_tod_lin.Add(new AmbitsList((LimpiezaDef.AmbitsTra)i, LimpiezaDef.ambits_tra_str[i]));
                }
            }

            //se hace lo mismo para la opción que da la posibilidad de seleccionar cualquier ámbito puntual
            amb_val_tod = limp.ambs_val[(int)LimpiezaDef.TiposTto.TtoCustom].ambs_ops[1].ambs;
            ambs_list_tod_pto = new ArrayList(amb_val_tod.Count(x => x));
            for (int i = 0; i < amb_val_tod.Length; i++)
            {
                if (amb_val_tod[i])
                {
                    ambs_list_tod_pto.Add(new AmbitsList((LimpiezaDef.AmbitsTra)i, LimpiezaDef.ambits_tra_str[i]));
                }
            }

            //se hace lo mismo para la opción que permite seleccionar únicamente los ejes de calle
            amb_val_eje = limp.ambs_val[(int)LimpiezaDef.TiposTto.TtoCustom].ambs_ops[2].ambs;
            ambs_list_eje = new ArrayList(amb_val_eje.Count(x => x));
            for (int i = 0; i < amb_val_eje.Length; i++)
            {
                if (amb_val_eje[i])
                {
                    ambs_list_eje.Add(new AmbitsList((LimpiezaDef.AmbitsTra)i, LimpiezaDef.ambits_tra_str[i]));
                }
            }
        }

        /**Checkea de la lista los ámbitos de trabajo en función del tipo de tratamiento
         * y la opción elegida
         */
        private void check_ambitos(int iop, ArrayList lista)
        {
            bool check = false;
            if (lista == null)
                return;
            for (int i = 0; i < lista.Count; i++)
            {
                check = false;
                if (iop < 0)
                {
                    //para reseteo
                    checkedListBox_amb.SetItemChecked(i,false);
                }
                else if (iop == 0)
                {
                    //dependiendo del tratamiento seleccionado en la opción 0(Editable) se seleccionarán diferentes opciones del TtoCustom(diferenciando entre ttos lineales o puntuales)
                    //para ámbitos lineales
                    if (limp.tipo_tto < (int)LimpiezaDef.TiposTto.TtoPapeVaci)
                    {
                        check = limp.ambs_val[(int)LimpiezaDef.TiposTto.TtoCustom].ambs_ops[iop].ambs[(int)((AmbitsList)lista[i]).amb_i]
                            && amb_tra_gdb[(int)((AmbitsList)lista[i]).amb_i];
                        checkedListBox_amb.SetItemChecked(i, check);
                    }
                    //para ámbitos puntuales
                    else if ((limp.tipo_tto > (int)LimpiezaDef.TiposTto.TtoCaidaHoja) && (limp.tipo_tto < (int)LimpiezaDef.TiposTto.TtoCustom))
                    {
                        //es la opción Genérica que es la opción 1 del TtoCustom, de ahi que el índice sea [iop + 1]
                        check = limp.ambs_val[(int)LimpiezaDef.TiposTto.TtoCustom].ambs_ops[iop + 1].ambs[(int)((AmbitsList)lista[i]).amb_i]
                            && amb_tra_gdb[(int)((AmbitsList)lista[i]).amb_i];
                        checkedListBox_amb.SetItemChecked(i, check);
                    }
                    //para ámbito custom
                    else
                    {
                        check = limp.ambs_val[(int)LimpiezaDef.TiposTto.TtoCustom].ambs_ops[iop].ambs[(int)((AmbitsList)lista[i]).amb_i]
                            && amb_tra_gdb[(int)((AmbitsList)lista[i]).amb_i];
                        checkedListBox_amb.SetItemChecked(i, check);
                    }
                }
                else if (iop == 1)
                {
                    //es la opción Genérica que es la opción 2 del TtoCustom, de ahi que el índice sea [iop + 1]
                    check = limp.ambs_val[(int)LimpiezaDef.TiposTto.TtoCustom].ambs_ops[iop + 1].ambs[(int)((AmbitsList)lista[i]).amb_i]
                     && amb_tra_gdb[(int)((AmbitsList)lista[i]).amb_i];
                    checkedListBox_amb.SetItemChecked(i, check);
                }
                else if ((iop - 2) < (limp.ambs_val[(int)limp.tipo_tto].n_ops))
                {
                    //pone el check si el elemento que aparece en la lista porque es común o no común 
                    //esa opción en concreto le tiene
                    check = limp.ambs_val[(int)limp.tipo_tto].ambs_ops[iop-2].ambs[(int)((AmbitsList)lista[i]).amb_i]
                        && amb_tra_gdb[(int)((AmbitsList)lista[i]).amb_i];
                    checkedListBox_amb.SetItemChecked(i, check);
                }
                    
            }
        }

        /**
         * Añade a la lista de ambitos seleccionados los que están checkeados de la lista de posibles
         */
        private bool lee_ambitos()
        {
            limp.amb_tra_sel = new bool[(int)LimpiezaDef.AmbitsTra.AmbN];   //reinicia los ambitos seleccionados
            if (checkedListBox_amb.CheckedItems.Count == 0)
                return false;
           else if ((comboBox_amb.SelectedIndex == 0) && (limp.tipo_tto < (int)LimpiezaDef.TiposTto.TtoPapeVaci))
            {
                for (int i = 0; i < checkedListBox_amb.Items.Count; i++)
                {
                    //lo pone a true si ese elemento está checkeado, para lo que coge el índice al array de ámbitos de ese elemento
                    if (checkedListBox_amb.GetItemChecked(i))
                        limp.amb_tra_sel[(int)((AmbitsList)ambs_list_tod_lin[i]).amb_i] = true;
                }
            }
            else if ((comboBox_amb.SelectedIndex == 0) && (limp.tipo_tto >= (int)LimpiezaDef.TiposTto.TtoPapeVaci))
            {
                for (int i = 0; i < checkedListBox_amb.Items.Count; i++)
                {
                    //lo pone a true si ese elemento está checkeado, para lo que coge el índice al array de ámbitos de ese elemento
                    if (checkedListBox_amb.GetItemChecked(i))
                        limp.amb_tra_sel[(int)((AmbitsList)ambs_list_tod_pto[i]).amb_i] = true;
                }
            }
            else if (comboBox_amb.SelectedIndex == 1)
            {
                for (int i = 0; i < checkedListBox_amb.Items.Count; i++)
                {
                    //lo pone a true si ese elemento está checkeado, para lo que coge el índice al array de ámbitos de ese elemento
                    if (checkedListBox_amb.GetItemChecked(i))
                        limp.amb_tra_sel[(int)((AmbitsList)ambs_list_eje[i]).amb_i] = true;
                }
            }
           else
            {
                for (int i = 0; i < checkedListBox_amb.Items.Count; i++)
                {
                    //lo pone a true si ese elemento está checkeado, para lo que coge el índice al array de ámbitos de ese elemento
                    if (checkedListBox_amb.GetItemChecked(i))
                        limp.amb_tra_sel[(int)((AmbitsList)ambs_list[i]).amb_i] = true;
                }
            }
            if (limp.amb_tra_sel[(int)LimpiezaDef.AmbitsTra.AmbEjeCalle])//si es ámbito tipo eje de calle 
            {
                if (limp.uds_t_tto == (int)GeneralDef.OlvTiposTto.OlvTipTtoMh)
                    limp.uds_t_tto = (int)GeneralDef.OlvTiposTto.OlvTipTtoMh_eje;
                else if (limp.uds_t_tto == (int)GeneralDef.OlvTiposTto.OlvTipTtoM2h)
                    limp.uds_t_tto = (int)GeneralDef.OlvTiposTto.OlvTipTtoM2h_eje;
            }
            return true;
        }

        /**
         * Cambio el tiempo del tratamiento en función del tipo de tratamiento seleccionado
         */
        private void cambia_tiempo_tto()
        {
            if (limp.tipo_tto == (int)LimpiezaDef.TiposTto.TtoNoDef)
            {
                //no está definido
                label_t_tto.Text = "";
                textBox_t_tto.Text = "";
                textBox_t_tto.Enabled = false;
                label_t_tto_def.Text = "Tiempo de tratamiento";
                return;
            }
            else if (limp.tipo_tto >= (int)LimpiezaDef.TiposTto.TtoPapeVaci)
            {
                //tipo puntual, el tiempo es en minutos
                label_t_tto.Text = "min";
                label_t_tto_def.Text = "Tiempo de tratamiento";
                limp.uds_t_tto = (int)OliviaDef.GeneralDef.OlvTiposTto.OlvTipTtoMin;
            }
            else if ((limp.tipo_tto == (int)LimpiezaDef.TiposTto.TtoBarrMecCalz) || 
                (limp.tipo_tto == (int)LimpiezaDef.TiposTto.TtoBaldMecCalz))
            {
                //tipo lineal, es velocidad en m/h
                label_t_tto.Text = "m/h";
                label_t_tto_def.Text = "Veloci. de tratamiento";
                limp.uds_t_tto = (int)OliviaDef.GeneralDef.OlvTiposTto.OlvTipTtoMh;
            }
            else
            {
                //tipo lineal, es velocidad en m2/h
                label_t_tto.Text = "m2/h";
                label_t_tto_def.Text = "Veloci. de tratamiento";
                limp.uds_t_tto = (int)OliviaDef.GeneralDef.OlvTiposTto.OlvTipTtoM2h;
            }

            textBox_t_tto.Enabled = true;
            textBox_t_tto.Text = LimpiezaDef.tiempos_tto[(int)limp.tipo_tto].ToString();
        }    

        /**
         * Lee los elementos de la ventana y guarda los parámetros
         */
        private bool lee()
        {
            string str_aux;

            try
            {
                //lee el tipo de tratamiento
                if (OliviaGlob.demo_id == true)
                {
                    if (comboBox_tto.SelectedIndex != -1)
                        limp.tipo_tto = (int)LimpiezaDef.TiposTto.TtoPapeVaci;
                }
                else
                    limp.tipo_tto = comboBox_tto.SelectedIndex;

                if (limp.tipo_tto == (int)LimpiezaDef.TiposTto.TtoNoDef)
                {
                    err_str = "No se ha seleccionado ningún Tipo de Tratamiento";
                    return false;
                }

                //lee el ámbito seleccionado
                if (!lee_ambitos())
                {
                    err_str = "No se ha seleccionado ningún Ámbito de trabajo";
                    return false;
                }
                
                //lee el ancho medio de la vía si está visible (se ha seleccionado la opción genérica Eje de calles)
                limp.ancho_via =  LimpiezaDef.Parametros.ancho_via;
                if (textBox_ancho_medio.Visible)
                {
                    try
                    {
                        str_aux = textBox_ancho_medio.Text;
                        limp.ancho_via = Convert.ToDouble(str_aux);
                        if ((limp.ancho_via == 0) || (limp.ancho_via > LimpiezaDef.Parametros.ancho_viaM) || (limp.ancho_via < LimpiezaDef.Parametros.ancho_viam))
                        {
                            err_str = "El ancho de la vía no está dentro de los límites configurados";
                            return false;
                        }
                    }
                    catch (FormatException)
                    {
                        err_str = "El formato introducido para el ancho de la vía no es válido.";
                        return false;
                    }
                }

                //cuando se ejecuta el proceso se compurueba si se va a tener en cuenta el umbral de carga de los contendores en su recogida
                if ((checkBox_papelera.Visible == true) && (checkBox_papelera.Checked == true))
                {
                    limp.umbral_reco_conten = true;
                    try
                    {
                        limp.umbral_basura = Convert.ToDouble(tbox_umbral_recog.Text);
                        if (limp.umbral_basura < 0 || limp.umbral_basura>100)
                        {
                            err_str = "El umbral de carga de papeleras no está dentro de los límites configurados";
                            return false;
                        }
                    }
                    catch (FormatException)
                    {
                        err_str = "El formato introducido para el umbral de carga de papeleras no es válido.";
                        return false;
                    }
                }
                else
                    limp.umbral_reco_conten = false;

                //lee el tiempo de tratamiento
                try
                {
                    str_aux = textBox_t_tto.Text;
                    limp.t_tto = Convert.ToDouble(str_aux);
                    if ((limp.t_tto == 0) || (limp.t_tto > LimpiezaDef.Parametros.t_ttoM) || (limp.t_tto < LimpiezaDef.Parametros.t_ttom))
                    {
                        err_str = "El tiempo de tratamiento no está dentro de los límites configurados";
                        return false;
                    }
                }
                catch (FormatException)
                {
                    err_str = "El formato introducido para el tiempo de tratamiento no es válido.";
                    return false;
                }

                //lee la velocidad de desplazamiento
                try
                {
                    str_aux = textBox_v_despl.Text;
                    if (str_aux != vel_nodef)
                    {
                        limp.v_despl = Convert.ToDouble(str_aux);
                        if ((limp.v_despl == 0) || (limp.v_despl > LimpiezaDef.Parametros.v_despM) || (limp.v_despl < LimpiezaDef.Parametros.v_despm))
                        {
                            err_str = "La velocidad de desplazamiento no está dentro de los límites configurados";                            
                            return false;
                        }
                    }
                }
                catch (FormatException)
                {
                    err_str = "El formato introducido para la velocidad de desplazamiento no es válido.";
                    return false;
                }

                //recoge el porcentaje de tráfico que se estima en las vías
                try
                {
                    limp.trafico = Convert.ToDouble(textBox_traf.Text);
                    if ((limp.trafico < 0) || (limp.trafico > 100))
                    {
                        err_str = "El porcentaje de tráfico en las vías no está dentro de los límites configurados";
                        return false;
                    }
                }
                catch (Exception)
                {
                    err_str = "El formato introducido para el porcentaje de tráfico en las vías no es válido.";
                    return false;
                }

                //lee el buffer de exportación
                try
                {
                    OliviaGlob.buff_export = Convert.ToInt32(textBox_buff.Text);
                    if ((OliviaGlob.buff_export < 0) || (OliviaGlob.buff_export > 10000))
                    {
                        err_str = "El buffer de exportación no está dentro de los límites configurados";
                        return false;
                    }
                }
                catch (Exception)
                {
                    err_str = "El formato introducido para el buffer de exportación no es válido.";
                    return false;
                }

                //lee el tiempo de trabajo al día por convenio
                int[] hm = { 0, 0 };
                hm[0] = dateTimePicker_t_conv.Value.Hour;
                hm[1] = dateTimePicker_t_conv.Value.Minute;
                limp.t_conv = OliviaGlob.dame_min(hm);
                if ((limp.t_conv == 0) || (limp.t_conv > LimpiezaDef.Parametros.t_convM) || (limp.t_conv < LimpiezaDef.Parametros.t_convm))
                {
                    err_str = "El valor introducido para el tiempo de trabajo por convenio no es válido.";
                    return false;
                }

                //lee el tiempo de descanso del personal
                hm[0] = dateTimePicker_t_desc.Value.Hour;
                hm[1] = dateTimePicker_t_desc.Value.Minute;
                limp.t_descan = OliviaGlob.dame_min(hm);
                if ((limp.t_descan == 0) || (limp.t_descan > LimpiezaDef.Parametros.t_descansoM) || (limp.t_descan < LimpiezaDef.Parametros.t_descansom))
                {
                    err_str = "El valor introducido para el tiempo de descanso no es válido.";
                    return false;
                }

                //lee el tiempo de carga y descarga
                hm[0] = dateTimePicker_carg.Value.Hour;
                hm[1] = dateTimePicker_carg.Value.Minute;
                limp.t_descarg = OliviaGlob.dame_min(hm);
                if ((limp.t_descarg == 0) || (limp.t_descarg > LimpiezaDef.Parametros.t_cardescM) || (limp.t_descarg < LimpiezaDef.Parametros.t_cardescm))
                {
                    err_str = "El valor introducido para el tiempo de carga y descarga no es válido.";
                    return false;
                }

                //lee el tiempo de desplazamiento inicio/fin
                hm[0] = dateTimePicker_despl.Value.Hour;
                hm[1] = dateTimePicker_despl.Value.Minute;
                limp.t_despl_insta = OliviaGlob.dame_min(hm);
                if ((limp.t_despl_insta == 0) || (limp.t_despl_insta > LimpiezaDef.Parametros.t_despM) || (limp.t_despl_insta < LimpiezaDef.Parametros.t_despm))
                {
                    err_str = "El valor introducido para el tiempo de desplazamiento no es válido.";
                    return false;
                }

                //lee la hora de inicio de la jornada
                hm[0] = dateTimePicker_h_inicio.Value.Hour;
                hm[1] = dateTimePicker_h_inicio.Value.Minute;
                limp.h_ini = OliviaGlob.dame_min(hm);

                //se lee el número de puntos de control
                limp.n_ptsctrl = (int)numericUpDown_pctrl.Value;
                if (limp.n_ptsctrl == 0)
                {
                    err_str = "No puede haber 0 puntos de control.";
                    return false;
                }

                //se lee el número de sectores si se ha puesto algún valor
                if (checkBox_sector_autom.Checked == true)
                    limp.n_secdef = 0;
                else
                {
                    limp.n_secdef = (int)numericUpDown_sectores.Value;
                    if (checkBox_ajust_sec.Checked == true)
                        limp.n_secdef = limp.n_secdef * (-1);//lo envía negativo si es modo ajusta a jornada,                     
                }

                //lee si se va a tener en cuenta los elementos asilados o no
                if (checkBox_aislados.Checked == true)
                    limp.aislados = 1;
                else
                    limp.aislados = 0;

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }      

        //*************************************************************************************
        //Eventos de elementos de la ventana
        /**
         * Desplegable para seleccionar el tipo de tratamiento
         */
        private void comboBox_tto_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                textBox_v_despl.Enabled = true;
                if (OliviaGlob.demo_id == true)
                {
                    if (comboBox_tto.SelectedIndex != -1)
                        limp.tipo_tto = (int)LimpiezaDef.TiposTto.TtoPapeVaci;
                }
                else
                    limp.tipo_tto = comboBox_tto.SelectedIndex;
                limp.amb_tra_sel = new bool[(int)LimpiezaDef.AmbitsTra.AmbN];   //reinicia los ambitos seleccionados

                cambia_tiempo_tto();

                ////////////////////////////////////////
                //Otros cambios que dependen del tratamiento
                if (limp.tipo_tto != (int)LimpiezaDef.TiposTto.TtoNoDef)
                {
                    checkBox_restr.Checked = limp.rest_circ[(int)limp.tipo_tto];
                    if (limp.t_carg_desc[(int)limp.tipo_tto] == true)
                        dateTimePicker_carg.Enabled = true;
                    else
                        dateTimePicker_carg.Enabled = false;

                    if (LimpiezaDef.v_desplazamiento[(int)limp.tipo_tto] > 0)
                        textBox_v_despl.Text = Convert.ToString(LimpiezaDef.v_desplazamiento[(int)limp.tipo_tto]);
                    else
                        textBox_v_despl.Text = vel_nodef;
                }
                else
                {
                    checkBox_restr.Checked = false;
                    dateTimePicker_carg.Enabled = false;
                    textBox_v_despl.Text = vel_nodef;
                }

                //si se selecciona el tratamiento de VACIADO DE PAPELERAS se muestra el checkbox que permite sectorizar sólo las papeleras llenas.
                if (limp.tipo_tto == (int)LimpiezaDef.TiposTto.TtoPapeVaci)
                    checkBox_papelera.Visible = true;
                else if (limp.tipo_tto != (int)LimpiezaDef.TiposTto.TtoNoDef)
                {
                    checkBox_papelera.Visible = false;
                    limp.umbral_reco_conten = false;
                    label_umbral_recog.Visible = false;
                    tbox_umbral_recog.Visible = false;
                }

                checkedListBox_amb.DataSource = null;
                //permite visualizar los elementos del ancho de vía que se activará cuando se seleccione la opción genérica de ejes de calle 
                //siempre y cuando el tiempo de tratamiento sea en m2/h
                label_ancho_medio.Visible = false;
                textBox_ancho_medio.Visible = false;
                label_uds_anch_med.Visible = false;

                //rellena el combo de opciones de los ambitos
                comboBox_amb.Items.Clear();
                comboBox_amb.Items.Add("Editable");
                comboBox_amb.Items.Add("Genérico");
                //en el caso del tratamiento customizable no se pondrán sus opciones particulares, sólo interesan las opciones globales a todos los tratamientos.
                //las opciones particulares del tratamiento customizable, son realemnte las opciones globales a todos los ttos.
                if ((limp.tipo_tto != (int)LimpiezaDef.TiposTto.TtoNoDef) && (limp.tipo_tto < (int)LimpiezaDef.TiposTto.TtoCustom))
                {
                    for (int i = 0; i < (limp.ambs_val[(int)limp.tipo_tto].n_ops); i++)
                        comboBox_amb.Items.Add("Opción " + (i + 1));
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Error al seleccionar tratamiento", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }
        
        /**
        * El botón cerrar cierra la aplicación Olivia
        */
        private void LimpiezaDlg_FormClosed(object sender, FormClosedEventArgs e)
        {
            OliviaGlob.borra_files();
            OliviaGlob.inidlg.Show();    
        }

        /**
        * El botón ejecutar lanza el proceso de secotrización y de cálculo de rutas
        */
        private void button_eje_Click(object sender, EventArgs e)
        {
            Hide();
            if (!ejecuta((int)Ejecuta.ModosEjec.Secto))
            {
                MessageBox.Show("Error al comenzar la ejecución. " + err_str, "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                OliviaGlob.borra_files();
                Show();
            }             
        }

        /**
         * Desplegable que permite seleccionar las opciones de ámbitos de trabajo según el tipo de tratamiento seleccionado.
         */
        private void comboBox_amb_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                ArrayList lista;
                lista = pon_ambitos();
                //checkea los ámbitos de esta opción
                check_ambitos(comboBox_amb.SelectedIndex, lista);
                checkedListBox_amb.Enabled = true;
                if (comboBox_amb.SelectedIndex == 1)
                {
                    //permite visualizar los elementos del ancho de vía que se activará cuando se seleccione la opción genérica de ejes de calle siempre y cuando el tiempo de tratamiento sea en ml/h
                    if (limp.uds_t_tto != (int)GeneralDef.OlvTiposTto.OlvTipTtoM2h_eje)
                    {
                        label_ancho_medio.Visible = true;
                        label_ancho_medio.Text = "Ancho medio de la calle";
                        textBox_ancho_medio.Visible = true;
                        textBox_ancho_medio.Text = limp.ancho_via.ToString();
                        label_uds_anch_med.Visible = true;
                    }
                }
                else
                {
                    label_ancho_medio.Visible = false;
                    textBox_ancho_medio.Visible = false;
                    label_uds_anch_med.Visible = false;
                }
                if (((limp.tipo_tto == (int)LimpiezaDef.TiposTto.TtoBaldMecCalz) && (comboBox_amb.SelectedIndex >= 2)) ||
                    ((limp.tipo_tto == (int)LimpiezaDef.TiposTto.TtoCaidaHoja) && (comboBox_amb.SelectedIndex >= 2)))
                    checkedListBox_amb.Enabled = false; //si uno de los ámbitos es "eje de calle" no se puede combinar con los demás ámbitos
            }
            catch (Exception)
            {
                MessageBox.Show("Error al seleccionar ámbitos", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }
        
        /**
         * Se aplica restricciones en la circulación en el cálculo de la sectorización
         */
        private void bt_restric_circ_Click(object sender, EventArgs e)
        {
            string text_sal;
            Hide();//esconde el dialogo
            if (limp.selec_polig("Seleccionar capa de restricciones de circulación", this.Handle.ToInt32(), out text_sal, out limp.geom_rest_acces))            
            {
                label_restric.Text = text_sal;
                limp.text_restr = text_sal;
            }
            else
            {
                label_restric.Text = limp.text_selec_rest;
                limp.text_restr = "";
            }
            Show(); 
        }

        /**
         * Para añadir una capa de niveles, en el cálculo de la sectorización, diferente a la existente en la GDB seleccionada al comienzo de la aplicación.
         */
        private void bt_niveles_Click(object sender, EventArgs e)
        {
            string text_sal;
            Hide();//esconde el dialogo
            if (limp.selec_polig("Seleccionar capa de niveles", this.Handle.ToInt32(), out text_sal, out limp.geom_niveles))
            {
                label_niv.Text = text_sal;
                limp.text_niv = text_sal;
            }
            else
            {
                label_niv.Text = limp.text_selec_nive;
                limp.text_niv = "";
            }
            Show();             
        }

        /**
        * Para añadir una capa de zonas, en el cálculo de la sectorización, diferente a la existente en la GDB seleccionada al comienzo de la aplicación.
        */
        private void bt_zonas_Click(object sender, EventArgs e)
        {
            string text_sal;
            Hide();//esconde el dialogo
            if (limp.selec_polig("Seleccionar capa de zonas", this.Handle.ToInt32(), out text_sal, out limp.geom_zonas))
            {
                label_zon.Text = text_sal;
                limp.text_zon = text_sal;
            }
            else
            {
                label_zon.Text = limp.text_selec_zonas;
                limp.text_zon = "";
            }
            Show();            
        }

        /**
        * Para añadir una capa de instalaciones, en el cálculo de la sectorización. 
         * De modo que se conozca la ubicación de la instalación a la que tendrán que ir los camiones a descargar.
        */
        private void bt_instalaciones_Click(object sender, EventArgs e)
        {
            string text_sal;
            Hide();//esconde el dialogo
            if (limp.selec_instal("Seleccionar capa de instalaciones de salida/llegada", this.Handle.ToInt32(), out text_sal,
                out limp.coords_instala[0], out limp.coords_instala[1]))
                instal_sel.Text = text_sal;
            else
                instal_sel.Text = limp.text_selec_instal;
            Show();            
        }

        /*
         * Una vez se ha realizado la sectorización se recibe el shapefile y, si fuera necesario, se modifica la sectorizacion.
         * Una vez esté todo al gusto del usuario se realiza la planificación de la ruta.
         */
        private void bt_planifica_Click(object sender, EventArgs e)
        {
            Hide();

            if (!ejecuta((int)Ejecuta.ModosEjec.Planif))
            {
                MessageBox.Show("Error al comenzar la ejecución: " + err_str, "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                OliviaGlob.borra_files();
                Show();
            }            
        }

        /*
         * Comienza la ejecución, secto o planif
         */
        private bool ejecuta(int modo)
        {
            ProgresoInic pro_inic = null;
            try
            {
                err_str = "";
                OliviaGlob.gdb_limp.err_st = "";

                button_eje.Enabled = bt_planifica.Enabled = false;

                //lee el dialogo de limpieza para recoger los parámetros que intervienen en el cálculo de la planificación
                if (!lee())
                {
                    return false;
                }

                pro_inic = new ProgresoInic();
                pro_inic.Show();

                EjecutaLimp eje_limp = new EjecutaLimp();
                if (!eje_limp.ejec(limp, modo))
                {
                    pro_inic.Close();
                    err_str = eje_limp.err_str;
                    return false;
                }
                pro_inic.Close();
                return true;
            }
            catch (Exception)
            {
                if (pro_inic != null)
                    pro_inic.Close();
                return false;
            }
            finally
            {
                button_eje.Enabled = bt_planifica.Enabled = true;
            }
        }

        /**
        * Permite seleccionar el cálculo autmático de sectores en función de la zona de trabajo, teniendo en cuenta las jornadas de trabajo marcadas
        */
        private void checkBox_sector_autom_CheckedChanged(object sender, EventArgs e)
        {
            numericUpDown_sectores.Enabled = checkBox_ajust_sec.Enabled = !checkBox_sector_autom.Checked;            
        }

        /*revisar borrar
         * private void LimpiezaDlg_VisibleChanged(object sender, EventArgs e)
        {
            try
            {
                if (OliviaGlob.estado == TiposEstado.Inicio)
                {
                    groupBox_edits.Enabled = true;
                    bt_planifica.Enabled = false;
                    button_eje.Enabled = true;
                    checkBox_aislados.Enabled = true;
                    Show();
                }
                else if (OliviaGlob.estado == TiposEstado.PreparadoPlanif ||
                    OliviaGlob.estado == TiposEstado.FinPlanif) 
                {
                    groupBox_edits.Enabled = false;
                    bt_planifica.Enabled = true;
                    button_eje.Enabled = false;
                    checkBox_aislados.Enabled = false;
                    Show();
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Error al mostrar la ventana de Limpieza", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }*/

        /*
         * Al pulsar en el check box de tener en cuenta un umbral de llenado para el vaciado de las papeleras
         */
        private void checkBox_papelera_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox_papelera.Checked == true)
            {
                label_umbral_recog.Visible = true;
                tbox_umbral_recog.Visible = true;
                tbox_umbral_recog.Text = limp.umbral_basura.ToString();
                limp.umbral_reco_conten = false;
            }
            else
            {
                limp.umbral_reco_conten = false;
                label_umbral_recog.Visible = false;
                tbox_umbral_recog.Visible = false;
            }
        }
        
        /**
         * Cuando se picnha en el botón de ayuda se abre el manual de Olivia
         */
        private void btn_help_Click(object sender, EventArgs e)
        {
            string[] archivos;

            try
            {
                archivos = Directory.GetFiles(OliviaGlob.Paths.PathWork, OliviaGlob.manual + ".pdf");
                if (archivos.Length <= 0)
                    MessageBox.Show("No se encuentra el archivo " + OliviaGlob.manual + ".pdf en la ubicación " + OliviaGlob.Paths.PathWork, "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);

                foreach (string f in archivos)
                {
                    Process.Start(f);
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Error al abrir el manual de ayuda " + OliviaGlob.manual + ".pdf", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void button_capa_limp_Click(object sender, EventArgs e)
        {
            string path_limp;
            
            //se despliega el dialogo para seleccionar ua capa de la que se recogerán los datos.
            path_limp = FunGDB.selec_ftcls("Seleccionar capa de limpieza", this.Handle.ToInt32());

            if (path_limp != null)
            {
                OliviaGlob.gdb_limp.path_class = path_limp;
                if (OliviaGlob.gdb_limp.comprueba_campos_limp(limp))
                {
                    label_capa_limp.Text = System.IO.Path.GetFileNameWithoutExtension(path_limp);
                    amb_tra_gdb = OliviaGlob.gdb_limp.lee_amb_gdb(limp);
                    checkedListBox_amb.pon_ambs_gdb(amb_tra_gdb);
                }
                else
                {
                    MessageBox.Show("Error en la capa " + path_limp + " " + limp.err_st, "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);                
                    label_capa_limp.Text = limp.text_capa_limp;
                    OliviaGlob.gdb_limp.path_class = null;
                }
            }
            else
            {
                label_capa_limp.Text = limp.text_capa_limp;
                OliviaGlob.gdb_limp.path_class = null;
            }
            comboBox_tto.SelectedIndex = -1;
            OliviaGlob.gdb_limp.path_import = null;
        }

        private void button_edit_camp_Click(object sender, EventArgs e)
        {
            try
            {
                LimpCampos camps = new LimpCampos(limp);
                if (camps.ShowDialog() == DialogResult.OK)
                {
                    if (OliviaGlob.gdb_limp.comprueba_campos_limp(limp))
                    {
                        amb_tra_gdb = OliviaGlob.gdb_limp.lee_amb_gdb(limp);
                        checkedListBox_amb.pon_ambs_gdb(amb_tra_gdb);
                    }
                    else
                    {
                        MessageBox.Show(limp.err_st, "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
                comboBox_tto.SelectedIndex = -1;
            }
            catch (Exception)
            {
                MessageBox.Show("Error al editar los campos de la capa de recogida de residuos", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }
    }
}
