public IActionResult DeletePointOfInterest(int cityId, int id)
        {
            if (!_cityInfoRepository.CityExists(cityId))
            {
                return(NotFound());
            }

            Entities.PointOfInterest pointOfInterestEntity = _cityInfoRepository.GetPointOfInterestForCity(cityId, id);
            if (pointOfInterestEntity == null)
            {
                return(NotFound());
            }

            _cityInfoRepository.DeletePointOfInterest(pointOfInterestEntity);

            if (!_cityInfoRepository.Save())
            {
                return(StatusCode(500, "A problem happened while handling your request."));
            }

            _mailService.Send("Point of interest deleted.",
                              $"Point of interest {pointOfInterestEntity.Name} with id {pointOfInterestEntity.Id} was deleted.");


            // Without EF Core and Mapper
            //var city = CitiesDataStore.Current.Cities.FirstOrDefault(c => c.Id == cityId);
            //if (city == null)
            //{
            //    return NotFound();
            //}

            //var pointOfInterestFromStore = city.PointsOfInterest.FirstOrDefault(c => c.Id == id);
            //if (pointOfInterestFromStore == null)
            //{
            //    return NotFound();
            //}

            //city.PointsOfInterest.Remove(pointOfInterestFromStore);

            //_mailService.Send("Point of interest deleted.",
            //    $"Point of interest {pointOfInterestFromStore.Name} with id {pointOfInterestFromStore.Id} was deleted.");



            return(NoContent());
        }
        public IActionResult UpdatePointOfInterest(int cityId, int id,
                                                   [FromBody] PointOfInterestForUpdateDto pointOfInterest)
        {
            if (pointOfInterest == null)
            {
                return(BadRequest());
            }

            if (pointOfInterest.Description == pointOfInterest.Name)
            {
                ModelState.AddModelError("Description", "The provided description should be different from the name.");
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            if (!_cityInfoRepository.CityExists(cityId))
            {
                return(NotFound());
            }

            Entities.PointOfInterest pointOfInterestEntity = _cityInfoRepository.GetPointOfInterestForCity(cityId, id);
            if (pointOfInterestEntity == null)
            {
                return(NotFound());
            }

            // AutoMapper will override the values in the destination object (pointOfInterestEntity) with the values in the source object(pointOfInterest)
            Mapper.Map(pointOfInterest, pointOfInterestEntity); //src, dest

            if (!_cityInfoRepository.Save())
            {
                return(StatusCode(500, "A problem happened while handling your request."));
            }

            return(NoContent());

            // >> Without AutoMapper, without Repository
            //var city = CitiesDataStore.Current.Cities.FirstOrDefault(c => c.Id == cityId);

            //if (city == null)
            //{
            //    return NotFound();
            //}


            //var pointOfInterestFromStore = city.PointsOfInterest.FirstOrDefault(p =>
            //    p.Id == id);

            //if (pointOfInterestFromStore == null)
            //{
            //    return NotFound();
            //}

            //pointOfInterestFromStore.Name = pointOfInterest.Name;
            //pointOfInterestFromStore.Description = pointOfInterest.Description;

            //return NoContent();
            // <<
        }
        public IActionResult PartiallyUpdatePointOfInterest(int cityId, int id,
                                                            [FromBody] JsonPatchDocument <PointOfInterestForUpdateDto> patchDoc)
        {
            if (patchDoc == null)
            {
                return(BadRequest());
            }

            if (!_cityInfoRepository.CityExists(cityId))
            {
                return(NotFound());
            }

            Entities.PointOfInterest pointOfInterestEntity = _cityInfoRepository.GetPointOfInterestForCity(cityId, id);
            if (pointOfInterestEntity == null)
            {
                return(NotFound());
            }

            PointOfInterestForUpdateDto pointOfInterestToPatch = Mapper.Map <PointOfInterestForUpdateDto>(pointOfInterestEntity);

            //var city = CitiesDataStore.Current.Cities.FirstOrDefault(c => c.Id == cityId);
            //if (city == null)
            //{
            //    return NotFound();
            //}

            //var pointOfInterestFromStore = city.PointsOfInterest.FirstOrDefault(c => c.Id == id);
            //if (pointOfInterestFromStore == null)
            //{
            //    return NotFound();
            //}


            //var pointOfInterestToPatch =
            //    new PointOfInterestForUpdateDto()
            //    {
            //        Name = pointOfInterestFromStore.Name,
            //        Description = pointOfInterestFromStore.Description
            //    };
            //  pointOfInterestFromStore.Name = pointOfInterestToPatch.Name;
            //  pointOfInterestFromStore.Description = pointOfInterestToPatch.Description;

            patchDoc.ApplyTo(pointOfInterestToPatch, ModelState);

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            if (pointOfInterestToPatch.Description == pointOfInterestToPatch.Name)
            {
                ModelState.AddModelError("Description", "The provided description should be different from the name.");
            }

            TryValidateModel(pointOfInterestToPatch);

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            Mapper.Map(pointOfInterestToPatch, pointOfInterestEntity);

            if (!_cityInfoRepository.Save())
            {
                return(StatusCode(500, "A problem happened while handling your request."));
            }


            return(NoContent());
        }
        public IActionResult CreatePointOfInterest(int cityId,
                                                   [FromBody] PointOfInterestForCreationDto pointOfInterest)
        {
            if (pointOfInterest == null)
            {
                return(BadRequest());
            }

            // Voor een betere validatie mechanisme zie: https://github.com/jeremySkinner/FluentValidation
            // Nu validatie met DataAnnotation en in de controller..

            if (pointOfInterest.Description == pointOfInterest.Name)
            {
                ModelState.AddModelError("Description", " The provided description should be different from the name.");
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            if (!_cityInfoRepository.CityExists(cityId))
            {
                return(NotFound());
            }

            //>> Without repository
            //var city = CitiesDataStore.Current.Cities.FirstOrDefault(c => c.Id == cityId);
            //if (city == null)
            //{
            //    return NotFound();
            //}

            // demo purposes - to be improved
            //var maxPointOfInterestId = CitiesDataStore.Current.Cities.SelectMany(
            //                                              c => c.PointsOfInterest)
            //                                          .Max(p => p.Id);

            //var finalPointOfInterest = new PointOfInterestDto()
            //{
            //    Id = ++maxPointOfInterestId,
            //    Name = pointOfInterest.Name,
            //    Description = pointOfInterest.Description
            //};
            //

            // city.PointsOfInterest.Add(finalPointOfInterest);
            // return CreatedAtRoute("GetPointOfInterest", new {cityId = cityId, id = finalPointOfInterest.Id}, finalPointOfInterest);
            //<<

            Entities.PointOfInterest finalPointOfInterest = Mapper.Map <Entities.PointOfInterest>(pointOfInterest);

            _cityInfoRepository.AddPointOfInterestForCity(cityId, finalPointOfInterest);
            if (!_cityInfoRepository.Save())
            {
                return(StatusCode(500, "A problem happened while handling your request."));
            }

            PointOfInterestDto createdPointOfInterestToReturn = Mapper.Map <Models.PointOfInterestDto>(finalPointOfInterest);

            // helper methods
            return(CreatedAtRoute("GetPointOfInterest", new { cityId = cityId, id = finalPointOfInterest.Id }, createdPointOfInterestToReturn));
        }