using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

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

namespace OliviaAddIn
{
    /**
    *	@file Recogida.cs
    *	Clase de las variables asociadas a la recogida de residuos.
    *	Contiene definiciones, nombres de campos, y las opciones configuradas en la ventana.
    */

    //*************************************************************************************
    /**
    *	Clase de las variables asociadas a la recogida de residuos.
    *	Contiene definiciones, nombres de campos, y las opciones configuradas en la ventana.
    */
    public class Recogida : Comun
    {
        //*************************************************************************************
        //Enums y structs
        public struct CargaMax
        {
            public int n;           //<Número de opciones de vehículos de ese tipo con esa carga
            public int i_def;       //<La opción por defecto de entre las posibles
            public int[] vol;       //<Array de opciones, su volumen en m3
            public int[,] offset;   //<Array de valores de correccion de los kg máximos de carga

        }
        //*************************************************************************************        
        //Variables 
        /**
         * Texto cuando no se ha seleccionado punto de descarga
         */
        public string text_selec_descarg = "Instalación de descarga";
        /**
        * Coordenadas de la instalación de partida, si las huibiera, 0 si no
        */
        public double[] coords_descarg = new double[2];
        /**
         * Texto cuando no se ha seleccionado capa de turno
         */
        public string text_selec_turno = "Capa de zonificación por turnos";
        /**
        * Geometría que componen los turnos seleccionadas, null si nunguno
        */
        public IGeometry geom_turnos = null;
        /**
         * Texto de turno
         */
        public string text_turnos = "";

        //*************************************************************************************
        /** 
        * Array de booleanos enumerando si se existen en la capa seleccionada los tipos de fracción
        */
        public bool[] tipos_fracc_bool = new bool[(int)RecogidaDef.TiposFracción.N - 1];
        /** 
        * Array de booleanos enumerando si se existen en la capa seleccionada los tipos de carga
        */
        public bool[] tipos_carg_bool = new bool[(int)RecogidaDef.TiposCarga.N - 1];
        /** 
        * Array de cadenas de caracteres enumerando si se existen en la capa seleccionada los tipos de vehículos
        */
        public bool[] tipos_vehic_bool = new bool[(int)RecogidaDef.TiposVehic.N];
        /** 
         * Array de cadenas de doubles enumerando los kg máximos permitidos por cada tipo de vehículo
         */
        public CargaMax[,] cargas_max_vehic = new CargaMax[(int)RecogidaDef.TiposCarga.N, (int)RecogidaDef.TiposVehic.N];     
        /**
         * Fracción de residuos elegida para la planificación
         */
        public int tipo_frac = -1;
        /**
         * Tipo de carga del vehículo elegido para la planificación
         */
        public int tipo_carg = -1;
        /**
        * Tipo de carga lateral (ambos, derecha, izquierda) del vehículo elegido para la planificación
        */
        public int lateralidad = -1;
        /**
         * Tipo de vehículo elegido para la planificación
         */
        public int tipo_vehic = -1;
        /**
         * Tipo de capacidad del vehículo elegida para la planificación
         */
        public int tipo_capa = -1;
        /**
         * Carga máxima del vehículo elegido para la planificación
         */
        public double carg_max_vehic = 1000;        
        /**
         * Tiempo de vaciado de los contenedores, en segundos
         */
        public double t_vaci = 30;
        /**
         * Ancho del vehículo, en metros
         */
        public double anch_vehic = 2.5;
        /**
         * Giro mínimo del vehículo, en º
         */
        public double giro_vehic = 100;        
        /*
         * Porcentaje de carga a partir del cual se recogen los contenedores
         */
        public int carga_max = -1;
        /*
        * Densidad de la carga de los contenedores
        */
        public double dens_cont = -1;
        /**
        * Capa que se selecciona como origen de datos para calcular la planificación de recogida de residuos.
        */
        public string dir_recogida = null;
        /**
        * Campo de identificadores de la fuente de datos de los sensores.
        */
        public string id_sens = null;
        /**
        * URL de dónde leer la fuente de datos de los sensores.
        */
        public string url_sens = null;
        /**
        * Fecha inicial en la que se registraron los datos de los sensores.
        */
        public string fecha_sens = null;
        /**
        * Fecha final en la que se registraron los datos de los sensores.
        */
        public string fechaf_sens = null;
        /**
        * Campo de identificadores de la fuente de datos de los datos externos.
        */
        public string id_csv = null;
        /**
        * Campo de llenado de la fuente de datos de los datos externos.
        */
        public string llen_csv = null;
        /**
        * Campo de la fecha de la fuente de datos de los datos externos.
        */
        public string fecha_csv = null;
        /**
        * Fecha inicial en la que se registraron los datos de los datos externos.
        */
        public string fechai_csv = null;
        /**
        * Fecha final en la que se registraron los datos de los datos externos.
        */
        public string fechaf_csv = null;
        /**
        * Indica si se hace la media entre la fecha inicial y la fecha final marcada en el campo de los sensores.
        */
        public int media = -1;
        /**
        * Array que contiene los IDS de los datos externos (CSV) que cumplen las fechas indicadas.
        */
        public int[] ids = null;
        /**
        * Array que contiene los porcentajes de llenado de los datos externos (CSV) que cumplen las fechas indicadas.
        */
        public int[] carga = null;
        /**
        * Campo del kg de la recogida de la capa de recogida de residuos.
        */
        public string rec_kg = null;
        /**
        * Campo de capacidad de la capa de recogida de residuos.
        */
        public string rec_capac = null;
        /**
        * Campo de unidades de la capa de recogida de residuos.
        */
        public string rec_uds = null;
        /**
        * Kg de recogida del contenedor de la capa de recogida de residuos.
         * -1 es que se va ahacer que están llenos los contenedores, 0 indica que se va a leer la columna de kgreco, y un valor !=0 es que se pone
         * dicho valor de kg de carga para todos igual
        */
        public int rec_kgrec_cont = -1;
        /**
         * listas con los identificadores y las cargas correspondientes de los datos externos introducidos por CSV
         */
        public List<int> id = null;//valores unicos de ids que cumplen con las fechas marcadas
        public List<double> cargas = null;//valor de la carga si solo tiene fecha inicial o Valor medio de las cargas que se encuentran entre fecha inicial y final

        //*************************************************************************************
        //Constructor
        public Recogida()
        {
            rellena_matrs();
            rellena_preffracc_gdb();
            rellena_prefcarg_gdb();
            rellena_simbol_rec();
            rellena_simb_tipbasura();
        }
        //*************************************************************************************
        //Métodos
        /**
         * Rellena las matrices de datos
         */
        private void rellena_matrs()
        {            
            //Rellena los tipos de vehículo
            RecogidaDef.tipos_vehic_str[(int)RecogidaDef.TiposVehic.Ejes3] = "3 Ejes";
            RecogidaDef.tipos_vehic_str[(int)RecogidaDef.TiposVehic.Ejes2] = "2 Ejes";
            RecogidaDef.tipos_vehic_str[(int)RecogidaDef.TiposVehic.Satelite] = "Satélite";
            
            //Rellena las densidades en camión
            RecogidaDef.dens_frac_cami[(int)RecogidaDef.TiposFracción.Organica] = RecogidaDef.Parametros.dens_vehi_org;
            RecogidaDef.dens_frac_cami[(int)RecogidaDef.TiposFracción.Resto] = RecogidaDef.Parametros.dens_vehi_res;
            RecogidaDef.dens_frac_cami[(int)RecogidaDef.TiposFracción.Envases] = RecogidaDef.Parametros.dens_vehi_env;
            RecogidaDef.dens_frac_cami[(int)RecogidaDef.TiposFracción.Papel] = RecogidaDef.Parametros.dens_vehi_pap;
            RecogidaDef.dens_frac_cami[(int)RecogidaDef.TiposFracción.Vidrio] = RecogidaDef.Parametros.dens_vehi_vid;
            RecogidaDef.dens_frac_cami[(int)RecogidaDef.TiposFracción.Otra] = RecogidaDef.Parametros.dens_vehi_otr;

            //Rellena las densidades en contenedor
            RecogidaDef.dens_frac_cont[(int)RecogidaDef.TiposFracción.Organica] = RecogidaDef.Parametros.dens_cont_org;
            RecogidaDef.dens_frac_cont[(int)RecogidaDef.TiposFracción.Resto] = RecogidaDef.Parametros.dens_cont_res;
            RecogidaDef.dens_frac_cont[(int)RecogidaDef.TiposFracción.Envases] = RecogidaDef.Parametros.dens_cont_env;
            RecogidaDef.dens_frac_cont[(int)RecogidaDef.TiposFracción.Papel] = RecogidaDef.Parametros.dens_cont_pap;
            RecogidaDef.dens_frac_cont[(int)RecogidaDef.TiposFracción.Vidrio] = RecogidaDef.Parametros.dens_cont_vid;
            RecogidaDef.dens_frac_cont[(int)RecogidaDef.TiposFracción.Otra] = RecogidaDef.Parametros.dens_cont_otr;

            //Rellena las anchuras de los vehículos
            RecogidaDef.ancho_vehic[(int)RecogidaDef.TiposVehic.Ejes3] = RecogidaDef.Parametros.anch_vehi_3;
            RecogidaDef.ancho_vehic[(int)RecogidaDef.TiposVehic.Ejes2] = RecogidaDef.Parametros.anch_vehi_2;
            RecogidaDef.ancho_vehic[(int)RecogidaDef.TiposVehic.Satelite] = RecogidaDef.Parametros.anch_vehi_s;

            //Rellena los ángulos de giro de los vehículos
            RecogidaDef.giro_vehic[(int)RecogidaDef.TiposVehic.Ejes3] = RecogidaDef.Parametros.rad_giro_3;
            RecogidaDef.giro_vehic[(int)RecogidaDef.TiposVehic.Ejes2] = RecogidaDef.Parametros.rad_giro_2;
            RecogidaDef.giro_vehic[(int)RecogidaDef.TiposVehic.Satelite] = RecogidaDef.Parametros.rad_giro_s;

            //Rellena los tiempos de vaciado
            RecogidaDef.t_vaci[(int)RecogidaDef.TiposCarga.Trasera] = RecogidaDef.Parametros.t_vaci_tra;
            RecogidaDef.t_vaci[(int)RecogidaDef.TiposCarga.Lateral] = RecogidaDef.Parametros.t_vaci_lat;
            RecogidaDef.t_vaci[(int)RecogidaDef.TiposCarga.Superior] = RecogidaDef.Parametros.t_vaci_sup;
            RecogidaDef.t_vaci[(int)RecogidaDef.TiposCarga.Bilateral] = RecogidaDef.Parametros.t_vaci_bi;
            RecogidaDef.t_vaci[(int)RecogidaDef.TiposCarga.BolseoPtaPta] = RecogidaDef.Parametros.t_vaci_bol;
            RecogidaDef.t_vaci[(int)RecogidaDef.TiposCarga.Lavado] = RecogidaDef.Parametros.t_vaci_lav;
            RecogidaDef.t_vaci[(int)RecogidaDef.TiposCarga.Otra] = RecogidaDef.Parametros.t_vaci_otr;


            //Rellena las matrices de carga máxima por tipo de vehículo y tipo de carga
            rellena_matrs_carg();
        }

        /**
         * Función general para rellenar campos de la matriz de cargas máximas por tipo de carga y de vehículo
         */
        private void rellena_carg(int icar, int iveh, int n, int i_def, int[] info)
        {
            cargas_max_vehic[icar, iveh].n = n;
            cargas_max_vehic[icar, iveh].i_def = i_def;
            cargas_max_vehic[icar, iveh].vol = null;
            cargas_max_vehic[icar, iveh].offset = null;
            if (n <= 0)
                return;
            cargas_max_vehic[icar, iveh].vol = new int[n];
            for (int i = 0; i < n; i++)
            {
                cargas_max_vehic[icar, iveh].vol[i] = info[i];
            }

        }

        /**
         * Función general para rellenar campos de la matriz de cargas máximas por tipo de carga y de vehículo
         */
        private void rellena_carg_offset(int icar, int iveh, int ifrac, int n, int[] info)
        {
            cargas_max_vehic[icar, iveh].offset = new int[n,(int)RecogidaDef.TiposFracción.N];
            for (int i = 0; i < n; i++)
            {
                cargas_max_vehic[icar, iveh].offset[i,ifrac] = info[i];
            }
        }

        /**
         * Rellena la matriz de las opciones de vehículos que hay de cada tipo de carga
         * y dimensión
         */
        private void rellena_matrs_carg()
        {
            int[] info = new int[10];
            int n, i_def, icar, iveh;

            //Rellena las opciones de carga máxima por vehículo
            //Trasera-satelite
            n = 4;
            i_def = 2;
            info[0] = 2;
            info[1] = 3;
            info[2] = 5;
            info[3] = 7;
            rellena_carg((int)RecogidaDef.TiposCarga.Trasera,
                (int)RecogidaDef.TiposVehic.Satelite, n, i_def, info);
            //rellena la corrección de la carga máxima
            info[0] = info[1] = -500;
            info[2] = info[3] = 0;
            rellena_carg_offset((int)RecogidaDef.TiposCarga.Trasera,
                (int)RecogidaDef.TiposVehic.Satelite, (int)RecogidaDef.TiposFracción.Resto, n, info);
            rellena_carg_offset((int)RecogidaDef.TiposCarga.Trasera,
                (int)RecogidaDef.TiposVehic.Satelite, (int)RecogidaDef.TiposFracción.Organica, n, info);

            //Trasera-2 ejes
            n = 6;
            i_def = 2;
            info[0] = 8;
            info[1] = 10;
            info[2] = 12;
            info[3] = 14;
            info[4] = 16;
            info[5] = 17;
            rellena_carg((int)RecogidaDef.TiposCarga.Trasera,
                (int)RecogidaDef.TiposVehic.Ejes2, n, i_def, info);
            //rellena la corrección de la carga máxima
            info[1] = -500;
            info[2] = -1000;
            info[3] = -1500;
            info[4] = -2000;
            info[0] = info[5] = 0;
            rellena_carg_offset((int)RecogidaDef.TiposCarga.Trasera,
                (int)RecogidaDef.TiposVehic.Ejes2, (int)RecogidaDef.TiposFracción.Resto, n, info);
            rellena_carg_offset((int)RecogidaDef.TiposCarga.Trasera,
                (int)RecogidaDef.TiposVehic.Ejes2, (int)RecogidaDef.TiposFracción.Organica, n, info);

            //Trasera-3ejes
            n = 4;
            i_def = 3;
            info[0] = 18;
            info[1] = 20;
            info[2] = 22;
            info[3] = 23;
            rellena_carg((int)RecogidaDef.TiposCarga.Trasera,
                (int)RecogidaDef.TiposVehic.Ejes3, n, i_def, info);

            //Lateral-satelite, no hay
            rellena_carg((int)RecogidaDef.TiposCarga.Lateral,
                (int)RecogidaDef.TiposVehic.Satelite, 0, 0, null);

            //Lateral - 2 ejes
            n = 2;
            i_def = 1;
            info[0] = 15;
            info[1] = 17;
            rellena_carg((int)RecogidaDef.TiposCarga.Lateral,
                (int)RecogidaDef.TiposVehic.Ejes2, n, i_def, info);
            //rellena la corrección de la carga máxima
            info[0] = -500;
            info[1] = -1000;
            rellena_carg_offset((int)RecogidaDef.TiposCarga.Lateral,
                (int)RecogidaDef.TiposVehic.Ejes2, (int)RecogidaDef.TiposFracción.Resto, n, info);
            rellena_carg_offset((int)RecogidaDef.TiposCarga.Lateral,
                (int)RecogidaDef.TiposVehic.Ejes2, (int)RecogidaDef.TiposFracción.Organica, n, info);

            //Lateral - 3 ejes
            n = 3;
            i_def = 2;
            info[0] = 21;
            info[1] = 23;
            info[2] = 26;
            rellena_carg((int)RecogidaDef.TiposCarga.Lateral,
                (int)RecogidaDef.TiposVehic.Ejes3, n, i_def, info);

            //Superior - satelite, no hay
            rellena_carg((int)RecogidaDef.TiposCarga.Superior,
                (int)RecogidaDef.TiposVehic.Satelite, 0, 0, null);

            //Superior - 2 ejes
            n = 2;
            i_def = 0;
            info[0] = 16;
            info[1] = 17;
            rellena_carg((int)RecogidaDef.TiposCarga.Superior,
                (int)RecogidaDef.TiposVehic.Ejes2, n, i_def, info);

            //Superior - 3 ejes
            n = 3;
            i_def = 2;
            info[0] = 20;
            info[1] = 23;
            info[2] = 25;
            rellena_carg((int)RecogidaDef.TiposCarga.Superior,
                (int)RecogidaDef.TiposVehic.Ejes3, n, i_def, info);

            //Bilateral - satelite, no hay
            rellena_carg((int)RecogidaDef.TiposCarga.Bilateral,
                (int)RecogidaDef.TiposVehic.Satelite, 0, 0, null);

            //Superior - 2 ejes
            n = 3;
            i_def = 1;
            info[0] = 14;
            info[1] = 16;
            info[2] = 18;
            rellena_carg((int)RecogidaDef.TiposCarga.Bilateral,
                (int)RecogidaDef.TiposVehic.Ejes2, n, i_def, info);

            //Superior - 3 ejes
            n = 3;
            i_def = 1;
            info[0] = 20;
            info[1] = 23;
            info[2] = 26;
            rellena_carg((int)RecogidaDef.TiposCarga.Bilateral,
                (int)RecogidaDef.TiposVehic.Ejes3, n, i_def, info);

            //Bolseo - todas, no hay
            //Lavado - todas, no hay
            //Otra - todas, no hay
            for (icar = (int)RecogidaDef.TiposCarga.BolseoPtaPta; icar < (int)RecogidaDef.TiposCarga.N; icar++)
            {
                for (iveh = (int)RecogidaDef.TiposVehic.Ejes3; iveh < (int)RecogidaDef.TiposVehic.N; iveh++)
                {
                    rellena_carg(icar, iveh, 0, 0, null);
                }
            }
        }        

        /**
        * Inicializa la matriz de strings con los prefijos (fracción) que llevarán los featureclass de la geodatabase importada a ArcGIS una vez realizada la planificación
        */
        public void rellena_preffracc_gdb()
        {
            RecogidaDef.preffracc_gdb[(int)RecogidaDef.TiposFracción.Organica] = "Org";
            RecogidaDef.preffracc_gdb[(int)RecogidaDef.TiposFracción.Resto] = "R";
            RecogidaDef.preffracc_gdb[(int)RecogidaDef.TiposFracción.Envases] = "E";
            RecogidaDef.preffracc_gdb[(int)RecogidaDef.TiposFracción.Papel] = "P";
            RecogidaDef.preffracc_gdb[(int)RecogidaDef.TiposFracción.Vidrio] = "V";
            RecogidaDef.preffracc_gdb[(int)RecogidaDef.TiposFracción.Otra] = "Otr_" + OliviaGlob.gdb_reco.fra_otra;
        }

        /**
        * Inicializa la matriz de strings con los prefijos (fracción) que llevarán los featureclass de la geodatabase importada a ArcGIS una vez realizada la planificación
        */
        public void rellena_prefcarg_gdb()
        {
            RecogidaDef.prefcarg_gdb[(int)RecogidaDef.TiposFracción.Organica] = "Tra";
            RecogidaDef.prefcarg_gdb[(int)RecogidaDef.TiposFracción.Resto] = "Lat";
            RecogidaDef.prefcarg_gdb[(int)RecogidaDef.TiposFracción.Envases] = "BiLat";
            RecogidaDef.prefcarg_gdb[(int)RecogidaDef.TiposFracción.Papel] = "Bols";
            RecogidaDef.prefcarg_gdb[(int)RecogidaDef.TiposFracción.Vidrio] = "Lav";
            RecogidaDef.prefcarg_gdb[(int)RecogidaDef.TiposFracción.Otra] = "Otr_" + OliviaGlob.gdb_reco.carg_otra;
        }

        /**
        * Inicializa la matriz de strings con los tipos de recogida
        */
        public void rellena_simbol_rec()
        {
            RecogidaDef.simb_rec_vsm[0] = RecogidaDef.nombre_simbrec_vsm[0];
            RecogidaDef.simb_rec_vsm[1] = RecogidaDef.nombre_simbrec_vsm[1];
            RecogidaDef.simb_rec_vsm[2] = RecogidaDef.nombre_simbrec_vsm[2];
            RecogidaDef.simb_rec_vsm[3] = RecogidaDef.nombre_simbrec_vsm[3];
            RecogidaDef.simb_rec_vsm[4] = RecogidaDef.nombre_simbrec_vsm[4];
            RecogidaDef.simb_rec_vsm[5] = RecogidaDef.nombre_simbrec_vsm[5];
            RecogidaDef.simb_rec_vsm[6] = RecogidaDef.tipos_carg_str[(int)RecogidaDef.TiposCarga.Lateral];
            RecogidaDef.simb_rec_vsm[7] = RecogidaDef.tipos_carg_str[(int)RecogidaDef.TiposCarga.Trasera];
            RecogidaDef.simb_rec_vsm[8] = RecogidaDef.tipos_carg_str[(int)RecogidaDef.TiposCarga.Superior];
        }

        /**
        * Inicializa la matriz de strings con los tipos de recogida
        */
        public void rellena_simb_tipbasura()
        {
            RecogidaDef.simb_tipbasura[0] = RecogidaDef.tipos_fracc_str[(int)RecogidaDef.TiposFracción.Envases];
            RecogidaDef.simb_tipbasura[1] = RecogidaDef.tipos_fracc_str[(int)RecogidaDef.TiposFracción.Papel];
            RecogidaDef.simb_tipbasura[2] = RecogidaDef.tipos_fracc_str[(int)RecogidaDef.TiposFracción.Vidrio];
            RecogidaDef.simb_tipbasura[3] = RecogidaDef.tipos_fracc_str[(int)RecogidaDef.TiposFracción.Organica];
            RecogidaDef.simb_tipbasura[4] = RecogidaDef.tipos_fracc_str[(int)RecogidaDef.TiposFracción.Resto];
        }
    }
}
