using System;
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.Net.Sockets;
using System.IO;
using System.Diagnostics;

using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Geometry;

namespace OliviaAddIn
{
    /**
    *	@file RecogidaDlg.cs
    *	Clase de la ventana de configuración de la herramienta de Recogida de Residuos.
    *	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 Recogida de Residuos.
    *	Contiene el manejo de sus eventos como el Click o la actualización de su estado.
    */
    public partial class RecogidaDlg : Form
    {
        //*************************************************************************************        
        //Variables

        /**
        *	Instancia que contiene las variables de la clase
        */
        public Recogida reco = null;
        /**
         * Variable para indicar los errores que pueden ir surgiendo
         */
        string err_str = null;
        //*************************************************************************************
        //Constructor
        public RecogidaDlg()
        {
            InitializeComponent();
            reco = new Recogida();
            inicia();
        }
        //*************************************************************************************
        //Métodos

        /**
         * Inicia los elementos de la ventana, rellenando los textos y los combos
         */ 
        private void inicia()
        {
            try
            {
                checkBox_sens.Enabled = false;
                checkBox_sens.Checked = false;
                groupBox_tiporeco.Enabled = false;
                button_edit_camp.Enabled = false;

                //se habilita la posibilidad de pintar los items con gris y con negro
                comboBox_fraccion.DrawMode = DrawMode.OwnerDrawFixed;
                comboBox_carga.DrawMode = DrawMode.OwnerDrawFixed;
                
                //inicia los tiempos
                inicia_timepickers();
                //rellena el factor de tráfico
                textBox_traf.Text = reco.trafico.ToString();

                textBox_dens_cont.Visible = false;
                label_dens_cont.Visible = false;
                //se reinicia los arrays de fracciones y tipos de carga por si ya se hubiera realizado algún proceso de recogida de residuos.
                if ((RecogidaDef.tipos_fracc_str.Length > (int)RecogidaDef.TiposFracción.N - 1) || (RecogidaDef.tipos_carg_str.Length > (int)RecogidaDef.TiposCarga.N - 1))
                {
                    System.Array.Resize(ref RecogidaDef.tipos_fracc_str, (int)RecogidaDef.TiposFracción.N - 1);
                    System.Array.Resize(ref RecogidaDef.tipos_carg_str, (int)RecogidaDef.TiposCarga.N - 1);
                }
                numericUpDown_sectores.Value = reco.n_secdef;
                
                /////////////////////////////////////////////////
                //pone los textos iniciales
                instal_sel.Text = reco.text_selec_instal;
                lbl_pto_descarg.Text = reco.text_selec_descarg;
                lbl_turno.Text = reco.text_selec_turno;
                lbl_capa_restricc.Text = reco.text_selec_rest;
                lbl_capa_zona.Text = reco.text_selec_zonas;

                reco.rec_capac = RecogidaDef.campos_def.cons_capac;
                reco.rec_uds = RecogidaDef.campos_def.cons_uds;
                reco.rec_kg = RecogidaDef.campos_def.cons_kgrec;
                textBox_buff.Text = OliviaGlob.buff_export.ToString();

                if (RecogidaDef.lleno)
                {
                    reco.rec_kgrec_cont = -1;
                }
                else if (RecogidaDef.kgrec_camp)
                {
                    reco.rec_kgrec_cont = 0;
                }
                else
                {
                    reco.rec_kgrec_cont = RecogidaDef.kgrec_cont;
                }

            }
            catch (Exception)
            {
                MessageBox.Show("Error al iniciar la ventana de Recogida", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        /**
        * 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 convenio
            hm = OliviaGlob.dame_h_m(reco.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(reco.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);

            //hora de inicio de la jornada
            hm = OliviaGlob.dame_h_m(reco.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);
        }

        /**
         * Rellena la lista de capacidades de vehículos disponibles
         */ 
        private void rellena_capac()
        {
            if (reco.tipo_vehic >= 0 && reco.tipo_vehic < (int)RecogidaDef.TiposVehic.N && 
                reco.tipo_carg >= 0 && reco.tipo_carg < (int)RecogidaDef.TiposCarga.N)
            {
                comboBox_capac.Items.Clear();
                textBox_kgmax.Text = "";
                if (reco.cargas_max_vehic[reco.tipo_carg, reco.tipo_vehic].n > 0)
                {
                    for (int i = 0; i < reco.cargas_max_vehic[reco.tipo_carg, reco.tipo_vehic].n; i++)
                        comboBox_capac.Items.Add(reco.cargas_max_vehic[reco.tipo_carg, reco.tipo_vehic].vol[i] + " m3");
                }                
            }

            else if (reco.tipo_vehic >= 0 && reco.tipo_vehic < (int)RecogidaDef.TiposVehic.N && 
                reco.tipo_carg >= (int)RecogidaDef.TiposCarga.N)
            {
                comboBox_capac.Items.Clear();
                textBox_kgmax.Text = "";
                if (reco.cargas_max_vehic[(int)RecogidaDef.TiposCarga.Otra, reco.tipo_vehic].n > 0)
                {
                    for (int i = 0; i < reco.cargas_max_vehic[(int)RecogidaDef.TiposCarga.Otra, reco.tipo_vehic].n; i++)
                        comboBox_capac.Items.Add(reco.cargas_max_vehic[(int)RecogidaDef.TiposCarga.Otra, reco.tipo_vehic].vol[i] + " m3");
                }   
            }
        }

        /**
         * Rellena la caja de texto con la capacidad en kg máxima del vehículo seleccionado
         */
        private void rellena_kgmax()
        {
            int kgmax,off;

            if (reco.tipo_vehic >= 0 && reco.tipo_vehic < (int)RecogidaDef.TiposVehic.N &&
                reco.tipo_carg >= 0 && reco.tipo_carg < (int)RecogidaDef.TiposCarga.N &&
                reco.tipo_capa >= 0 && reco.tipo_capa < (int)reco.cargas_max_vehic[reco.tipo_carg, reco.tipo_vehic].n)
            {
                if ((reco.cargas_max_vehic[reco.tipo_carg, reco.tipo_vehic].offset != null) && (reco.tipo_frac < (int)RecogidaDef.TiposFracción.N))
                    off = reco.cargas_max_vehic[reco.tipo_carg, reco.tipo_vehic].offset[reco.tipo_capa,reco.tipo_frac];
                else if ((reco.cargas_max_vehic[reco.tipo_carg, reco.tipo_vehic].offset != null) && (reco.tipo_frac >= (int)RecogidaDef.TiposFracción.N))
                    off = reco.cargas_max_vehic[reco.tipo_carg, reco.tipo_vehic].offset[reco.tipo_capa, (int)RecogidaDef.TiposFracción.Otra];
                else
                    off = 0;
                if (reco.tipo_frac < (int)RecogidaDef.TiposFracción.N)
                    kgmax = reco.cargas_max_vehic[reco.tipo_carg, reco.tipo_vehic].vol[reco.tipo_capa] * RecogidaDef.dens_frac_cami[reco.tipo_frac] + off;
                else
                    kgmax = reco.cargas_max_vehic[reco.tipo_carg, reco.tipo_vehic].vol[reco.tipo_capa] * RecogidaDef.dens_frac_cami[(int)RecogidaDef.TiposFracción.Otra] + off;
                textBox_kgmax.Text = kgmax.ToString();
            }

            else if (reco.tipo_vehic >= 0 && reco.tipo_vehic < (int)RecogidaDef.TiposVehic.N &&
                reco.tipo_carg >= (int)RecogidaDef.TiposCarga.N &&
                reco.tipo_capa >= 0 && reco.tipo_capa < (int)reco.cargas_max_vehic[(int)RecogidaDef.TiposCarga.Otra, reco.tipo_vehic].n)
            {
                if ((reco.cargas_max_vehic[(int)RecogidaDef.TiposCarga.Otra, reco.tipo_vehic].offset != null) && (reco.tipo_frac < (int)RecogidaDef.TiposFracción.N))
                    off = reco.cargas_max_vehic[(int)RecogidaDef.TiposCarga.Otra, reco.tipo_vehic].offset[reco.tipo_capa, reco.tipo_frac];
                else if ((reco.cargas_max_vehic[(int)RecogidaDef.TiposCarga.Otra, reco.tipo_vehic].offset != null) && (reco.tipo_frac >= (int)RecogidaDef.TiposFracción.N))
                    off = reco.cargas_max_vehic[(int)RecogidaDef.TiposCarga.Otra, reco.tipo_vehic].offset[reco.tipo_capa, (int)RecogidaDef.TiposFracción.Otra];
                else
                    off = 0;
                if (reco.tipo_frac < (int)RecogidaDef.TiposFracción.N)
                    kgmax = reco.cargas_max_vehic[(int)RecogidaDef.TiposCarga.Otra, reco.tipo_vehic].vol[reco.tipo_capa] * RecogidaDef.dens_frac_cami[reco.tipo_frac] + off;
                else
                    kgmax = reco.cargas_max_vehic[(int)RecogidaDef.TiposCarga.Otra, reco.tipo_vehic].vol[reco.tipo_capa] * RecogidaDef.dens_frac_cami[(int)RecogidaDef.TiposFracción.Otra] + off;
                textBox_kgmax.Text = kgmax.ToString();
            }
        }

        /**
         * Lee los datos seleccionados en el diálogo
         */
        private bool lee()
        {
            int ind;
            int[] hm = { 0, 0 };
            string aux = null;

            ////////////////////////////////////////////////
            reco.rellena_simbol_rec();
            reco.rellena_simb_tipbasura();
            //se rellena el array de filtros            
            RecogidaDef.filtro_str = new string[RecogidaDef.tipos_fracc_str.Length + RecogidaDef.tipos_carg_str.Length];
            for (int i = 0; i < RecogidaDef.tipos_fracc_str.Length; i++)
            {
                //se comprueba que tipo de fracción se ha seleccionado. Si se ha seleccionado una fracción sin nombre (el campo en la capa es NULL, y en el comboBox de fracciiones aparece como "-") hay que modificar el filtro
                if (RecogidaDef.tipos_fracc_str[i] == "-")
                    RecogidaDef.filtro_str[i] = RecogidaDef.campos_def.cons_fracc + " IS NULL";
                else
                    RecogidaDef.filtro_str[i] = RecogidaDef.campos_def.cons_fracc + "= '" + RecogidaDef.tipos_fracc_str[i] + "'";
            }
            for (int i = RecogidaDef.tipos_fracc_str.Length; i < RecogidaDef.filtro_str.Length; i++)
            {
                RecogidaDef.filtro_str[i] = RecogidaDef.campos_def.cons_nomrec + "= '" + RecogidaDef.tipos_carg_str[i - RecogidaDef.tipos_fracc_str.Length] + "'";
            }            

            reco.tipo_frac = comboBox_fraccion.SelectedIndex;
            if (reco.tipo_frac == -1)
            {
                err_str = "No se ha seleccionado ningún Tipo de Fracción";
                return false;
            }
            if (reco.tipo_frac >= (int)RecogidaDef.TiposFracción.N - 1)
                OliviaGlob.gdb_reco.fra_otra = RecogidaDef.tipos_fracc_str[reco.tipo_frac];

            //si se ha seleccionado que se recogen los contenedores llenos hay que comprobar que se ha rellenado la densidad de los contenedores
            if (RecogidaDef.lleno /*&& textBox_dens_cont.Visible == true*/)
            {
                try
                {
                    reco.dens_cont = Convert.ToDouble(textBox_dens_cont.Text);
                    if (reco.dens_cont <= 0 || reco.dens_cont>100)
                    {
                        err_str = "El valor introducido para la densidad del contenedor no es válido.";
                        return false;
                    }
                }
                catch (Exception)
                {
                    err_str = "El formato introducido para la densidad del contenedor no es válido.";
                    return false;
                } 
            }
            else
                reco.dens_cont = -1;


            reco.tipo_carg = comboBox_carga.SelectedIndex;
            if (reco.tipo_carg == -1)
            {
                err_str = "No se ha seleccionado ningún Tipo de Carga";
                return false;
            }
            if (reco.tipo_carg >= (int)RecogidaDef.TiposCarga.N - 1)
            {
                OliviaGlob.gdb_reco.carg_otra = RecogidaDef.tipos_carg_str[reco.tipo_carg];
            }
            if (comboBox_lateralidad.Visible == true)
            {
                reco.lateralidad = comboBox_lateralidad.SelectedIndex;
                if (reco.lateralidad == -1)
                {
                    err_str = "No se ha seleccionado ningún Tipo de Lateralidad";
                    return false;
                }
            }
            reco.tipo_vehic = comboBox_vehic.SelectedIndex;
            if (reco.tipo_vehic == -1)
            {
                err_str = "No se ha seleccionado ningún Tipo de Vehículo";
                return false;
            }

            reco.giro_vehic = RecogidaDef.giro_vehic[reco.tipo_vehic];

            //a la hora de leer la capacidad hay que tener en cuenta que cuando se selecciona una carga no contemplada en la enumeracion RecogidaDef.TiposCarga, es decir,
            //>= a RecogidaDef.TiposCarga.Otra no hay que leer la capacidad porque se deshanbilita al no tener información de densidades, etc
            if (reco.tipo_carg < (int)RecogidaDef.TiposCarga.N - 1)
            {
                reco.tipo_capa = comboBox_capac.SelectedIndex;
                if (reco.tipo_capa == -1)
                {
                    err_str = "No se ha seleccionado ningún Tipo de Capacidad";
                    return false;
                }
            }            

            //se verifica que se haya seleccionado una capa de instalación de llegada y salida.
            if ((reco.coords_instala[0] == 0) && (reco.coords_instala[1] == 0))
            {
                err_str = "No se ha seleccionado ninguna capa de Instalación de salida y llegada.";
                return false;
            }

            //se verifica que se ha seleccionado una capa de lugar de descarga de los vehículos.
            if ((reco.coords_descarg[0] == 0) && (reco.coords_descarg[1] == 0))
            {
                err_str = "No se ha seleccionado ninguna capa de Instalación de descarga de los vehículos.";
                return false;
            }

            //recoge la carga máxima del vehículo que se ha configurado
            try
            {
                reco.carg_max_vehic = Convert.ToInt32(textBox_kgmax.Text);
                if ((reco.carg_max_vehic <= 0) || (reco.carg_max_vehic > RecogidaDef.Parametros.kgmaxM) || (reco.carg_max_vehic < RecogidaDef.Parametros.kgmaxm))
                {
                    err_str = "El valor introducido para la carga máxima del vehículo no es válido.";
                    return false;
                }
            }
            catch (Exception)
            {
                err_str = "El formato introducido para la carga máxima del vehículo no es válido.";
                return false;
            }

            //recoge el porcentaje de tráfico que se estima en las vías
            try
            {
                reco.trafico = Convert.ToDouble(textBox_traf.Text);
                if ((reco.trafico < 0) || (reco.trafico > 100))
                {
                    err_str = "El valor introducido para el procentaje de tráfico en las vías no es válido.";
                    return false;
                }
            }
            catch (Exception)
            {
                err_str = "El formato introducido para el procentaje 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 la información de los sensores
            if (checkBox_sens.Checked == true)
            {
                if (groupBox_sens.Enabled == true ) 
                {
                    try
                    {
                        if (textBox_url.Text != "")
                        {
                            //se lee la url de los sensores si el chekbox se encuentra habilitado
                            ind = textBox_url.Text.IndexOf("/");
                            if (textBox_url.Text.StartsWith("http"))
                            {
                                aux = textBox_url.Text.Substring(ind + 2);
                                ind = aux.IndexOf("/");
                                aux = aux.Substring(0, ind);
                            }
                            else
                                aux = textBox_url.Text.Substring(0, ind);
                            if ((aux == "") || (aux.StartsWith("http")) || (aux.Contains("/")) || (aux.Contains(" ")))
                            {
                                err_str = "No se ha introducido una URL correcta";
                                return false;
                            }
                            RecogidaDef.campos.cons_url_sens = textBox_url.Text;
                            reco.url_sens = RecogidaDef.campos.cons_url_sens;
                            //se comprueba que se ha escrito un URL y uq esta es correcta
                            TcpClient tcpClientB = new TcpClient();
                            try
                            {
                                tcpClientB.Connect(aux, 80);
                            }
                            catch (Exception e)
                            {
                                err_str = "Error al generar la conexión: " + e.Message;                                
                                //por si geofoto sí funciona la conexión
                            }                                                        
                        }
                        //se lee la carga maxima indicada en la caja de texto
                        reco.carga_max = Convert.ToInt32(textBox_carga_max.Text);
                        if ((reco.carga_max <= 0) || (reco.carga_max > RecogidaDef.Parametros.carga_maxM) || (reco.carga_max < RecogidaDef.Parametros.carga_maxm))
                        {
                            err_str = "No se ha introducido un valor correcto para el umbral de recogida de basuras";
                            return false;
                        }
                    }
                    catch (FormatException)
                    {
                        err_str = "Error al leer los datos referentes a los umbrales de carga para recoger los contendores.";
                        return false;
                    }
                }
                else
                {
                    err_str = "Si se quiere recibir información externa, hay que se seleccionar si proviene de sensores o de csv.";
                    return false;
                }
            }

            //se lee el número de puntos de control
            reco.n_ptsctrl = (int)numericUpDown_pctrl.Value;
            if (reco.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)
                reco.n_secdef = 0;
            else
            {
                reco.n_secdef = (int)numericUpDown_sectores.Value;
                if (checkBox_ajust_sec.Checked == true)
                    reco.n_secdef = reco.n_secdef * (-1);//lo envía negativo si es modo ajusta a jornada,                     
            }   

            //recoge el tiempo de vaciado que se ha configurado
            try
            {
                reco.t_vaci = Convert.ToInt32(textBox_t_vaciado.Text);
                if ((reco.t_vaci <= 0) || (reco.t_vaci > RecogidaDef.Parametros.t_vaciM) || (reco.t_vaci < RecogidaDef.Parametros.t_vacim))
                {
                    err_str = "El valor introducido para el tiempo de vaciado no es válido.";
                    return false;
                }
            }
            catch (FormatException)
            {
                err_str = "El formato introducido para el tiempo de vaciado no es válido.";
                return false;
            } 
            
            //lee el tiempo en llegar a las instalaciones o en salir y llegar al destino de trabajo
            try
            {
                reco.t_despl_insta = Convert.ToInt32(textBox_t_sal.Text);
                if ((reco.t_despl_insta <= 0) || (reco.t_despl_insta > RecogidaDef.Parametros.t_llegsalM) || (reco.t_despl_insta < RecogidaDef.Parametros.t_llegsalm))
                {
                    err_str = "El valor introducido para el tiempo de desplazamiento a la instalación no es válido.";
                    return false;
                }
            }
            catch (FormatException)
            {
                err_str = "El formato introducido para el tiempo de desplazamiento a la instalación no es válido.";
                return false;
            } 

            //recoge invertido en descargar el vehículo lleno de residuos en la planta
            try
            {
                reco.t_descarg = Convert.ToInt32(textBox_descar.Text);
                if ((reco.t_descarg <= 0) || (reco.t_descarg > RecogidaDef.Parametros.t_descM) || (reco.t_descarg < RecogidaDef.Parametros.t_descm))
                {
                    err_str = "El valor introducido para el tiempo de descarga no es válido.";
                    return false;
                }
            }
            catch (FormatException)
            {
                err_str = "El formato introducido para el tiempo de descarga no es válido.";
                return false;
            } 

            //lee el tiempo de trabajo al día por convenio
            hm[0] = dateTimePicker_t_conv.Value.Hour;
            hm[1] = dateTimePicker_t_conv.Value.Minute;
            reco.t_conv = OliviaGlob.dame_min(hm);
            if ((reco.t_conv == 0) || (reco.t_conv > RecogidaDef.Parametros.t_convM) || (reco.t_conv < RecogidaDef.Parametros.t_convm))
            {
                err_str = "El formato o 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;
            reco.t_descan = OliviaGlob.dame_min(hm);
            if ((reco.t_descan == 0) || (reco.t_descan > RecogidaDef.Parametros.t_descansoM) || (reco.t_descan < RecogidaDef.Parametros.t_descansom))
            {
                err_str = "El formato o valor introducido para el tiempo de descanso 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;
            reco.h_ini = OliviaGlob.dame_min(hm);

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

        //*************************************************************************************
        //Eventos de ventana
        private void comboBox_carga_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                reco.tipo_carg = comboBox_carga.SelectedIndex;
                if (comboBox_carga.SelectedIndex == -1)
                {
                    reco.tipo_carg = -1;
                    return;
                }
                if (!reco.tipos_carg_bool[reco.tipo_carg])
                {
                    comboBox_fraccion.SelectedIndex = -1;
                    return;
                }
                if (comboBox_carga.SelectedIndex == (int)RecogidaDef.TiposCarga.Lateral)
                    comboBox_lateralidad.Visible = true;
                else
                    comboBox_lateralidad.Visible = false;
                if (reco.tipo_carg >= 0 && reco.tipo_carg < (int)RecogidaDef.TiposCarga.N - 1)
                {
                    //cuando se selecciona una carga contemplada en el listado origianl se habilita el comboBox de capacidad ya que sí habrá contemplado datos para tipos de cargas conocidos.
                    comboBox_capac.Enabled = true;
                    textBox_t_vaciado.Text = RecogidaDef.t_vaci[reco.tipo_carg].ToString();
                    if (reco.tipo_vehic >= 0)
                    {
                        //si también se ha seleccionado tipo de vehículo, se rellena la lista de capacidades
                        rellena_capac();
                    }
                }
                else if (reco.tipo_carg >= (int)RecogidaDef.TiposCarga.N - 1)
                {
                    //cuando se selecciona una carga no contemplada en el listado original se deshabilita el comboBox de capacidad porque no tendrá datos contemplado para ese caso
                    comboBox_capac.Enabled = false;
                    textBox_t_vaciado.Text = RecogidaDef.t_vaci[(int)RecogidaDef.TiposCarga.Otra].ToString();
                    if (reco.tipo_vehic >= 0)
                    {
                        //si también se ha seleccionado tipo de vehículo, se rellena la lista de capacidades
                        rellena_capac();
                    }
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Error al seleccionar la carga", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void comboBox_vehic_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                reco.tipo_vehic = comboBox_vehic.SelectedIndex;
                if (reco.tipo_carg >= 0)
                {
                    //si también se ha seleccionado tipo de carga, se rellena la lista de capacidades
                    rellena_capac();
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Error al seleccionar el tipo de vehículo", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void comboBox_capac_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                reco.tipo_capa = comboBox_capac.SelectedIndex;
                rellena_kgmax();
            }
            catch (Exception)
            {
                MessageBox.Show("Error al seleccionar la capacidad", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        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();
            }   
        }

        private void button_eje_Click(object sender, EventArgs e)
        {
            Hide();

            if (!ejecuta((int)Ejecuta.ModosEjec.SoloPlanif))
            {
                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_reco.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();

                EjecutaReco eje_reco = new EjecutaReco();
                if (!eje_reco.ejec(reco, modo))
                {
                    pro_inic.Close();
                    err_str = eje_reco.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;
            }
        }

        private void comboBox_fraccion_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                //cuando se selecciona un item pintado en gris (que no existe en la GDB) se actúa como si no se hubiera seleccionado item
                reco.tipo_frac = comboBox_fraccion.SelectedIndex;
                if (comboBox_fraccion.SelectedIndex == -1)
                {
                    reco.tipo_frac = -1;
                    return;
                }
                if (!reco.tipos_fracc_bool[reco.tipo_frac])
                {
                    comboBox_fraccion.SelectedIndex = -1;
                    return;
                }
                if ((reco.tipo_vehic >= 0) && (reco.tipo_carg >= 0))
                {
                    //si también se ha seleccionado tipo de carga y de vehículo, se rellena la lista de capacidades
                    rellena_capac();
                }
                if (RecogidaDef.lleno)
                {
                    if (reco.tipo_frac < (int)RecogidaDef.TiposFracción.Otra)
                    {
                        textBox_dens_cont.Text = RecogidaDef.dens_frac_cont[reco.tipo_frac].ToString();
                    }
                    else
                    {
                        textBox_dens_cont.Text = "";
                    }
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Error al seleccionar el tipo de fracción", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void button_edit_camp_Click(object sender, EventArgs e)
        {
            try
            {
                RecoCampos camps = new RecoCampos(reco);
                if (camps.ShowDialog() == DialogResult.OK)
                {
                    click_edit_camps_sin_show();
                    button_leer_tbl_Click(null, null);
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Error al editar los campos de la capa de recogida de residuos", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void click_edit_camps_sin_show()
        {
            groupBox_tiporeco.Enabled = false;
            textBox_dens_cont.Text = "";
            textBox_dens_cont.Visible = false;
            checkBox_sens.Enabled = true;
            if (RecogidaDef.lleno == true)
            {
                if (checkBox_sens.Checked == true)
                {
                    checkBox_sens.Checked = false;
                }
                checkBox_sens.Enabled = true;
            }
            else
            {
                if (checkBox_sens.Checked == true)
                {
                    checkBox_sens.Checked = false;
                }
                checkBox_sens.Enabled = false;
                btn_csv.Enabled = false;
                btn_edit_camp_sensor.Enabled = false;
            }
            comboBox_fraccion.Items.Clear();
            comboBox_carga.Items.Clear();
            comboBox_vehic.Items.Clear();
            comboBox_capac.Items.Clear();
            comboBox_lateralidad.Items.Clear();
            comboBox_lateralidad.Visible = false;
            textBox_kgmax.Text = "";
        }

        private void checkBox_sens_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox_sens.Checked == true)
            {
                btn_edit_camp_sensor.Enabled = checkBox_sens.Checked;
                btn_csv.Enabled = checkBox_sens.Checked;
                groupBox_sens.Enabled = checkBox_sens.Checked;
                textBox_url.Enabled = false;
                textBox_carga_max.Enabled = checkBox_sens.Checked;
                label20.Enabled = checkBox_sens.Checked;
                textBox_url.Text = "";
            }
            else
            {
                btn_edit_camp_sensor.Enabled = checkBox_sens.Checked;
                btn_csv.Enabled = checkBox_sens.Checked;
                groupBox_sens.Enabled = checkBox_sens.Checked;
                textBox_carga_max.Enabled = checkBox_sens.Checked;
                label20.Enabled = checkBox_sens.Checked;
                textBox_url.Text = "";
            }
        }

        private void RecogidaDlg_FormClosed(object sender, FormClosedEventArgs e)
        {
            OliviaGlob.borra_files();
            OliviaGlob.inidlg.Cursor = Cursors.Default;
            OliviaGlob.inidlg.Show();         
        }

        private void comboBox_capac_DropDown(object sender, EventArgs e)
        {
            if (comboBox_capac.Items.Count == 0)
                toolTip1.Show("No hay información de capacidad para ese tipo de vehículo y ese tipo de carga", comboBox_capac);
        }

        private void comboBox_capac_DropDownClosed(object sender, EventArgs e)
        {
            if (comboBox_capac.Items.Count == 0)
                toolTip1.Hide(comboBox_capac);
        }

        /*
         * Lee en la capa seleccionada, a partir de los campos configurados el dialogo de editar campos, aquellos tipos de de basura (FRACCION), el tipo de carga y elt ipo de vehúclo.
         * De modo que sólo muestra en los desplegables correspondientes los datos existentes en la capa.
         */
        private void button_leer_tbl_Click(object sender, EventArgs e)
        {
            try
            {
                //se borra el listado que pudiera estar ya puesto para evitar duplicados
                comboBox_capac.Items.Clear();
                comboBox_carga.Items.Clear();
                comboBox_fraccion.Items.Clear();
                comboBox_lateralidad.Items.Clear();
                comboBox_vehic.Items.Clear();
                comboBox_lateralidad.Visible = false;

                //leer los campos de la tabla... si todo va bien: existe la tabla y los campos que se han editado
                if (!OliviaGlob.gdb_reco.lee_capa_recogida(reco))
                {
                    err_str = reco.err_st;
                    MessageBox.Show(err_str, "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                //se rellena el array que se incorpora al desplegable relacionado con el tipo de basura
                OliviaGlob.gdb_reco.lee_frac_gdb(reco);

                //se rellena el array que se incorpora al desplegable relacionado con el tipo de carga
                if (!OliviaGlob.gdb_reco.lee_tipocarga_gdb(reco))
                {
                    MessageBox.Show("Error al leer los tipos de carga en la capa seleccionada", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                //se rellena los desplegables relacionados con el tipo de contenedor (FRACCION) y desde dónde se recogen (tipo de carga)
                comboBox_fraccion.Items.AddRange(RecogidaDef.tipos_fracc_str);
                comboBox_carga.Items.AddRange(RecogidaDef.tipos_carg_str);
                comboBox_vehic.Items.AddRange(RecogidaDef.tipos_vehic_str);
                comboBox_lateralidad.Items.AddRange(RecogidaDef.tipos_lateralidad);

                //si se pasa la verificación de la lectura
                groupBox_tiporeco.Enabled = true;
                if (RecogidaDef.lleno)
                {
                    textBox_dens_cont.Visible = true;
                    label_dens_cont.Visible = true;
                }
                else
                {
                    textBox_dens_cont.Visible = false;
                    label_dens_cont.Visible = false;
                }
                //se eliminan los datos que pudiera haber ya introducidos en la zona de sensores y datos externos de CSV
                groupBox_sens.Enabled = false;
                textBox_url.Enabled = false;
                label24.Enabled = false;
                textBox_carga_max.Enabled = false;
                label20.Enabled = false;
                textBox_url.Text = "";
            }
            catch (Exception)
            {
                MessageBox.Show("Error al leer la capa seleccionada", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /*
         * Permite seleccionar la capa sobre la que se van a extraer los datos para el cálculo de la recogida de basuras.
         */
        private void button_dat_entrada_Click(object sender, EventArgs e)
        {
            string path_recogida;
            IFeatureClass fc;

            try
            {
                RecogidaDef.filtro_str = null;

                //se despliega el dialogo para seleccionar ua capa de la que se recogerán los datos de la recogida.
                path_recogida = FunGDB.selec_ftcls("Seleccionar datos de entrada para la recogida de residuos", this.Handle.ToInt32());

                if (path_recogida == null)
                {
                    err_str = "No se ha seleccionado ninguna capa para la recogida de residuos";
                    MessageBox.Show(err_str, "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    label_dat_entrada.Text = "Seleccionar Datos de entrada ...";

                    //Si se ha seleccionado unos datos de entrada que existen y todo ok, true, si no, false
                    button_edit_camp.Enabled = false;
                    groupBox_tiporeco.Enabled = false;
                    textBox_dens_cont.Visible = false;
                    label_dens_cont.Visible = false;
                    comboBox_fraccion.Items.Clear();
                    comboBox_carga.Items.Clear();
                    comboBox_vehic.Items.Clear();
                    comboBox_capac.Items.Clear();
                    comboBox_lateralidad.Items.Clear();
                    comboBox_lateralidad.Visible = false;
                    textBox_kgmax.Text = "";
                    groupBox_sens.Enabled = false;
                    textBox_url.Enabled = false;
                    label24.Enabled = false;
                    textBox_carga_max.Enabled = false;
                    label20.Enabled = false;
                    textBox_url.Text = "";

                    return;
                }

                //guarda el path completo de la clase
                OliviaGlob.gdb_reco.path_class = path_recogida;  

                //se comprueba que la capa seleccionada sea de puntos
                fc = FunGDB.abre_ftclass(OliviaGlob.gdb_reco.path_class);
                if (fc==null || !FunGDB.is_ftclass_punt(fc))
                {
                    MessageBox.Show("La capa seleccionada debe contener elementos puntuales.", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    FunGDB.libera(fc);
                    return;
                }

                //Si se ha seleccionado unos datos de entrada que existen y todo ok, true, si no, false
                label_dat_entrada.Text = System.IO.Path.GetFileNameWithoutExtension(path_recogida);
                button_edit_camp.Enabled = true;
                groupBox_tiporeco.Enabled = false;
                textBox_dens_cont.Visible = false;
                label_dens_cont.Visible = false;
                comboBox_fraccion.Items.Clear();
                comboBox_carga.Items.Clear();
                comboBox_vehic.Items.Clear();
                comboBox_capac.Items.Clear();
                textBox_kgmax.Text = "";
                groupBox_sens.Enabled = false;
                textBox_url.Enabled = false;
                label24.Enabled = false;
                textBox_carga_max.Enabled = false;
                label20.Enabled = false;
                textBox_url.Text = "";

                //se manda click a los campos y leer tabla
                click_edit_camps_sin_show();
                button_leer_tbl_Click(null, null);
            }
            catch (Exception)
            {
                MessageBox.Show("Error al abrir la capa de recogida de residuos.", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void checkBox_sector_autom_CheckedChanged(object sender, EventArgs e)
        {
            numericUpDown_sectores.Enabled = checkBox_ajust_sec.Enabled = !checkBox_sector_autom.Checked;
        }

        /**
        * 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_capa_zonas_Click(object sender, EventArgs e)
        {
            string text_sal;
            Hide();//esconde el dialogo
            if (reco.selec_polig("Seleccionar capa de zonas", this.Handle.ToInt32(), out text_sal, out reco.geom_zonas))
            {
                lbl_capa_zona.Text = text_sal;
                reco.text_zon = text_sal;
            }
            else
            {
                lbl_capa_zona.Text = reco.text_selec_zonas;
                reco.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_nave_sal_Click(object sender, EventArgs e)
        {
            string text_sal;
            Hide();//esconde el dialogo
            if (reco.selec_instal("Seleccionar capa de instalaciones de salida/llegada", this.Handle.ToInt32(), out text_sal,
                out reco.coords_instala[0], out reco.coords_instala[1]))
                instal_sel.Text = text_sal;
            else
                instal_sel.Text = reco.text_selec_instal;
            Show();          
        }

        /**
         * Se aplican restricciones de acceso a la circulación en determinados polígonos, 
         * dependiendo del tipo de vehículo
        */
        private void button_cap_restricc_Click(object sender, EventArgs e)
        {
            string text_sal;
            Hide();//esconde el dialogo
            if (reco.selec_polig("Seleccionar capa de restricciones de acceso", this.Handle.ToInt32(), out text_sal, out reco.geom_rest_acces))
            {
                lbl_capa_restricc.Text = text_sal;
                reco.text_restr = text_sal;
            }
            else
            {
                lbl_capa_restricc.Text = reco.text_selec_rest;
                reco.text_restr = "";
            }
            Show();             
        }
        
        /*
         * Seleccionada una capa se selecciona el lugar donde se va a descargar y se guardan las coordenadas del punto.
         */
        private void button_pto_desc_Click(object sender, EventArgs e)
        {
            string text_sal;
            Hide();//esconde el dialogo
            if (reco.selec_instal("Seleccionar capa de instalaciones de descarga", this.Handle.ToInt32(), out text_sal,
                out reco.coords_descarg[0], out reco.coords_descarg[1]))
                lbl_pto_descarg.Text = text_sal;
            else
                lbl_pto_descarg.Text = reco.text_selec_descarg;
            Show();            
        }

        /*
         * Se aplica capapara restricciones por zonificación en función de los turnos
         */
        private void button_capa_turno_Click(object sender, EventArgs e)
        {
            string text_sal;
            Hide();//esconde el dialogo
            if (reco.selec_polig("Seleccionar capa de zonificación por turnos", this.Handle.ToInt32(), out text_sal, out reco.geom_turnos))
            {
                lbl_turno.Text = text_sal;
                reco.text_turnos = text_sal;
            }
            else
            {
                lbl_turno.Text = reco.text_selec_turno;
                reco.text_turnos = "";
            }
            Show();             
        }

        /*
         * Se van a colorear en gris aquellos items que no se encuentran en la GDB y en negro los que sí se han encontrado.
         */
        private void comboBox_fraccion_DrawItem(object sender, DrawItemEventArgs e)
        {
            Font myFont = new Font("Arial", 10, FontStyle.Regular);
            int items = comboBox_fraccion.Items.Count;
            if (e.Index >= 0 && items != 0)
            {
                if (!reco.tipos_fracc_bool[e.Index])//si no se ha encontrado en la GDB se pinta de gris clarito 
                {
                    e.Graphics.DrawString(comboBox_fraccion.Items[e.Index].ToString(), e.Font, Brushes.LightGray, e.Bounds);
                }
                else
                {
                    e.Graphics.DrawString(comboBox_fraccion.Items[e.Index].ToString(), e.Font, Brushes.Black, e.Bounds);
                }
            }
        }

        /*
         * Se van a colorear en gris aquellos items que no se encuentran en la GDB y en negro los que sí se han encontrado.
         */
        private void comboBox_carga_DrawItem(object sender, DrawItemEventArgs e)
        {
            Font myFont = new Font("Arial", 10, FontStyle.Regular);
            int items = comboBox_carga.Items.Count;
            if (e.Index >= 0 && items != 0)
            {
                if (!reco.tipos_carg_bool[e.Index])//si no se ha encontrado en la GDB se pinta de gris clarito 
                {
                    e.Graphics.DrawString(comboBox_carga.Items[e.Index].ToString(), e.Font, Brushes.LightGray, e.Bounds);
                }
                else
                {
                    e.Graphics.DrawString(comboBox_carga.Items[e.Index].ToString(), e.Font, Brushes.Black, e.Bounds);
                }
            }
        }

        /**
         * Abre una ventana para la selección de las fechas que se quieren consultar en la URL marcada, donde se recogerán los datos de los sensores.
         */
        private void btn_edit_camp_sensor_Click(object sender, EventArgs e)
        {
            try
            {
                SensCampos camps = new SensCampos(reco);
                camps.ShowDialog();
                if (camps.acept == true)
                {
                    groupBox_sens.Enabled = true;
                    textBox_url.Enabled = true;
                    label24.Enabled = true;
                    textBox_carga_max.Enabled = true;
                    label20.Enabled = true;
                    textBox_url.Text = RecogidaDef.campos.cons_url_sens;
                }
                else
                {
                    groupBox_sens.Enabled = false;
                    textBox_url.Enabled = false;
                    label24.Enabled = false;
                    textBox_carga_max.Enabled = false;
                    label20.Enabled = false;
                    textBox_url.Text = "";
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Error con la ventana de edición de los campos para la lectura de sensores.", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        /**
         * Abre un diálogo para seleccionar el CSV del que se leerán los datos de carga de los contenedores a partir de los campos marcados que deberán existir en el CSV
         */
        private void btn_csv_Click(object sender, EventArgs e)
        {
            try
            {
                DatosCsv csv = new DatosCsv(reco);
                csv.ShowDialog();
                if (csv.acept == true)
                {
                    groupBox_sens.Enabled = true;
                    reco.rec_kgrec_cont = 0;
                    textBox_carga_max.Enabled = true;
                    label20.Enabled = true;
                    textBox_url.Text = "";
                    textBox_url.Enabled = false;
                    label24.Enabled = false;
                }
                else
                {
                    groupBox_sens.Enabled = false;
                    reco.rec_kgrec_cont = -1;
                    textBox_carga_max.Enabled = false;
                    label20.Enabled = false;
                    textBox_url.Text = "";
                    textBox_url.Enabled = false;
                    label24.Enabled = false;
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Error con la ventana de edición de los campos para la lectura de datos a partir de un CSV.", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        /**
         * 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 comboBox_lateralidad_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                reco.lateralidad = comboBox_lateralidad.SelectedIndex;
                if (reco.lateralidad < 0)
                {
                    MessageBox.Show("Hay que seleccionar un tipo de lateralidad para la carga", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Error al seleccionar el tipo lateralidad de la carga del vehículo", "Olivia", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        /*revisar borrar
         * private void RecogidaDlg_VisibleChanged(object sender, EventArgs e)
        {
            if (OliviaGlob.estado == TiposEstado.FinPlanif) 
            {
                groupBox_edits.Enabled = false;
                bt_planifica.Enabled = true;
                checkBox_aislados.Enabled = false;
                Show();
            }
        }*/

    }
}
