using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using DodoSSH.Client.App.Platform;

namespace DodoSSH.Client.App.Views;

/// <summary>
/// The window's own titlebar, drawn because the design draws one.
/// </summary>
/// <remarks>
/// <para>
/// Everything here is a window operation, which is why it is code-behind and not a command on a view model:
/// dragging, maximising and closing are properties of the <see cref="Window"/> this control happens to be
/// inside, and a view model that knew about them would be a view model that could not be tested without one.
/// </para>
/// <para>
/// The window is found by walking up rather than injected, so this control drops into any window — including
/// the bare one the layout harness hosts it in, where <see cref="Host"/> is simply a different window and
/// every handler still has something to act on.
/// </para>
/// </remarks>
internal sealed partial class TitleBar : UserControl
{
    public TitleBar()
    {
        InitializeComponent();

        // ◆ A nightly says which one it is, in the one place a person is always looking at.
        //
        // The two channels install side by side on purpose, so both windows are on screen at once, both
        // are called DodoSSH, and both ask for a passphrase the same way. Everything else that
        // distinguishes them — the Start menu entry, the install directory, the version on the
        // preferences screen — is somewhere nobody is looking while typing into one of them.
        //
        // Set here rather than in the markup so the release build is exactly what the XAML says, and so
        // the layout harness, which hosts this control directly, measures the shipping string.
        if (DesktopChannel.IsNightly)
        {
            ProductName.Text = "DodoSSH Nightly";
        }
    }

    private Window? Host => TopLevel.GetTopLevel(this) as Window;

    /// <remarks>
    /// Left button only, and only on a press that has not already been handled by something inside the bar —
    /// otherwise dragging would start from the close button and swallow the click that was meant to close
    /// the window.
    /// </remarks>
    private void OnDrag(object? sender, PointerPressedEventArgs e)
    {
        if (e.Handled || !e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
        {
            return;
        }

        Host?.BeginMoveDrag(e);
    }

    private void OnMinimise(object? sender, RoutedEventArgs e)
    {
        if (Host is { } window)
        {
            window.WindowState = WindowState.Minimized;
        }
    }

    /// <remarks>
    /// Both the button and a double-click on the bar arrive here, which is the convention Windows sets and
    /// the one people reach for without thinking about it.
    /// </remarks>
    private void OnToggleMaximised(object? sender, RoutedEventArgs e)
    {
        if (Host is not { } window)
        {
            return;
        }

        window.WindowState = window.WindowState == WindowState.Maximized
            ? WindowState.Normal
            : WindowState.Maximized;
    }

    private void OnClose(object? sender, RoutedEventArgs e) => Host?.Close();
}
