public static List<string> ListErrors(Layer layer)
        {
            List<string> errors = new List<string>();
            int polygonsWithoutID = 0;
            foreach (var z in layer.Zones)
            {
                foreach (var p in z.Polygons)
                {

                    if (p.Name == null)
                        polygonsWithoutID++;

                    for (var i = 0; i < p.Locations.Count; i++)
                    {
                        var l = p.Locations[i];
                        l.Index = i;
                        if (!l.Latitude.HasValue)
                        {
                            errors.Add(string.Format("Error Latitud {0} del poligono {1} en finca {2}", l.Index, p.Name, z.Name));
                        }
                        if (!l.Longitude.HasValue)
                        {
                            errors.Add(string.Format("Error Longitud {0} del poligono {1} en finca {2}", l.Index, p.Name, z.Name));
                        }
                    }
                }
            }

            if (polygonsWithoutID > 0)
            {
                errors.Add(string.Format("{0} Polygons without ID", polygonsWithoutID));
            }

            return errors;
        }
        public Layer ReadKmlFile()
        {
            //TODO: Darle acceso a una carpeta con N archivos KML.
            var path = ConfigurationManager.AppSettings.Get("kmlparser.kmlfile"); //Modificar el nombre del archivo desde el App.config
            XDocument xDoc = XDocument.Load(path);
            XNamespace ns = "http://www.opengis.net/kml/2.2";

            var doc = xDoc.Descendants(ns + "Document").ToList();
            var layerElement = doc.Elements(ns + "Folder").First();

            Layer layer = new Layer();
            layer.Name = layerElement.Element(ns + "name").Value;
            layer.Zones = layerElement.Elements(ns + "Folder").Select(ze =>
                    new Zone(ze.Element(ns + "name").Value,
                              ze.Descendants(ns + "Placemark").Select(pm =>
                                    new Polygon()
                                    {
                                        Name = pm.Element(ns + "name").Value != null? pm.Element(ns + "name").Value : "Poligono",
                                        Locations = pm.Descendants(ns + "coordinates").FirstOrDefault() != null? pm.Descendants(ns + "coordinates").FirstOrDefault().Value.Trim()
                                                                        .Replace("\n", "")
                                                                        .Replace("\t", "")
                                                                        .Split(' ')
                                                                        .Select(x => new Location(ParseLatitude(x), ParseLongitude(x)))
                                                                        .ToList() : null,
                                        PolygonGeom = this.ParsePolygon(pm.Descendants(ns + "coordinates").FirstOrDefault() != null? pm.Descendants(ns + "coordinates").FirstOrDefault().Value.Trim()
                                                                       .Replace("\n", " ")
                                                                       .Replace("\t", " ")
                                                                       .Replace(",0 ", "|")
                                                                       .Replace(",", " ")
                                                                       .Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries) : new string[]{""})
                                    }).ToList()
                                )).ToList();
            return layer;
        }
        public void SaveLayer(Layer lay)
        {
            connection.Open();
            var cmd = connection.CreateCommand() as SqlCommand;
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.CommandText = "Layer_SaveLayer";
            cmd.Parameters.Add(new SqlParameter("@name", lay.Name));
            var desc = string.IsNullOrEmpty(lay.Description) ? DBNull.Value : (object)lay.Description;
            cmd.Parameters.Add(new SqlParameter("@description", desc));
            var idParameter = new SqlParameter("@ID", SqlDbType.Int) { Direction = ParameterDirection.Output };
            cmd.Parameters.Add(idParameter);
            cmd.ExecuteNonQuery();
            connection.Close();
            lay.Id = (int)idParameter.Value;

        }
        public static Layer ReadKmlFiles()
        {

            var path = ConfigurationManager.AppSettings.Get("kml.fincas.path");
            var filename = Directory.GetFiles(path).FirstOrDefault();
            XDocument xDoc = XDocument.Load(filename);
            XNamespace ns = "http://www.opengis.net/kml/2.2";

            var doc = xDoc.Descendants(ns + "Document").ToList();
            var layerElement = doc.Elements(ns + "Folder").First();

            Layer layer = new Layer();
            layer.Name = layerElement.Element(ns + "name").Value;
            layer.Zones = layerElement.Elements(ns + "Folder").Select(ze =>
                   new Zone(ze.Element(ns + "name").Value,
                              ze.Descendants(ns + "Placemark").Select(pm =>
                                    new Polygon()
                                    {
                                        Name = pm.Element(ns + "name").Value,
                                        Locations = pm.Descendants(ns + "coordinates").First().Value.Trim()
                                                                        .Replace("\n", "")
                                                                        .Replace("\t", "")
                                                                        .Split(' ')
                                                                        .Select(x => new Location(ParseLatitude(x), ParseLongitude(x)))
                                                                        .ToList(),
                                        PolygonGeom = ParsePolygon(pm.Descendants(ns + "coordinates").First().Value.Trim()
                                                                       .Replace("\n", " ")
                                                                       .Replace("\t", " ")
                                                                       .Replace(",0 ", "|")
                                                                       .Replace(",", " ")
                                                                       .Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries))
                                    }).ToList(),
                                ze.Element(ns + "description").Value,
                             "" //Agrega el basecampId a la zona (TODOS NULL PORQUE ES CARGA MASIVA)
                                )).ToList();
            //Una vez finalizado mover a la carpeta Achieved
            return layer;
        }
        public void SaveFincaFull(Layer lay)
        {
            using (var scope = new TransactionScope())
            {
                var layerDb = this.GetLayerByName(lay.Name);
                lay.Id = layerDb.Id;

                foreach (Zone z in lay.Zones)
                {
                    DeleteZone(z.Id);
                    SaveFinca(z, lay.Id);
                    foreach (Polygon pol in z.Polygons)
                    {
                        SaveFincaPolygon(pol, z.Id);
                        foreach (Location loc in pol.Locations)
                        {
                            SaveLocation(loc, pol.Id);
                        }
                    }
                }

                scope.Complete();
            }
        }
        public void SaveLayerFull(Layer lay)
        {
            using (var scope = new TransactionScope())
            {
                SaveLayer(lay);
                foreach (Zone z in lay.Zones)
                {
                    SaveZone(z, lay.Id);
                    foreach (Polygon pol in z.Polygons)
                    {
                        SavePolygon(pol, z.Id);
                        foreach (Location loc in pol.Locations)
                        {
                            SaveLocation(loc, pol.Id);
                        }
                    }
                }

                scope.Complete();
            }
        }
        public static List<string> ReadKmlFile(int id)
        {
            var errors = new List<string>();
            var path = ConfigurationManager.AppSettings.Get("kml.fincas.path");
            if (Directory.GetFiles(path).Count() > 1)
            {
                errors.Add("Se encontró mas de un archivo kml a procesar en la carpeta, estos archivos ya fueron eliminados. Intente nuevamente la operación");

                for (var i = 0; i <= Directory.GetFiles(path).Count(); i++ )
                {
                    var filename = Directory.GetFiles(path).FirstOrDefault();
                    var archivePath = ConfigurationManager.AppSettings.Get("kml.fincas.archive.path");
                    var archiveName = new FileInfo(filename).Name.Replace(".kml", string.Format("{0}.{1}.{2}.kml", "archive", DateTime.Now.ToString("yyyyMMdd"), DateTime.Now.ToString("HHmmss")));
                    if (!Directory.Exists(archivePath))
                        Directory.CreateDirectory(archivePath);
                    File.Move(filename, Path.Combine(archivePath, archiveName));
                }
            }
            else
            {
                BasecampRepository basecampRepo = new BasecampRepository(ConfigurationManager.ConnectionStrings["EarthwatchersConnection"].ConnectionString);
                var fincaRegionId = (basecampRepo.GetById(id)).RegionId;
                var FincasLayerName = "FincasLayer" + fincaRegionId;
                var filename = Directory.GetFiles(path).FirstOrDefault();
                XDocument xDoc = XDocument.Load(filename);
                XNamespace ns = "http://www.opengis.net/kml/2.2";

                var doc = xDoc.Descendants(ns + "Document").ToList();
                Layer layer = new Layer();
                layer.Name = FincasLayerName;
                layer.Zones = doc.Elements(ns + "Folder").Select(ze =>
                       new Zone(ze.Element(ns + "name").Value,
                                  ze.Descendants(ns + "Placemark").Select(pm =>
                                        new Polygon()
                                        {
                                            Name = pm.Element(ns + "name").Value,
                                            Locations = pm.Descendants(ns + "coordinates").First().Value.Trim()
                                                                            .Replace("\n", "")
                                                                            .Replace("\t", "")
                                                                            .Split(' ')
                                                                            .Select(x => new Location(ParseLatitude(x), ParseLongitude(x)))
                                                                            .ToList(),
                                            PolygonGeom = ParsePolygon(pm.Descendants(ns + "coordinates").First().Value.Trim()
                                                                           .Replace("\n", " ")
                                                                           .Replace("\t", " ")
                                                                           .Replace(",0 ", "|")
                                                                           .Replace(",", " ")
                                                                           .Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries))
                                        }).ToList(),
                                    ze.Element(ns + "description").Value,
                                 id.ToString() //Agrega el basecampId a la zona
                                    )).ToList();

                errors = KmlParserBasecamp.ListErrors(layer);

                if (errors.Count == 0)
                {
                    //Save finca
                    LayerRepository la = new LayerRepository(ConfigurationManager.ConnectionStrings["EarthwatchersConnection"].ConnectionString);
                    la.SaveFincaFull(layer);
                    LandRepository landRepo = new LandRepository(ConfigurationManager.ConnectionStrings["EarthwatchersConnection"].ConnectionString);
                    landRepo.LoadLandBasecamp(fincaRegionId);
                }

                //Una vez finalizado mover a la carpeta Achieved
                var archivePath = ConfigurationManager.AppSettings.Get("kml.fincas.archive.path");
                var archiveName = new FileInfo(filename).Name.Replace(".kml", string.Format("{0}.{1}.{2}.kml", "archive", DateTime.Now.ToString("yyyyMMdd"), DateTime.Now.ToString("HHmmss")));
                if (!Directory.Exists(archivePath))
                    Directory.CreateDirectory(archivePath);
                File.Move(filename, Path.Combine(archivePath, archiveName));
            }

            return errors;
        }
        public Layer ReadKmlFile()
        {
            //TODO: Darle acceso a una carpeta con N archivos KML.
            XDocument xDoc = XDocument.Load(ConfigurationManager.AppSettings.Get("kmlparser.kmlfile"));
            XNamespace ns = "http://www.opengis.net/kml/2.2";

            var doc = xDoc.Descendants(ns + "Document").ToList();
            var layerElement = doc.Elements(ns + "Folder").First();

            Layer layer = new Layer();
            layer.Name = "OTBN";

            //var pm = layerElement.Descendants(ns + "Placemark").First();
            //var name = pm.Element(ns + "name").Value;
            //var id = pm.Attribute("id").Value;

            var redZone = new Zone("Zona Roja", layerElement.Descendants(ns + "Folder").FirstOrDefault().Descendants(ns + "Placemark")
                                                            //.Where(pm => pm.Element(ns + "name").Value == "proteccion")
                                                            .Select(pm => new Polygon()
                                                            {
                                                                Name = pm.Attribute("id") != null ? pm.Attribute("id").Value : null,
                                                                Locations = pm.Descendants(ns + "coordinates").FirstOrDefault() != null ? pm.Descendants(ns + "coordinates").FirstOrDefault().Value.Trim()
                                                                                                .Replace("\n", "")
                                                                                                .Replace("\t", "")
                                                                                                .Split(' ')
                                                                                                .Select(x => new Location(ParseLatitude(x), ParseLongitude(x)))
                                                                                                .ToList() : null,
                                                                PolygonGeom = this.ParsePolygon(pm.Descendants(ns + "coordinates").FirstOrDefault().Value.Trim()
                                                                                               .Replace("\n", " ")
                                                                                               .Replace("\t", " ")
                                                                                               .Replace(",0 ", "|")
                                                                                               .Replace(",", " ")
                                                                                               .Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries))
                                                            }).ToList());

            var yellowZone = new Zone("Zona Amarilla", layerElement.Descendants(ns + "Folder").Skip(1).FirstOrDefault().Descendants(ns + "Placemark")
                                                            //.Where(pm => pm.Element(ns + "name").Value == "mcb")
                                                            .Select(pm => new Polygon()
                                                            {
                                                                Name = pm.Attribute("id") != null ? pm.Attribute("id").Value : null,
                                                                Locations = pm.Descendants(ns + "coordinates").FirstOrDefault() != null ? pm.Descendants(ns + "coordinates").FirstOrDefault().Value.Trim()
                                                                                                .Replace("\n", "")
                                                                                                .Replace("\t", "")
                                                                                                .Split(' ')
                                                                                                .Select(x => new Location(ParseLatitude(x), ParseLongitude(x)))
                                                                                                .ToList() : null,
                                                                PolygonGeom = this.ParsePolygon(pm.Descendants(ns + "coordinates").FirstOrDefault().Value.Trim()
                                                                                               .Replace("\n", " ")
                                                                                               .Replace("\t", " ")
                                                                                               .Replace(",0 ", "|")
                                                                                               .Replace(",", " ")
                                                                                               .Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries))
                                                            }).ToList());

            //var greenZone = new Zone("Zona Verde", layerElement.Descendants(ns + "Placemark")
            //                                                .Where(pm => pm.Element(ns + "name").Value == "potencial productivo")
            //                                                .Select(pm => new Polygon()
            //                                                {
            //                                                    Name = pm.Attribute("id") != null ? pm.Attribute("id").Value : null,
            //                                                    Locations = pm.Descendants(ns + "coordinates").First().Value.Trim()
            //                                                                                    .Replace("\n", "")
            //                                                                                    .Replace("\t", "")
            //                                                                                    .Split(' ')
            //                                                                                    .Select(x => new Location(ParseLatitude(x), ParseLongitude(x)))
            //                                                                                    .ToList(),
            //                                                    PolygonGeom = this.ParsePolygon(pm.Descendants(ns + "coordinates").First().Value.Trim()
            //                                                                                   .Replace("\n", " ")
            //                                                                                   .Replace("\t", " ")
            //                                                                                   .Replace(",0 ", "|")
            //                                                                                   .Replace(",", " ")
            //                                                                                   .Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries))
            //                                                }).ToList());
            layer.Zones = new List<Zone>();
            layer.Zones.Add(redZone);
            layer.Zones.Add(yellowZone);
            //layer.Zones.Add(greenZone);

            return layer;
        }