using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia.Controls;
using PolyTrader.Core.Modularity;
namespace PolyTrader.App.Avalonia.Shell
{
///
/// Avalonia-Umsetzung von .
///
/// Umstellung auf die Einfenster-Shell: Früher öffnete jede View ein eigenes
/// Fenster. Jetzt gibt es genau ein Anwendungsfenster (); eine
/// View ist eine -Seite, die in dessen Inhaltsbereich gehängt wird.
/// Eine Seite wird beim ersten Aufruf erzeugt und bleibt danach für die Sitzung bestehen –
/// das entspricht dem alten „Fenster bleibt offen": Timer, Log-Abos und der Bildlaufstand
/// überleben den Seitenwechsel.
///
/// Der Core-Contract ist toolkit-neutral ( liefert
/// ) – hier wird auf gecastet. Ein falscher Typ ist ein
/// Programmierfehler und soll laut scheitern, nicht still eine leere Seite erzeugen.
///
public sealed class AvaloniaUiHost : IModuleUiHost
{
/// ID der Startseite (frühere LauncherForm/LauncherWindow).
public const string StartViewId = "core.start";
private readonly List _views = new();
private readonly List _unavailable = new();
private readonly Dictionary _pages = new();
private Views.ShellWindow? _shell;
private string? _activeViewId;
private bool _shutdownDialogOpen;
/// True, sobald das Herunterfahren über die Sicherheitsabfrage bestätigt wurde.
public bool ShutdownConfirmed { get; private set; }
public event Action? OpenStateChanged;
public IReadOnlyList Views => _views;
/// ID der gerade angezeigten Seite – die Seitenleiste hebt sie hervor.
public string? ActiveViewId => _activeViewId;
public void RegisterView(ModuleView view) => _views.Add(view);
///
/// Ein bekanntes, in dieser Sitzung aber nicht geladenes Modul. Solche Module haben keine
/// Seite – die Seitenleiste zeigt sie trotzdem, ausgegraut und mit dem Grund als Hinweis.
///
/// Warum das Modul fehlt (Lizenz, Abschaltung, fehlender API-Key …).
public sealed record UnavailableView(string Title, string? IconKey, int Order, string Reason);
///
/// Meldet ein nicht geladenes Modul an. Ohne das verschwände es spurlos aus der Oberfläche –
/// in der Mehrfenster-Fassung fiel das kaum auf, in einer Seitenleiste ist eine unerklärt
/// leere Rubrik dagegen schlicht ein Fehler.
///
public void RegisterUnavailable(UnavailableView view) => _unavailable.Add(view);
/// Bekannte, aber nicht geladene Module (siehe ).
public IReadOnlyList UnavailableViews => _unavailable;
/// Setzt das Shell-Fenster – Ziel aller Seitenwechsel und Besitzer der Dialoge.
public void SetShell(Views.ShellWindow shell) => _shell = shell;
/// Das Shell-Fenster, oder null vor dessen Aufbau (z.B. im Smoke-Lauf).
public Window? ShellWindow => _shell;
///
/// Wurde die Seite in dieser Sitzung schon einmal aufgerufen? Erbt die Bedeutung des früheren
/// „Fenster ist offen": die Seite existiert und arbeitet weiter, auch wenn gerade eine andere
/// angezeigt wird.
///
public bool IsOpen(string viewId) => _pages.ContainsKey(viewId);
/// Zurück auf die Startseite.
public void ActivateMain() => OpenView(StartViewId);
public void OpenView(string viewId)
{
var view = _views.FirstOrDefault(v => v.Id == viewId);
if (view != null) OpenView(view);
}
public void OpenView(ModuleView view)
{
if (!_pages.TryGetValue(view.Id, out var page))
{
page = (Control)view.CreateView();
_pages[view.Id] = page;
}
_activeViewId = view.Id;
_shell?.ShowPage(view.Title, page);
OpenStateChanged?.Invoke();
}
///
/// Zeigt die Sicherheitsabfrage (Beenden-Schaltfläche 10 s gesperrt) und fährt bei Bestätigung
/// herunter. Aus jeder Seite aufrufbar – auch aus Modul-Seiten, die die App nicht kennen.
///
public async void RequestShutdown()
{
if (ShutdownConfirmed || _shutdownDialogOpen) return;
_shutdownDialogOpen = true;
try
{
var dlg = new Views.ShutdownConfirmWindow();
bool confirmed = _shell != null
? await dlg.ShowDialog(_shell)
: await dlg.ShowDialog(new Window());
if (!confirmed) return;
ShutdownConfirmed = true;
if (global::Avalonia.Application.Current?.ApplicationLifetime
is global::Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.Shutdown();
}
}
finally
{
_shutdownDialogOpen = false;
}
}
}
}