using OperationControl.Helpers; using OperationControl.Models; using OperationControl.Windows; using System.ComponentModel; using System.Globalization; using System.Windows; using System.Windows.Input; using static OperationControl.Services.BaseFixService; using static OperationControl.Services.GpsService; namespace OperationControl.ViewModels { public class MetodoFixacaoItem { public MetodoFixacaoBase Valor { get; set; } public string Nome { get; set; } = string.Empty; } public class PreparacaoMapaBottomViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler? PropertyChanged; public event Action? CarregarMapaSolicitado; // Método, latitude, longitude, altitude, offset frontal cm, offset lateral cm public event Action? FixarBaseSolicitado; // Offset frontal cm, offset lateral cm public event Action? AplicarOffsetSolicitado; public event Action? UsarGnssMovelSolicitado; public event Action? ContinuarSolicitado; public event Action? VoltarSolicitado; public List MetodosFixacaoDisponiveis { get; } = new() { new MetodoFixacaoItem { Valor = MetodoFixacaoBase.Ntrip, Nome = "Correção pela rede (NTRIP)" }, new MetodoFixacaoItem { Valor = MetodoFixacaoBase.SurveyIn, Nome = "Determinar posição no local" }, new MetodoFixacaoItem { Valor = MetodoFixacaoBase.Manual, Nome = "Informar posição conhecida" } }; public ICommand CarregarMapaCommand { get; } public ICommand FixarBaseCommand { get; } public ICommand AplicarOffsetCommand { get; } public ICommand UsarGnssMovelCommand { get; } public ICommand ContinuarCommand { get; } public ICommand VoltarCommand { get; } public PreparacaoMapaBottomViewModel() { CarregarMapaCommand = new RelayCommand(_ => ExecutarCarregarMapa(), _ => PodeCarregarMapa); FixarBaseCommand = new RelayCommand(_ => ExecutarFixarBase(), _ => PodeFixarBase); AplicarOffsetCommand = new RelayCommand(_ => ExecutarAplicarOffset(), _ => PodeEditarOffsetBase); UsarGnssMovelCommand = new RelayCommand(_ => ExecutarUsarGnssMovel(), _ => PodeUsarGnssMovel); ContinuarCommand = new RelayCommand(_ => ContinuarSolicitado?.Invoke(), _ => PodeContinuar); VoltarCommand = new RelayCommand(_ => VoltarSolicitado?.Invoke()); MetodoFixacaoSelecionado = MetodoFixacaoBase.Ntrip; OffsetFrontalBaseTexto = "0"; OffsetLateralBaseTexto = "0"; StatusTexto = "Carregue o mapa da operação e prepare o GNSS."; } private MetodoFixacaoBase _metodoFixacaoSelecionado = MetodoFixacaoBase.Ntrip; public MetodoFixacaoBase MetodoFixacaoSelecionado { get => _metodoFixacaoSelecionado; set { if (_metodoFixacaoSelecionado != value) { _metodoFixacaoSelecionado = value; OnPropertyChanged(nameof(MetodoFixacaoSelecionado)); OnPropertyChanged(nameof(ExibirCamposManuais)); OnPropertyChanged(nameof(ExibirProgresso)); OnPropertyChanged(nameof(PodeEditarCoordenadasManuais)); OnPropertyChanged(nameof(PodeFixarBase)); OnPropertyChanged(nameof(TextoBotaoFixarBase)); if (!FixacaoEmAndamento) { StatusTexto = _metodoFixacaoSelecionado switch { MetodoFixacaoBase.Ntrip => "Método selecionado: NTRIP. A base será fixada via correção RTK pela rede.", MetodoFixacaoBase.SurveyIn => "Método selecionado: Survey-In. A base calculará sua posição média localmente.", MetodoFixacaoBase.Manual => "Método selecionado: Manual. Informe latitude, longitude e altitude conhecidas da base.", _ => "Pronto para fixar a posição da base." }; } } } } private bool _mapaCarregado; public bool PodeContinuar => _mapaCarregado && !FixacaoEmAndamento && !AlteracaoPapelGnssEmAndamento; public bool PodeVoltar => !FixacaoEmAndamento && !AlteracaoPapelGnssEmAndamento; public void DefinirMapaCarregado(bool carregado) { if ( _mapaCarregado == carregado ) { return; } _mapaCarregado = carregado; OnPropertyChanged( nameof(PodeContinuar) ); } private GnssPapelEstacao _papelGnssAtual = GnssPapelEstacao.Indefinido; public GnssPapelEstacao PapelGnssAtual { get => _papelGnssAtual; private set { if ( _papelGnssAtual == value ) { return; } _papelGnssAtual = value; OnPropertyChanged( nameof(PapelGnssAtual) ); OnPropertyChanged( nameof(PapelGnssTexto) ); OnPropertyChanged( nameof(PapelGnssDescricao) ); OnPropertyChanged( nameof(PapelGnssCor) ); OnPropertyChanged( nameof(TextoBotaoModoGnss) ); OnPropertyChanged( nameof(PodeUsarGnssMovel) ); OnPropertyChanged( nameof(TextoBotaoFixarBase) ); } } private bool _alteracaoPapelGnssEmAndamento; public bool AlteracaoPapelGnssEmAndamento { get => _alteracaoPapelGnssEmAndamento; private set { if ( _alteracaoPapelGnssEmAndamento == value ) { return; } _alteracaoPapelGnssEmAndamento = value; OnPropertyChanged( nameof( AlteracaoPapelGnssEmAndamento ) ); OnPropertyChanged( nameof(PapelGnssTexto) ); OnPropertyChanged( nameof(PapelGnssDescricao) ); OnPropertyChanged( nameof(PapelGnssCor) ); OnPropertyChanged( nameof(PodeUsarGnssMovel) ); OnPropertyChanged( nameof(PodeCarregarMapa) ); OnPropertyChanged( nameof(PodeEditarMetodoFixacao) ); OnPropertyChanged( nameof(PodeEditarCoordenadasManuais) ); OnPropertyChanged( nameof(PodeEditarOffsetBase) ); OnPropertyChanged( nameof(PodeFixarBase) ); OnPropertyChanged( nameof(PodeContinuar) ); OnPropertyChanged( nameof(PodeVoltar) ); } } public string PapelGnssTexto { get { if (AlteracaoPapelGnssEmAndamento) return "CONFIGURANDO..."; if (FixacaoEmAndamento) return "FIXANDO BASE..."; return PapelGnssAtual switch { GnssPapelEstacao.Movel => "LEVANTAMENTO MÓVEL", GnssPapelEstacao.BaseFixa => "BASE FIXA", _ => "NÃO DEFINIDO" }; } } public string PapelGnssDescricao { get { if (AlteracaoPapelGnssEmAndamento) { return "Aguarde enquanto o modo do receptor GNSS é alterado."; } if (FixacaoEmAndamento) { return "A posição da estação está sendo determinada."; } return PapelGnssAtual switch { GnssPapelEstacao.Movel => "A antena pode ser movimentada e usada para levantamento e edição do mapa.", GnssPapelEstacao.BaseFixa => "A estação está fixa e pronta para fornecer referência à operação.", _ => "Escolha o modo móvel para levantamento ou fixe a estação como base." }; } } public Brush PapelGnssCor => AlteracaoPapelGnssEmAndamento || FixacaoEmAndamento ? Brushes.Gold : PapelGnssAtual switch { GnssPapelEstacao.Movel => Brushes.DeepSkyBlue, GnssPapelEstacao.BaseFixa => Brushes.LimeGreen, _ => Brushes.Gray }; public string TextoBotaoModoGnss => PapelGnssAtual switch { GnssPapelEstacao.BaseFixa => "Liberar para levantamento", GnssPapelEstacao.Movel => "Levantamento ativo", _ => "Usar para levantamento" }; public bool PodeUsarGnssMovel => !FixacaoEmAndamento && !AlteracaoPapelGnssEmAndamento && PapelGnssAtual != GnssPapelEstacao.Movel; private bool _fixacaoEmAndamento; public bool FixacaoEmAndamento { get => _fixacaoEmAndamento; set { if (_fixacaoEmAndamento != value) { _fixacaoEmAndamento = value; OnPropertyChanged(nameof(FixacaoEmAndamento)); OnPropertyChanged(nameof(PodeCarregarMapa)); OnPropertyChanged(nameof(PodeEditarMetodoFixacao)); OnPropertyChanged(nameof(PodeEditarCoordenadasManuais)); OnPropertyChanged(nameof(PodeEditarOffsetBase)); OnPropertyChanged(nameof(PodeFixarBase)); OnPropertyChanged(nameof(TextoBotaoFixarBase)); OnPropertyChanged( nameof(PapelGnssTexto) ); OnPropertyChanged( nameof(PapelGnssDescricao) ); OnPropertyChanged( nameof(PapelGnssCor) ); OnPropertyChanged( nameof(PodeUsarGnssMovel) ); OnPropertyChanged( nameof(PodeContinuar) ); OnPropertyChanged( nameof(PodeVoltar) ); } } } public bool PodeCarregarMapa => !FixacaoEmAndamento && !AlteracaoPapelGnssEmAndamento; public bool PodeEditarMetodoFixacao => !FixacaoEmAndamento && !AlteracaoPapelGnssEmAndamento; public bool PodeEditarCoordenadasManuais => !FixacaoEmAndamento && !AlteracaoPapelGnssEmAndamento && MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual; public bool PodeEditarOffsetBase => !FixacaoEmAndamento && !AlteracaoPapelGnssEmAndamento; public bool ExibirCamposManuais => MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual; public bool ExibirProgresso => MetodoFixacaoSelecionado != MetodoFixacaoBase.Manual; private bool _exibirOffsets; public bool ExibirOffsets { get { return _exibirOffsets; } set { _exibirOffsets = value; OnPropertyChanged(nameof(ExibirOffsets)); } } public bool PodeFixarBase { get { if (AlteracaoPapelGnssEmAndamento) return false; if (FixacaoEmAndamento) return true; // botão vira "Parar" if (MetodoFixacaoSelecionado != MetodoFixacaoBase.Manual) return true; return LatitudeManual.HasValue && LongitudeManual.HasValue && AltitudeManual.HasValue; } } public string TextoBotaoFixarBase { get { if (FixacaoEmAndamento) return "Parar"; if ( MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual ) { return PapelGnssAtual == GnssPapelEstacao.BaseFixa ? "Reposicionar base" : "Aplicar posição da base"; } return PapelGnssAtual == GnssPapelEstacao.BaseFixa ? "Reposicionar base" : "Fixar como base"; } } private double? _latitudeManual; public double? LatitudeManual { get => _latitudeManual; private set { if (_latitudeManual != value) { _latitudeManual = value; OnPropertyChanged(nameof(LatitudeManual)); OnPropertyChanged(nameof(PodeFixarBase)); } } } private double? _longitudeManual; public double? LongitudeManual { get => _longitudeManual; private set { if (_longitudeManual != value) { _longitudeManual = value; OnPropertyChanged(nameof(LongitudeManual)); OnPropertyChanged(nameof(PodeFixarBase)); } } } private double? _altitudeManual; public double? AltitudeManual { get => _altitudeManual; private set { if (_altitudeManual != value) { _altitudeManual = value; OnPropertyChanged(nameof(AltitudeManual)); OnPropertyChanged(nameof(PodeFixarBase)); } } } private string _latitudeManualTexto = string.Empty; public string LatitudeManualTexto { get => _latitudeManualTexto; set { if (_latitudeManualTexto != value) { _latitudeManualTexto = value; LatitudeManual = TryParseDouble(value); OnPropertyChanged(nameof(LatitudeManualTexto)); OnPropertyChanged(nameof(PodeFixarBase)); } } } private string _longitudeManualTexto = string.Empty; public string LongitudeManualTexto { get => _longitudeManualTexto; set { if (_longitudeManualTexto != value) { _longitudeManualTexto = value; LongitudeManual = TryParseDouble(value); OnPropertyChanged(nameof(LongitudeManualTexto)); OnPropertyChanged(nameof(PodeFixarBase)); } } } private string _altitudeManualTexto = string.Empty; public string AltitudeManualTexto { get => _altitudeManualTexto; set { if (_altitudeManualTexto != value) { _altitudeManualTexto = value; AltitudeManual = TryParseDouble(value); OnPropertyChanged(nameof(AltitudeManualTexto)); OnPropertyChanged(nameof(PodeFixarBase)); } } } private double? _offsetFrontalBaseCm = 0; public double? OffsetFrontalBaseCm { get => _offsetFrontalBaseCm; private set { if (_offsetFrontalBaseCm != value) { _offsetFrontalBaseCm = value; OnPropertyChanged(nameof(OffsetFrontalBaseCm)); } } } private double? _offsetLateralBaseCm = 0; public double? OffsetLateralBaseCm { get => _offsetLateralBaseCm; private set { if (_offsetLateralBaseCm != value) { _offsetLateralBaseCm = value; OnPropertyChanged(nameof(OffsetLateralBaseCm)); } } } private string _offsetFrontalBaseTexto = "0"; public string OffsetFrontalBaseTexto { get => _offsetFrontalBaseTexto; set { if (_offsetFrontalBaseTexto != value) { _offsetFrontalBaseTexto = value; OffsetFrontalBaseCm = TryParseDouble(value); OnPropertyChanged(nameof(OffsetFrontalBaseTexto)); } } } private string _offsetLateralBaseTexto = "0"; public string OffsetLateralBaseTexto { get => _offsetLateralBaseTexto; set { if (_offsetLateralBaseTexto != value) { _offsetLateralBaseTexto = value; OffsetLateralBaseCm = TryParseDouble(value); OnPropertyChanged(nameof(OffsetLateralBaseTexto)); } } } private double _progressoFixacao; public double ProgressoFixacao { get => _progressoFixacao; set { if (Math.Abs(_progressoFixacao - value) > 0.001) { _progressoFixacao = value; OnPropertyChanged(nameof(ProgressoFixacao)); OnPropertyChanged(nameof(ProgressoFixacaoTexto)); } } } public string ProgressoFixacaoTexto => $"{ProgressoFixacao:F0}%"; private string _statusTexto = string.Empty; public string StatusTexto { get => _statusTexto; set { if (_statusTexto != value) { _statusTexto = value; OnPropertyChanged(nameof(StatusTexto)); } } } private void ExecutarCarregarMapa() { var dlgTipo = new SelecaoTipoMapa { Owner = Variaveis.Dock }; if (dlgTipo.ShowDialog() != true || dlgTipo.Resultado == null) return; var tipoMapa = dlgTipo.Resultado.Value; var dlg = new Microsoft.Win32.OpenFileDialog { Filter = "Arquivos de mapa|*.geojson;*.json;*.shp", Title = "Selecione o arquivo de mapa" }; if (dlg.ShowDialog() == true) { StatusTexto = $"Mapa selecionado: {System.IO.Path.GetFileName(dlg.FileName)} ({tipoMapa})"; CarregarMapaSolicitado?.Invoke(dlg.FileName, tipoMapa); } } private void ExecutarFixarBase() { if (FixacaoEmAndamento) { FixarBaseSolicitado?.Invoke(MetodoFixacaoSelecionado, LatitudeManual, LongitudeManual, AltitudeManual); return; } if (MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual) { if (!LatitudeManual.HasValue || !LongitudeManual.HasValue || !AltitudeManual.HasValue) { System.Windows.MessageBox.Show( "Preencha latitude, longitude e altitude para aplicar a posição manual da base.", "Dados incompletos", MessageBoxButton.OK, MessageBoxImage.Warning); return; } StatusTexto = "Pronto para aplicar a posição manual da base."; } FixarBaseSolicitado?.Invoke(MetodoFixacaoSelecionado, LatitudeManual, LongitudeManual, AltitudeManual); } private void ExecutarAplicarOffset() { AplicarOffsetSolicitado?.Invoke(OffsetFrontalBaseCm, OffsetLateralBaseCm); } public void IniciarFixacao() { FixacaoEmAndamento = true; ProgressoFixacao = 0; StatusTexto = MetodoFixacaoSelecionado switch { MetodoFixacaoBase.Ntrip => "Iniciando fixação da base via NTRIP...", MetodoFixacaoBase.SurveyIn => "Iniciando Survey-In da base...", MetodoFixacaoBase.Manual => "Aplicando posição manual da base...", _ => "Iniciando fixação da posição da base..." }; } public void AtualizarProgresso(double progresso, string status) { ProgressoFixacao = progresso; StatusTexto = status; } public void FinalizarFixacao(bool sucesso, string? mensagem = null) { ExibirOffsets = sucesso; FixacaoEmAndamento = false; if (sucesso) ProgressoFixacao = 100; StatusTexto = !string.IsNullOrWhiteSpace(mensagem) ? mensagem : sucesso ? "Fixação da base concluída com sucesso." : "Fixação da base encerrada."; } public void CancelarFixacao(string? mensagem = null) { FixacaoEmAndamento = false; StatusTexto = mensagem ?? "Fixação da base cancelada."; } public void LimparCamposManuais() { LatitudeManualTexto = string.Empty; LongitudeManualTexto = string.Empty; AltitudeManualTexto = string.Empty; LatitudeManual = null; LongitudeManual = null; AltitudeManual = null; } private void ExecutarUsarGnssMovel() { if (!PodeUsarGnssMovel) return; UsarGnssMovelSolicitado?.Invoke(); } public void IniciarAlteracaoPapelGnss() { AlteracaoPapelGnssEmAndamento = true; StatusTexto = "Configurando o GNSS para levantamento..."; } public void FinalizarAlteracaoPapelGnss(bool sucesso, GnssPapelEstacao papel, string mensagem) { PapelGnssAtual = papel; AlteracaoPapelGnssEmAndamento = false; if ( papel != GnssPapelEstacao.BaseFixa ) { ExibirOffsets = false; } StatusTexto = mensagem; } public void AtualizarPapelGnss(GnssPapelEstacao papel) { PapelGnssAtual = papel; if ( papel != GnssPapelEstacao.BaseFixa ) { ExibirOffsets = false; } } private double? TryParseDouble(string? texto) { if (string.IsNullOrWhiteSpace(texto)) return null; texto = texto.Trim().Replace(",", "."); if (double.TryParse(texto, NumberStyles.Any, CultureInfo.InvariantCulture, out var valor)) return valor; return null; } private void OnPropertyChanged(string nome) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nome)); CommandManager.InvalidateRequerySuggested(); } } }