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; 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 List MetodosFixacaoDisponiveis { get; } = new() { new MetodoFixacaoItem { Valor = MetodoFixacaoBase.Ntrip, Nome = "Utilizando NTRIP" }, new MetodoFixacaoItem { Valor = MetodoFixacaoBase.SurveyIn, Nome = "Modo Survey-In" }, new MetodoFixacaoItem { Valor = MetodoFixacaoBase.Manual, Nome = "Preenchimento manual" } }; public ICommand CarregarMapaCommand { get; } public ICommand FixarBaseCommand { get; } public ICommand AplicarOffsetCommand { get; } public PreparacaoMapaBottomViewModel() { CarregarMapaCommand = new RelayCommand(_ => ExecutarCarregarMapa(), _ => PodeCarregarMapa); FixarBaseCommand = new RelayCommand(_ => ExecutarFixarBase(), _ => PodeFixarBase); AplicarOffsetCommand = new RelayCommand(_ => ExecutarAplicarOffset(), _ => PodeEditarOffsetBase); MetodoFixacaoSelecionado = MetodoFixacaoBase.Ntrip; OffsetFrontalBaseTexto = "0"; OffsetLateralBaseTexto = "0"; StatusTexto = "Pronto para carregar o mapa e fixar a base."; } 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 _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)); } } } public bool PodeCarregarMapa => !FixacaoEmAndamento; public bool PodeEditarMetodoFixacao => !FixacaoEmAndamento; public bool PodeEditarCoordenadasManuais => !FixacaoEmAndamento && MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual; public bool PodeEditarOffsetBase => !FixacaoEmAndamento; 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 (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"; return MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual ? "Aplicar posição manual" : "Fixar posição da 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 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(); } } }