private async Task UpdatePointsOfInterest(OsmChange changes)
        {
            var deleteTasks            = new List <Task>();
            var relevantTagsDictionary = _tagsHelper.GetAllTags();

            foreach (var poiToRemove in changes.Delete)
            {
                var task = _elasticSearchGateway.DeletePointOfInterestById(poiToRemove.Id.ToString(), poiToRemove.Type.ToString().ToLower());
                deleteTasks.Add(task);
            }
            await Task.WhenAll(deleteTasks);

            var updateTasks = new List <Task <ICompleteOsmGeo> >();

            foreach (var poiToUpdate in changes.Modify
                     .Concat(changes.Create)
                     .Where(o => IsRelevantPointOfInterest(o, relevantTagsDictionary)))
            {
                var task = _osmGateway.GetElement(poiToUpdate.Id.ToString(), poiToUpdate.Type.ToString().ToLower());
                updateTasks.Add(task);
            }
            var allElemets = await Task.WhenAll(updateTasks);

            var osmNamesDictionary     = allElemets.GroupBy(e => e.Tags.GetName()).ToDictionary(g => g.Key, g => g.ToList());
            var geoJsonNamesDictionary = _osmGeoJsonPreprocessorExecutor.Preprocess(osmNamesDictionary);

            await _elasticSearchGateway.UpdatePointsOfInterestData(geoJsonNamesDictionary.Values.SelectMany(v => v).ToList());
        }
        private async Task <Feature> UpdateElasticSearch(ICompleteOsmGeo osm, string name)
        {
            var feature = ConvertOsmToFeature(osm, name);

            if (feature == null)
            {
                return(null);
            }
            var featureFromDb = await _elasticSearchGateway.GetPointOfInterestById(feature.Attributes[FeatureAttributes.ID].ToString(), Sources.OSM);

            if (featureFromDb != null)
            {
                foreach (var attributeKey in featureFromDb.Attributes.GetNames().Where(n => n.StartsWith(FeatureAttributes.POI_PREFIX)))
                {
                    if (!feature.Attributes.GetNames().Any(n => n == attributeKey))
                    {
                        feature.Attributes.AddOrUpdate(attributeKey, featureFromDb.Attributes[attributeKey]);
                    }
                }
                if (feature.Geometry.OgcGeometryType == OgcGeometryType.Point &&
                    featureFromDb.Geometry.OgcGeometryType != OgcGeometryType.Point)
                {
                    feature.Geometry = featureFromDb.Geometry;
                }
            }

            await _elasticSearchGateway.UpdatePointsOfInterestData(new List <Feature> {
                feature
            });

            foreach (var language in Languages.Array)
            {
                var title = feature.Attributes.GetWikipediaTitle(language);
                if (string.IsNullOrWhiteSpace(title))
                {
                    continue;
                }
                var pageFetaure = await _wikipediaGateway.GetByPageTitle(title, language);

                if (pageFetaure == null)
                {
                    continue;
                }
                await _elasticSearchGateway.DeletePointOfInterestById(pageFetaure.Attributes[FeatureAttributes.ID].ToString(), Sources.WIKIPEDIA);
            }
            return(feature);
        }