@using DeepDrftPublic.Client.Controls
@using DeepDrftPublic.Client.Controls.AudioPlayerBar
@using DeepDrftPublic.Client.Services
@using DeepDrftPublic.Client.Common
@using DeepDrftShared.Client.Common
@using Microsoft.AspNetCore.Components
@inherits LayoutComponentBase
@implements IDisposable
@implements IAsyncDisposable

<MudThemeProvider Theme="@DeepDrftPalettes.Default" IsDarkMode="_isDarkMode" />
<MudPopoverProvider />
<MudDialogProvider />
<MudSnackbarProvider />
<div class="@ThemeWrapperClass">
    <MudLayout Style="display: flex; flex-direction: column; min-height: 100vh">
        <AudioPlayerProvider>
            <DeepDrftMenu Elevation="4" @bind-IsDarkMode="_isDarkMode" />
            <MudMainContent Class="flex-grow-1 pb-8 dd-main-content">
                <MudContainer MaxWidth="MaxWidth.False" Class="pa-4">
                    @Body
                </MudContainer>
            </MudMainContent>
            <DeepDrftFooter />
            <AudioPlayerBar OnMinimized="ToggleAudioPlayerMinimized" />
            
            @* Spacer to prevent content overlap. Height tracks the fixed player
               dock's live size via the --player-height var the player publishes
               (see AudioPlayerBar / Interop/layout/spacer.ts). *@
            <div class="player-spacer @_audioPlayerClass"></div>
        </AudioPlayerProvider>
    </MudLayout>
</div>


<div id="blazor-error-ui" data-nosnippet>
    An unhandled error has occurred.
    <a href="." class="reload">Reload</a>
    <span class="dismiss">🗙</span>
</div>

@code {
    private string _audioPlayerClass = "minimized";
    private const string DarkModeKey = "darkMode";
    private bool _isDarkMode = false;
    private bool? _lastAppliedDarkMode = null;
    private PersistingComponentStateSubscription _persistingSubscription;
    private IJSObjectReference? _themeModule;

    [Inject] public required PersistentComponentState PersistentState { get; set; }
    [Inject] public required DarkModeSettings DarkModeSettings { get; set; }
    [Inject] public required IJSRuntime JS { get; set; }

    protected override void OnInitialized()
    {
        base.OnInitialized();

        // Restore persisted dark mode state (from server prerender)
        if (PersistentState.TryTakeFromJson<bool>(DarkModeKey, out var restored))
        {
            _isDarkMode = restored;
            DarkModeSettings.IsDarkMode = restored;
        }
        else
        {
            _isDarkMode = DarkModeSettings.IsDarkMode;
        }

        // Register to persist state when prerendering completes
        _persistingSubscription = PersistentState.RegisterOnPersisting(PersistDarkMode);
    }

    // Sync dark mode class on <body> so portaled MudBlazor elements (popovers, menus, selects)
    // inherit --deepdrft-popover-surface from body.deepdrft-theme-dark rather than from :root only.
    // Popovers portal outside the ThemeWrapperClass div, so only a body-level class can reach them.
    // Gated: only fires on first render or when _isDarkMode actually changes, to avoid redundant
    // JS calls on unrelated re-renders (e.g. audio player minimize/expand).
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);

        if (firstRender || _isDarkMode != _lastAppliedDarkMode)
        {
            _lastAppliedDarkMode = _isDarkMode;
            _themeModule ??= await JS.InvokeAsync<IJSObjectReference>(
                "import", "./_content/DeepDrftShared.Client/js/theme/theme.js");
            await _themeModule.InvokeVoidAsync("setBodyThemeClass", _isDarkMode);
        }
    }

    // Theme wrapper class for CSS targeting
    private string ThemeWrapperClass => _isDarkMode ? "deepdrft-theme-dark" : "deepdrft-theme-light";

    private Task PersistDarkMode()
    {
        PersistentState.PersistAsJson(DarkModeKey, _isDarkMode);
        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _persistingSubscription.Dispose();
    }

    public async ValueTask DisposeAsync()
    {
        if (_themeModule != null)
        {
            try { await _themeModule.DisposeAsync(); }
            catch (JSDisconnectedException) { /* circuit torn down */ }
        }
    }

    private void ToggleAudioPlayerMinimized(bool isMinimized)
    {
        _audioPlayerClass = isMinimized ? "minimized" : "expanded";
    }

}


