using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Windows.Foundation;

namespace Sonex.Client.Controls;

public sealed partial class ToolBarNumberField : UserControl
{
    public static readonly DependencyProperty LabelProperty = DependencyProperty.Register(
        nameof(Label),
        typeof(string),
        typeof(ToolBarNumberField),
        new PropertyMetadata(string.Empty, OnLabelChanged));

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
        nameof(Value),
        typeof(double),
        typeof(ToolBarNumberField),
        new PropertyMetadata(0d, OnValueChanged));

    public static readonly DependencyProperty SmallChangeProperty = DependencyProperty.Register(
        nameof(SmallChange),
        typeof(double),
        typeof(ToolBarNumberField),
        new PropertyMetadata(1d, OnSmallChangeChanged));

    private bool _isUpdatingFromNumberBox;

    public ToolBarNumberField()
    {
        InitializeComponent();
        _LabelTextBlock.Text = Label;
        _NumberBox.SmallChange = SmallChange;
        _NumberBox.Value = Value;
    }

    public event TypedEventHandler<NumberBox, NumberBoxValueChangedEventArgs>? ValueChanged;

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

    public double Value
    {
        get => (double)GetValue(ValueProperty);
        set => SetValue(ValueProperty, value);
    }

    public double SmallChange
    {
        get => (double)GetValue(SmallChangeProperty);
        set => SetValue(SmallChangeProperty, value);
    }

    private static void OnLabelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is not ToolBarNumberField control)
        {
            return;
        }

        control._LabelTextBlock.Text = e.NewValue as string ?? string.Empty;
    }

    private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is not ToolBarNumberField control || control._isUpdatingFromNumberBox)
        {
            return;
        }

        if (e.NewValue is not double value || control._NumberBox == null)
        {
            return;
        }

        if (control._NumberBox.Value == value)
        {
            return;
        }

        control._NumberBox.Value = value;
    }

    private static void OnSmallChangeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is not ToolBarNumberField control)
        {
            return;
        }

        if (e.NewValue is not double value || control._NumberBox == null)
        {
            return;
        }

        control._NumberBox.SmallChange = value;
    }

    private void NumberBox_ValueChanged(NumberBox sender, NumberBoxValueChangedEventArgs args)
    {
        _isUpdatingFromNumberBox = true;
        try
        {
            SetValue(ValueProperty, sender.Value);
        }
        finally
        {
            _isUpdatingFromNumberBox = false;
        }

        ValueChanged?.Invoke(sender, args);
    }
}
