using Manager.DTOs; using ManagerService.Data; using ManagerService.Data.SubSection; using ManagerService.DTOs; using ManagerService.Helpers; using ManagerService.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using NetTopologySuite.Geometries; using NSwag.Annotations; using System; using System.Collections.Generic; using System.Linq; using static ManagerService.Data.SubSection.SectionEvent; namespace ManagerService.Controllers { [Authorize] // TODO Add ROLES (Roles = "Admin") [ApiController, Route("api/[controller]")] [OpenApiTag("Section map", Description = "Section map management")] public class SectionMapController : ControllerBase { private readonly MyInfoMateDbContext _myInfoMateDbContext; private readonly ILogger _logger; private readonly IConfiguration _configuration; IHexIdGeneratorService idService = new HexIdGeneratorService(); public SectionMapController(IConfiguration configuration, ILogger logger, MyInfoMateDbContext myInfoMateDbContext) { _logger = logger; _configuration = configuration; _myInfoMateDbContext = myInfoMateDbContext; } /// /// Get all points from section /// /// Section id [AllowAnonymous] [ProducesResponseType(typeof(List), 200)] [ProducesResponseType(typeof(string), 404)] [ProducesResponseType(typeof(string), 500)] [HttpGet("{sectionId}/points")] public ObjectResult GetAllGeoPointsFromSection(string sectionId) { try { SectionMap sectionMap = _myInfoMateDbContext.Sections.OfType().Include(sm => sm.MapPoints).FirstOrDefault(sm => sm.Id == sectionId); if (sectionMap == null) throw new KeyNotFoundException("Section map does not exist"); List geoPointDTOs = new List(); foreach (var point in sectionMap.MapPoints) { foreach (var content in point.Contents) { var resource = _myInfoMateDbContext.Resources.FirstOrDefault(r => r.Id == content.resourceId); if (resource != null) { content.resource = resource.ToDTO(); } } geoPointDTOs.Add(new GeoPointDTO() { id = point.Id, title = point.Title, description = point.Description, contents = point.Contents, categorieId = point.CategorieId, geometry = point.Geometry?.ToDto(), polyColor = point.PolyColor, imageResourceId = point.ImageResourceId, imageUrl = point.ImageUrl, schedules = point.Schedules, prices = point.Prices, phone = point.Phone, email = point.Email, site = point.Site }); } return new OkObjectResult(geoPointDTOs); } catch (KeyNotFoundException ex) { return new NotFoundObjectResult(ex.Message) { }; } catch (Exception ex) { return new ObjectResult(ex.Message) { StatusCode = 500 }; } } /// /// Create new point /// /// Section Id /// geoPoint [ProducesResponseType(typeof(GeoPointDTO), 200)] [ProducesResponseType(typeof(string), 400)] [ProducesResponseType(typeof(string), 409)] [ProducesResponseType(typeof(string), 500)] [HttpPost("{sectionId}/points")] public ObjectResult Create(string sectionId, [FromBody] GeoPointDTO geoPointDTO) { try { if (sectionId == null) throw new ArgumentNullException("Section param is null"); if (geoPointDTO == null) throw new ArgumentNullException("GeoPoint is null"); var existingSection = _myInfoMateDbContext.Sections.OfType().Include(s => s.MapPoints).FirstOrDefault(s => s.Id == sectionId); if (existingSection == null) throw new KeyNotFoundException("Section map does not exist"); // TODO verification ? GeoPoint geoPoint = new GeoPoint(); geoPoint.Title = geoPointDTO.title; geoPoint.Description = geoPointDTO.description; geoPoint.Contents = geoPointDTO.contents; geoPoint.CategorieId = geoPointDTO.categorieId; if (geoPointDTO.geometry != null) { geoPoint.Geometry = geoPointDTO.geometry.FromDto(); } else { geoPoint.Geometry = null; } geoPoint.PolyColor = geoPointDTO.polyColor; geoPoint.ImageResourceId = geoPointDTO.imageResourceId; geoPoint.ImageUrl = geoPointDTO.imageUrl; // TO BE TESTED ? Depends on front geoPoint.Schedules = geoPointDTO.schedules; geoPoint.Prices = geoPointDTO.prices; geoPoint.Phone = geoPointDTO.phone; geoPoint.Email = geoPointDTO.email; geoPoint.Site = geoPointDTO.site; if (existingSection.MapPoints == null) { existingSection.MapPoints = []; } existingSection.MapPoints.Add(geoPoint); _myInfoMateDbContext.SaveChanges(); var geoPointDto = new GeoPointDTO() { id = geoPoint.Id, title = geoPoint.Title, description = geoPoint.Description, contents = geoPoint.Contents, categorieId = geoPoint.CategorieId, geometry = geoPoint.Geometry?.ToDto(), polyColor = geoPointDTO.polyColor, imageResourceId = geoPoint.ImageResourceId, imageUrl = geoPoint.ImageUrl, schedules = geoPoint.Schedules, prices = geoPoint.Prices, phone = geoPoint.Phone, email = geoPoint.Email, site = geoPoint.Site }; return new OkObjectResult(geoPointDto); } catch (ArgumentNullException ex) { return new BadRequestObjectResult(ex.Message) { }; } catch (InvalidOperationException ex) { return new ConflictObjectResult(ex.Message) { }; } catch (Exception ex) { return new ObjectResult(ex.Message) { StatusCode = 500 }; } } /// /// Update a geo point /// /// GeoPoint to update [ProducesResponseType(typeof(GeoPoint), 200)] [ProducesResponseType(typeof(string), 400)] [ProducesResponseType(typeof(string), 404)] [ProducesResponseType(typeof(string), 500)] [HttpPut] public ObjectResult Update([FromBody] GeoPointDTO geoPointDTO) { try { if (geoPointDTO == null) throw new ArgumentNullException("GeoPoint param is null"); var existingGeoPoint = _myInfoMateDbContext.GeoPoints.FirstOrDefault(gp => gp.Id == geoPointDTO.id); if (existingGeoPoint == null) throw new KeyNotFoundException("GeoPoint does not exist"); existingGeoPoint.Title = geoPointDTO.title; existingGeoPoint.Description = geoPointDTO.description; existingGeoPoint.Contents = geoPointDTO.contents; existingGeoPoint.CategorieId = geoPointDTO.categorieId; existingGeoPoint.Geometry = geoPointDTO.geometry.FromDto(); existingGeoPoint.PolyColor = geoPointDTO.polyColor; existingGeoPoint.ImageResourceId = geoPointDTO.imageResourceId; existingGeoPoint.ImageUrl = geoPointDTO.imageUrl; existingGeoPoint.Schedules = geoPointDTO.schedules; existingGeoPoint.Prices = geoPointDTO.prices; existingGeoPoint.Phone = geoPointDTO.phone; existingGeoPoint.Email = geoPointDTO.email; existingGeoPoint.Site = geoPointDTO.site; _myInfoMateDbContext.SaveChanges(); return new OkObjectResult(existingGeoPoint); } catch (ArgumentNullException ex) { return new BadRequestObjectResult(ex.Message) { }; } catch (KeyNotFoundException ex) { return new NotFoundObjectResult(ex.Message) { }; } catch (Exception ex) { return new ObjectResult(ex.Message) { StatusCode = 500 }; } } /// /// Update sections order /// /// New sections order /*[ProducesResponseType(typeof(string), 200)] [ProducesResponseType(typeof(string), 400)] [ProducesResponseType(typeof(string), 404)] [ProducesResponseType(typeof(string), 500)] [HttpPut("order")] public ObjectResult UpdateOrder([FromBody] List updatedSectionsOrder) { // TODO REWRITE LOGIC.. try { if (updatedSectionsOrder == null) throw new ArgumentNullException("Sections param is null"); foreach (var section in updatedSectionsOrder) { var sectionDB = _myInfoMateDbContext.Sections.FirstOrDefault(s => s.Id == section.id); if (sectionDB == null) throw new KeyNotFoundException($"Section {section.label} with id {section.id} does not exist"); } foreach (var updatedSection in updatedSectionsOrder) { var section = _myInfoMateDbContext.Sections.FirstOrDefault(s => s.Id == updatedSection.id); //OldSection section = _sectionService.GetById(updatedSection.id); section.Order = updatedSection.order.GetValueOrDefault(); _myInfoMateDbContext.SaveChanges(); //_sectionService.Update(section.Id, section); } if (updatedSectionsOrder.Count > 0) { MqttClientService.PublishMessage($"config/{updatedSectionsOrder[0].configurationId}", JsonConvert.SerializeObject(new PlayerMessageDTO() { configChanged = true })); } return new ObjectResult("Sections order has been successfully modified") { StatusCode = 200 }; } catch (ArgumentNullException ex) { return new BadRequestObjectResult(ex.Message) { }; } catch (KeyNotFoundException ex) { return new NotFoundObjectResult(ex.Message) { }; } catch (Exception ex) { return new ObjectResult(ex.Message) { StatusCode = 500 }; } }*/ /// /// Delete a geopoint /// /// Id of geopoint to delete [ProducesResponseType(typeof(string), 202)] [ProducesResponseType(typeof(string), 404)] [ProducesResponseType(typeof(string), 500)] [HttpDelete("points/{geoPointId}")] public ObjectResult Delete(int geoPointId) { try { var geoPoint = _myInfoMateDbContext.GeoPoints.FirstOrDefault(gp => gp.Id == geoPointId); if (geoPoint == null) throw new KeyNotFoundException("GeoPoint does not exist"); _myInfoMateDbContext.Remove(geoPoint); _myInfoMateDbContext.SaveChanges(); return new ObjectResult("The geopoint has been deleted") { StatusCode = 202 }; } catch (ArgumentNullException ex) { return new BadRequestObjectResult(ex.Message) { }; } catch (KeyNotFoundException ex) { return new NotFoundObjectResult(ex.Message) { }; } catch (Exception ex) { return new ObjectResult(ex.Message) { StatusCode = 500 }; } } /// /// Get all guided path from section /// /// Section id [AllowAnonymous] [ProducesResponseType(typeof(List), 200)] [ProducesResponseType(typeof(string), 404)] [ProducesResponseType(typeof(string), 500)] [HttpGet("{sectionMapId}/guided-path")] public ObjectResult GetAllGuidedPathFromSection(string sectionMapId) { try { List guidedPaths = _myInfoMateDbContext.GuidedPaths .Include(gp => gp.Steps).ThenInclude(gp => gp.QuizQuestions) .Include(gp => gp.Steps).ThenInclude(gp => gp.TriggerGeoPoint) .Where(gp => gp.SectionMapId == sectionMapId).ToList(); /*List programmeBlocks = new List(); foreach (var program in sectionEvent.Programme) { foreach (var mapAnnotation in program.MapAnnotations) { var resource = _myInfoMateDbContext.Resources.FirstOrDefault(r => r.Id == mapAnnotation.IconResourceId); if (resource != null) { mapAnnotation.IconResource = resource; // TO check.. use DTO instead ? } } }*/ return new OkObjectResult(guidedPaths.Select(gp => gp.ToDTO())); } catch (KeyNotFoundException ex) { return new NotFoundObjectResult(ex.Message) { }; } catch (Exception ex) { return new ObjectResult(ex.Message) { StatusCode = 500 }; } } /// /// Create new guided path /// /// Section map Id /// guidedPath [ProducesResponseType(typeof(GuidedPathDTO), 200)] [ProducesResponseType(typeof(string), 400)] [ProducesResponseType(typeof(string), 409)] [ProducesResponseType(typeof(string), 500)] [HttpPost("{sectionMapId}/guided-path")] public ObjectResult CreateGuidedPath(string sectionMapId, [FromBody] GuidedPathDTO guidedPathDTO) { try { if (sectionMapId == null) throw new ArgumentNullException("Section param is null"); if (guidedPathDTO == null) throw new ArgumentNullException("GuidedPath param is null"); var existingSection = _myInfoMateDbContext.Sections.OfType().FirstOrDefault(sm => sm.Id == sectionMapId); if (existingSection == null) throw new KeyNotFoundException("Section map does not exist"); GuidedPath guidedPath = new GuidedPath().FromDTO(guidedPathDTO); guidedPath.Id = idService.GenerateHexId(); _myInfoMateDbContext.GuidedPaths.Add(guidedPath); _myInfoMateDbContext.SaveChanges(); return new OkObjectResult(guidedPath.ToDTO()); } catch (ArgumentNullException ex) { return new BadRequestObjectResult(ex.Message) { }; } catch (InvalidOperationException ex) { return new ConflictObjectResult(ex.Message) { }; } catch (Exception ex) { return new ObjectResult(ex.Message) { StatusCode = 500 }; } } /// /// Update a guided path /// /// GuidedPath to update [ProducesResponseType(typeof(GuidedPathDTO), 200)] [ProducesResponseType(typeof(string), 400)] [ProducesResponseType(typeof(string), 404)] [ProducesResponseType(typeof(string), 500)] [HttpPut("guided-path")] public ObjectResult UpdateGuidedPath([FromBody] GuidedPathDTO guidedPathDTO) { try { if (guidedPathDTO == null) throw new ArgumentNullException("GuidedPath param is null"); var existingGuidedPath = _myInfoMateDbContext.GuidedPaths.FirstOrDefault(gp => gp.Id == guidedPathDTO.Id); if (existingGuidedPath == null) throw new KeyNotFoundException("GuidedPath does not exist"); existingGuidedPath.InstanceId = guidedPathDTO.InstanceId; existingGuidedPath.Title = guidedPathDTO.Title ?? new List(); existingGuidedPath.Description = guidedPathDTO.Description ?? new List(); existingGuidedPath.SectionMapId = guidedPathDTO.SectionMapId; existingGuidedPath.SectionEventId = guidedPathDTO.SectionEventId; existingGuidedPath.IsLinear = guidedPathDTO.IsLinear; existingGuidedPath.RequireSuccessToAdvance = guidedPathDTO.RequireSuccessToAdvance; existingGuidedPath.HideNextStepsUntilComplete = guidedPathDTO.HideNextStepsUntilComplete; existingGuidedPath.Order = guidedPathDTO.Order; _myInfoMateDbContext.SaveChanges(); return new OkObjectResult(existingGuidedPath); } catch (ArgumentNullException ex) { return new BadRequestObjectResult(ex.Message) { }; } catch (KeyNotFoundException ex) { return new NotFoundObjectResult(ex.Message) { }; } catch (Exception ex) { return new ObjectResult(ex.Message) { StatusCode = 500 }; } } /// /// Delete a guided path /// /// Id of the guidedPath to delete [ProducesResponseType(typeof(string), 202)] [ProducesResponseType(typeof(string), 404)] [ProducesResponseType(typeof(string), 500)] [HttpDelete("guided-path/{guidedPathId}")] public ObjectResult DeleteGuidedPath(string guidedPathId) { try { var guidedPath = _myInfoMateDbContext.GuidedPaths.FirstOrDefault(gp => gp.Id == guidedPathId); if (guidedPath == null) throw new KeyNotFoundException("GuidedPath does not exist"); _myInfoMateDbContext.Remove(guidedPath); _myInfoMateDbContext.SaveChanges(); return new ObjectResult("The guidedPath has been deleted") { StatusCode = 202 }; } catch (ArgumentNullException ex) { return new BadRequestObjectResult(ex.Message) { }; } catch (KeyNotFoundException ex) { return new NotFoundObjectResult(ex.Message) { }; } catch (Exception ex) { return new ObjectResult(ex.Message) { StatusCode = 500 }; } } /// /// Get all guided step from guided path /// /// Guided path id [AllowAnonymous] [ProducesResponseType(typeof(List), 200)] [ProducesResponseType(typeof(string), 404)] [ProducesResponseType(typeof(string), 500)] [HttpGet("guided-path/{guidedPathId}/guided-step")] public ObjectResult GetAllGuidedStepFromGuidedPath(string guidedPathId) { try { List guidedSteps = _myInfoMateDbContext.GuidedSteps .Include(gs => gs.QuizQuestions) .Include(gs => gs.TriggerGeoPoint) .Where(gs => gs.GuidedPathId == guidedPathId).ToList(); /*List programmeBlocks = new List(); foreach (var program in sectionEvent.Programme) { foreach (var mapAnnotation in program.MapAnnotations) { var resource = _myInfoMateDbContext.Resources.FirstOrDefault(r => r.Id == mapAnnotation.IconResourceId); if (resource != null) { mapAnnotation.IconResource = resource; // TO check.. use DTO instead ? } } }*/ return new OkObjectResult(guidedSteps.Select(gs => gs.ToDTO())); } catch (KeyNotFoundException ex) { return new NotFoundObjectResult(ex.Message) { }; } catch (Exception ex) { return new ObjectResult(ex.Message) { StatusCode = 500 }; } } /// /// Create new guided step /// /// guidedPath Id /// guidedStep [ProducesResponseType(typeof(GuidedStepDTO), 200)] [ProducesResponseType(typeof(string), 400)] [ProducesResponseType(typeof(string), 409)] [ProducesResponseType(typeof(string), 500)] [HttpPost("guided-path/{guidedPathId}/guided-step")] public ObjectResult CreateGuidedStep(string guidedPathId, [FromBody] GuidedStepDTO guidedStepDTO) { try { if (guidedPathId == null) throw new ArgumentNullException("GuidedPathId param is null"); if (guidedStepDTO == null) throw new ArgumentNullException("GuidedStep param is null"); GuidedStep guidedStep = new GuidedStep().FromDTO(guidedStepDTO); guidedStep.Id = idService.GenerateHexId(); _myInfoMateDbContext.GuidedSteps.Add(guidedStep); _myInfoMateDbContext.SaveChanges(); return new OkObjectResult(guidedStep.ToDTO()); } catch (ArgumentNullException ex) { return new BadRequestObjectResult(ex.Message) { }; } catch (InvalidOperationException ex) { return new ConflictObjectResult(ex.Message) { }; } catch (Exception ex) { return new ObjectResult(ex.Message) { StatusCode = 500 }; } } /// /// Update a guided step /// /// GuidedStep to update [ProducesResponseType(typeof(GuidedStepDTO), 200)] [ProducesResponseType(typeof(string), 400)] [ProducesResponseType(typeof(string), 404)] [ProducesResponseType(typeof(string), 500)] [HttpPut("guided-step")] public ObjectResult UpdateGuidedStep([FromBody] GuidedStepDTO guidedStepDTO) { try { if (guidedStepDTO == null) throw new ArgumentNullException("GuidedStep param is null"); var existingGuidedStep = _myInfoMateDbContext.GuidedSteps.FirstOrDefault(gs => gs.Id == guidedStepDTO.Id); if (existingGuidedStep == null) throw new KeyNotFoundException("GuidedStep does not exist"); existingGuidedStep.GuidedPathId = guidedStepDTO.GuidedPathId; existingGuidedStep.Order = guidedStepDTO.Order; existingGuidedStep.Title = guidedStepDTO.Title; existingGuidedStep.Description = guidedStepDTO.Description; existingGuidedStep.Geometry = guidedStepDTO.Geometry != null ? guidedStepDTO.Geometry : null; // TO TEST existingGuidedStep.ZoneRadiusMeters = guidedStepDTO.ZoneRadiusMeters; existingGuidedStep.ImageUrl = guidedStepDTO.ImageUrl; existingGuidedStep.TriggerGeoPointId = guidedStepDTO.TriggerGeoPointId; existingGuidedStep.IsHiddenInitially = guidedStepDTO.IsHiddenInitially; existingGuidedStep.QuizQuestions = guidedStepDTO.QuizQuestions; // à convertir si besoin ? existingGuidedStep.IsStepTimer = guidedStepDTO.IsStepTimer; existingGuidedStep.IsStepLocked = guidedStepDTO.IsStepLocked; existingGuidedStep.TimerSeconds = guidedStepDTO.TimerSeconds; existingGuidedStep.TimerExpiredMessage = guidedStepDTO.TimerExpiredMessage; _myInfoMateDbContext.SaveChanges(); return new OkObjectResult(existingGuidedStep); } catch (ArgumentNullException ex) { return new BadRequestObjectResult(ex.Message) { }; } catch (KeyNotFoundException ex) { return new NotFoundObjectResult(ex.Message) { }; } catch (Exception ex) { return new ObjectResult(ex.Message) { StatusCode = 500 }; } } /// /// Delete a guided step /// /// Id of the guidedStep to delete [ProducesResponseType(typeof(string), 202)] [ProducesResponseType(typeof(string), 404)] [ProducesResponseType(typeof(string), 500)] [HttpDelete("guided-step/{guidedStepId}")] public ObjectResult DeleteGuidedStep(string guidedStepId) { try { var guidedStep = _myInfoMateDbContext.GuidedSteps.Include(gs => gs.QuizQuestions).FirstOrDefault(gs => gs.Id == guidedStepId); if (guidedStep == null) throw new KeyNotFoundException("GuidedStep does not exist"); guidedStep.QuizQuestions.Clear(); _myInfoMateDbContext.Remove(guidedStep); _myInfoMateDbContext.SaveChanges(); return new ObjectResult("The guidedStep has been deleted") { StatusCode = 202 }; } catch (ArgumentNullException ex) { return new BadRequestObjectResult(ex.Message) { }; } catch (KeyNotFoundException ex) { return new NotFoundObjectResult(ex.Message) { }; } catch (Exception ex) { return new ObjectResult(ex.Message) { StatusCode = 500 }; } } } }