using OperationControl.Mapas.Models; using static AgroBase.Models.Enums; namespace OperationControl.Mapas.Services { public sealed class MapaEntidadeDinamicaService { public MapaEntidadeDinamica DefinirBase( MapaEstadoDinamico estado, string id, string nome, double? latitude, double? longitude, double? heading = null, double? latitudeBruta = null, double? longitudeBruta = null) { return DefinirEntidade( estado, id, MapaTipoEntidadeDinamica.Base, nome, latitude, longitude, heading, latitudeBruta, longitudeBruta ); } public MapaEntidadeDinamica DefinirRover( MapaEstadoDinamico estado, string id, string nome, double? latitude, double? longitude, double? heading = null, double? latitudeBruta = null, double? longitudeBruta = null) { return DefinirEntidade( estado, id, MapaTipoEntidadeDinamica.Rover, nome, latitude, longitude, heading, latitudeBruta, longitudeBruta ); } public void AtualizarPosicao( MapaEstadoDinamico estado, string id, double? latitude, double? longitude, double? heading = null, double? latitudeBruta = null, double? longitudeBruta = null) { var entidade = ObterObrigatoria( estado, id ); if ( latitude.HasValue && longitude.HasValue ) { ValidarCoordenada( latitude.Value, longitude.Value ); entidade.Latitude = latitude.Value; entidade.Longitude = longitude.Value; } if ( heading.HasValue && double.IsFinite( heading.Value ) ) { entidade.Heading = NormalizarHeading( heading.Value ); } if ( latitudeBruta.HasValue && longitudeBruta.HasValue ) { ValidarCoordenada( latitudeBruta.Value, longitudeBruta.Value ); entidade.LatitudeBruta = latitudeBruta.Value; entidade.LongitudeBruta = longitudeBruta.Value; } } public void AtualizarStatus( MapaEstadoDinamico estado, string id, StatusOperacao status, bool? pulverizando = null) { var entidade = ObterObrigatoria( estado, id ); entidade.Status = status; if (pulverizando.HasValue) { entidade.Pulverizando = pulverizando.Value; } } public void DefinirFoco( MapaEstadoDinamico estado, string? id) { ValidarEstado( estado ); foreach ( var entidade in estado.EntidadesMutaveis.Values) { entidade.EmFoco = false; } if ( string.IsNullOrWhiteSpace(id) ) { return; } if ( estado.EntidadesMutaveis.TryGetValue( id.Trim(), out var selecionada ) ) { selecionada.EmFoco = true; } } public MapaEntidadeDinamica? Obter( MapaEstadoDinamico estado, string id) { ValidarEstado( estado ); if ( string.IsNullOrWhiteSpace(id) ) { return null; } estado.EntidadesMutaveis .TryGetValue( id.Trim(), out var entidade ); return entidade; } public bool Remover( MapaEstadoDinamico estado, string id) { ValidarEstado( estado ); if ( string.IsNullOrWhiteSpace(id) ) { return false; } return estado .EntidadesMutaveis .Remove( id.Trim() ); } private MapaEntidadeDinamica DefinirEntidade( MapaEstadoDinamico estado, string id, MapaTipoEntidadeDinamica tipo, string nome, double? latitude, double? longitude, double? heading, double? latitudeBruta, double? longitudeBruta) { ValidarEstado( estado ); if ( string.IsNullOrWhiteSpace(id) ) { throw new ArgumentException( "O ID da entidade não foi informado.", nameof(id) ); } string idCanonico = id.Trim(); if ( !estado.EntidadesMutaveis .TryGetValue( idCanonico, out var entidade ) ) { entidade = new MapaEntidadeDinamica { Id = idCanonico }; estado.EntidadesMutaveis[ idCanonico ] = entidade; } entidade.Tipo = tipo; entidade.Nome = string.IsNullOrWhiteSpace(nome) ? idCanonico : nome.Trim(); AtualizarPosicao( estado, idCanonico, latitude, longitude, heading, latitudeBruta, longitudeBruta ); return entidade; } private static MapaEntidadeDinamica ObterObrigatoria( MapaEstadoDinamico estado, string id) { ValidarEstado( estado ); if ( string.IsNullOrWhiteSpace(id) ) { throw new ArgumentException( "O ID da entidade não foi informado.", nameof(id) ); } if ( !estado.EntidadesMutaveis .TryGetValue( id.Trim(), out var entidade ) ) { throw new InvalidOperationException( $"A entidade '{id}' não existe." ); } return entidade; } private static void ValidarCoordenada( double latitude, double longitude) { if ( !double.IsFinite(latitude) || latitude < -90.0 || latitude > 90.0 ) { throw new ArgumentOutOfRangeException( nameof(latitude), "Latitude WGS84 inválida." ); } if ( !double.IsFinite(longitude) || longitude < -180.0 || longitude > 180.0 ) { throw new ArgumentOutOfRangeException( nameof(longitude), "Longitude WGS84 inválida." ); } } private static double NormalizarHeading( double heading) { double normalizado = heading % 360.0; if (normalizado < 0) { normalizado += 360.0; } return normalizado; } private static void ValidarEstado( MapaEstadoDinamico estado) { if (estado == null) { throw new ArgumentNullException( nameof(estado) ); } } } }