using OperationControl.Models; using System.Collections.ObjectModel; using System.ComponentModel; using System.Windows.Threading; using static AgroBase.Models.Enums; namespace OperationControl.ViewModels.Views.Operacao { public class OperacaoBottomViewModel : INotifyPropertyChanged { public ObservableCollection AlertasAtivos { get; } = new(); private AlertaModel _toastAlerta; public AlertaModel ToastAlerta { get => _toastAlerta; set { if (_toastAlerta == value) return; _toastAlerta = value; OnPropertyChanged(nameof(ToastAlerta)); } } private readonly DispatcherTimer _toastTimer; public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); // EVENTO PARA O PAI TRATAR A NAVEGAÇÃO public event Action SolicitarAbrirDiagnostico; public OperacaoBottomViewModel() { _toastTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(6) }; _toastTimer.Tick += (s, e) => { _toastTimer.Stop(); ToastAlerta = null; }; } public void SelecionarAlerta(AlertaModel alerta) { if (alerta == null) return; SolicitarAbrirDiagnostico?.Invoke(alerta); } public void LimparToast() { _toastTimer.Stop(); ToastAlerta = null; } public void MostrarToast(AlertaModel alerta) { ToastAlerta = alerta; _toastTimer.Stop(); _toastTimer.Start(); } public void AdicionarAlerta(string roverId, AgroBase.Models.Enums.T_Code modulo, SeveridadeAlerta severidade, string mensagem, string? modId = null) { App.Current.Dispatcher.BeginInvoke(new Action(() => { var existente = AlertasAtivos.FirstOrDefault(x => x.Rover_ID == roverId && x.Modulo == modulo && x.Mod_ID == modId); if (existente == null) { var alerta = new AlertaModel { Rover_ID = roverId, Modulo = modulo, Mod_ID = modId, Severidade = severidade, Mensagem = mensagem, CriadoEm = DateTime.Now }; AlertasAtivos.Add(alerta); MostrarToast(alerta); } else { existente.Mensagem = mensagem; existente.Severidade = severidade; } })); } public void RemoverAlerta(string roverId, AgroBase.Models.Enums.T_Code modulo, SeveridadeAlerta? severidade = null, string? modId = null) { App.Current.Dispatcher.BeginInvoke(new Action(() => { var alerta = AlertasAtivos.FirstOrDefault(x => x.Rover_ID == roverId && x.Modulo == modulo && x.Mod_ID == modId && (severidade != null ? x.Severidade == severidade : true)); if (alerta != null) AlertasAtivos.Remove(alerta); })); } public void ClicarNoAlerta(AlertaModel alerta) { if (alerta == null) return; SelecionarAlerta(alerta); } public void ClicarNoToast() { var alerta = ToastAlerta; if (alerta == null) return; LimparToast(); SelecionarAlerta(alerta); } SeveridadeAlerta DeParaStatus(StatusModulo status, bool mandatorio) { switch (status) { case StatusModulo.Operante: return SeveridadeAlerta.Info; case StatusModulo.Alerta: return SeveridadeAlerta.Warning; case StatusModulo.Falha: return mandatorio ? SeveridadeAlerta.Critical : SeveridadeAlerta.Error; case StatusModulo.Conectado: return mandatorio ? SeveridadeAlerta.Warning : SeveridadeAlerta.Info; case StatusModulo.Desconectado: return mandatorio ? SeveridadeAlerta.Critical : SeveridadeAlerta.Error; default: return SeveridadeAlerta.Info; } } public void AtualizarListaAlertasRoverSelecionado(string rover_id) { var rover = VariaveisControleOperacao.RoversNaRede.FirstOrDefault(x => x.RoverId == rover_id); if (rover == null) return; var dados_leitura = rover?.DadosLeitura; if (dados_leitura?.ModulosSaude == null) return; foreach (var mod in dados_leitura.ModulosSaude) { if (mod.saude_individual.Any()) { foreach (var ind in mod.saude_individual) { if (ind.status != StatusModulo.Operante) { AdicionarAlerta(rover.RoverId, mod.modulo, DeParaStatus(ind.status, ind.em_uso), string.Join(", ", ind.motivos), modId: ind.label); } else { RemoverAlerta(rover.RoverId, mod.modulo, modId: ind.label); } } } else { if (mod.status != StatusModulo.Operante) { AdicionarAlerta(rover.RoverId, mod.modulo, DeParaStatus(mod.status, rover.ModulosMandatorios?.Any(x => x.Dispositivo == mod.modulo && x.Mandatorio) ?? false), string.Join(", ", mod.motivos)); } else { RemoverAlerta(rover.RoverId, mod.modulo); } } } } public void AtualizarListaAlertasTodosRovers() { App.Current.Dispatcher.BeginInvoke(new Action(() => { string GerarChave(string roverId, T_Code modulo, string? modId) => $"{roverId}|{modulo}|{modId ?? ""}"; var agora = DateTime.Now; // 1) Gera os alertas que DEVERIAM existir neste momento var alertasEsperados = new List(); foreach (var rover in VariaveisControleOperacao.RoversNaRede) { var dadosLeitura = rover?.DadosLeitura; if (dadosLeitura?.ModulosSaude == null) continue; foreach (var mod in dadosLeitura.ModulosSaude) { if (mod.saude_individual != null && mod.saude_individual.Any()) { foreach (var ind in mod.saude_individual) { if (ind.status == StatusModulo.Operante) continue; alertasEsperados.Add(new AlertaModel { Rover_ID = rover.RoverId, Modulo = mod.modulo, Mod_ID = ind.label, Severidade = DeParaStatus(ind.status, ind.em_uso), Mensagem = string.Join(", ", ind.motivos ?? new List()) // NÃO define Timestamp aqui ainda }); } } else { if (mod.status == StatusModulo.Operante) continue; bool mandatorio = rover.ModulosMandatorios?.Any(x => x.Dispositivo == mod.modulo && x.Mandatorio) ?? false; alertasEsperados.Add(new AlertaModel { Rover_ID = rover.RoverId, Modulo = mod.modulo, Mod_ID = null, Severidade = DeParaStatus(mod.status, mandatorio), Mensagem = string.Join(", ", mod.motivos ?? new List()) // NÃO define Timestamp aqui ainda }); } } } var mapaEsperado = alertasEsperados.ToDictionary( x => GerarChave(x.Rover_ID, x.Modulo, x.Mod_ID), x => x); var mapaAtual = AlertasAtivos.ToDictionary( x => GerarChave(x.Rover_ID, x.Modulo, x.Mod_ID), x => x); // 2) Remove os alertas que não existem mais var chavesParaRemover = mapaAtual.Keys .Where(chave => !mapaEsperado.ContainsKey(chave)) .ToList(); foreach (var chave in chavesParaRemover) { var alertaRemover = mapaAtual[chave]; AlertasAtivos.Remove(alertaRemover); if (ToastAlerta == alertaRemover) LimparToast(); } // 3) Adiciona novos ou atualiza os existentes foreach (var kv in mapaEsperado) { var chave = kv.Key; var esperado = kv.Value; if (!mapaAtual.TryGetValue(chave, out var existente)) { // Novo alerta esperado.CriadoEm = agora; AlertasAtivos.Add(esperado); MostrarToast(esperado); } else { // Alerta já existia -> mantém Timestamp original bool mudou = existente.Mensagem != esperado.Mensagem || existente.Severidade != esperado.Severidade; if (mudou) { existente.Mensagem = esperado.Mensagem; existente.Severidade = esperado.Severidade; // Se quiser que Timestamp represente "última mudança", mantém isso: existente.AtualizadoEm = agora; MostrarToast(existente); } } } var ordenado = AlertasAtivos.OrderByDescending(x => x.AtualizadoEm ?? x.CriadoEm).ToList(); AlertasAtivos.Clear(); foreach (var a in ordenado) { AlertasAtivos.Add(a); } })); } } }