using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Layout;
using Avalonia.Media;

// Avalonia's Button, not Android.Widget's. .NET for Android puts Android.Widget in this project's
// implicit usings, so the bare name is ambiguous — the same collision the namespace itself causes
// for Android.App. See the note at the top of MainActivity.
using Application = Avalonia.Application;
using Button = Avalonia.Controls.Button;

namespace DodoSSH.Client.Android.Views;

/// <summary>
/// One destination in the bottom bar.
/// </summary>
/// <remarks>
/// <para>
/// Written in C# rather than as a XAML control because it is a button with a label and a rule about the
/// accent bar, and a templated control for that would be more machinery than the thing it draws.
/// </para>
/// <para>
/// <b>The accent bar is on top, not underneath.</b> The design puts it there in the nav rail and it is
/// worth keeping on a phone for a reason the desktop does not have: the bottom of a phone screen is under
/// the system's own gesture bar, and an indicator drawn there is one the user cannot see.
/// </para>
/// </remarks>
internal sealed class NavButton : Button
{
    public static readonly StyledProperty<string> LabelProperty =
        AvaloniaProperty.Register<NavButton, string>(nameof(Label), string.Empty);

    public static readonly StyledProperty<bool> IsCurrentProperty =
        AvaloniaProperty.Register<NavButton, bool>(nameof(IsCurrent));

    private readonly Border indicator;
    private readonly TextBlock text;

    public NavButton()
    {
        Background = Brushes.Transparent;
        BorderThickness = new Thickness(0);
        CornerRadius = new CornerRadius(0);
        Padding = new Thickness(0);
        HorizontalAlignment = HorizontalAlignment.Stretch;
        VerticalAlignment = VerticalAlignment.Stretch;
        HorizontalContentAlignment = HorizontalAlignment.Stretch;
        VerticalContentAlignment = VerticalAlignment.Stretch;

        indicator = new Border
        {
            Height = 2,
            VerticalAlignment = VerticalAlignment.Top,
            Background = Brushes.Transparent,
        };

        text = new TextBlock
        {
            FontSize = 9,
            FontWeight = FontWeight.SemiBold,
            HorizontalAlignment = HorizontalAlignment.Center,
            VerticalAlignment = VerticalAlignment.Center,
            Foreground = new SolidColorBrush(Color.Parse("#566059")),
        };

        Content = new Panel { Children = { indicator, text } };
    }

    public string Label
    {
        get => GetValue(LabelProperty);
        set => SetValue(LabelProperty, value);
    }

    /// <summary>Whether this is the destination currently showing.</summary>
    public bool IsCurrent
    {
        get => GetValue(IsCurrentProperty);
        set => SetValue(IsCurrentProperty, value);
    }

    /// <inheritdoc />
    protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
    {
        base.OnPropertyChanged(change);

        if (change.Property == LabelProperty)
        {
            text.Text = Label;
        }
        else if (change.Property == IsCurrentProperty)
        {
            // Both the label and the bar, not just the bar. Colour alone at 9pt on a dark background is a
            // weak signal, and it is the only one a user with a colour deficiency would have.
            text.Foreground = new SolidColorBrush(Color.Parse(IsCurrent ? "#3CE88F" : "#566059"));
            indicator.Background = IsCurrent
                ? new SolidColorBrush(Color.Parse("#3CE88F"))
                : Brushes.Transparent;
        }
        else if (change.Property == FontFamilyProperty)
        {
            text.FontFamily = FontFamily;
        }
    }

    /// <inheritdoc />
    protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
    {
        base.OnApplyTemplate(e);

        // Resolved here rather than in the constructor: application resources are not reachable while the
        // control is still being constructed, and a hard-coded stack would drift from Palette.axaml.
        if (Application.Current?.FindResource("MonoFont") is FontFamily mono)
        {
            text.FontFamily = mono;
        }
    }
}
