using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Markup;
using System.Collections.Generic;
using Windows.Foundation;

namespace Sonex.Client.Controls;

[ContentProperty(Name = nameof(Children))]
public sealed partial class ToolBar : UserControl
{
    public static readonly DependencyProperty ChromePaddingProperty = DependencyProperty.Register(
        nameof(ChromePadding),
        typeof(Thickness),
        typeof(ToolBar),
        new PropertyMetadata(new Thickness(8d, 6d, 8d, 6d)));

    public static readonly DependencyProperty ChromeCornerRadiusProperty = DependencyProperty.Register(
        nameof(ChromeCornerRadius),
        typeof(CornerRadius),
        typeof(ToolBar),
        new PropertyMetadata(new CornerRadius(10d)));

    public static readonly DependencyProperty ChromeBorderThicknessProperty = DependencyProperty.Register(
        nameof(ChromeBorderThickness),
        typeof(Thickness),
        typeof(ToolBar),
        new PropertyMetadata(new Thickness(1d)));

    private bool _isCompactionUpdateInProgress;

    public ToolBar()
    {
        InitializeComponent();
        Loaded += ToolBar_Loaded;
        SizeChanged += ToolBar_SizeChanged;
    }

    public UIElementCollection Children => _ChildrenHost.Children;

    public Thickness ChromePadding
    {
        get => (Thickness)GetValue(ChromePaddingProperty);
        set => SetValue(ChromePaddingProperty, value);
    }

    public CornerRadius ChromeCornerRadius
    {
        get => (CornerRadius)GetValue(ChromeCornerRadiusProperty);
        set => SetValue(ChromeCornerRadiusProperty, value);
    }

    public Thickness ChromeBorderThickness
    {
        get => (Thickness)GetValue(ChromeBorderThicknessProperty);
        set => SetValue(ChromeBorderThicknessProperty, value);
    }

    private void ToolBar_Loaded(object sender, RoutedEventArgs e)
    {
        UpdateGroupCompaction();
    }

    private void ToolBar_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        UpdateGroupCompaction();
    }

    private void UpdateGroupCompaction()
    {
        if (_isCompactionUpdateInProgress || _ChildrenHost == null || _RootBorder == null)
        {
            return;
        }

        var availableWidth = GetAvailableContentWidth();
        if (availableWidth <= 0d)
        {
            return;
        }

        _isCompactionUpdateInProgress = true;
        try
        {
            var groups = new List<ToolBarGroup>();
            foreach (var child in _ChildrenHost.Children)
            {
                if (child is ToolBarGroup group)
                {
                    groups.Add(group);
                    group.IsCompact = false;
                }
            }

            if (groups.Count == 0)
            {
                return;
            }

            var totalWidth = MeasureChildrenWidth();
            if (totalWidth <= availableWidth)
            {
                return;
            }

            for (var i = groups.Count - 1; i >= 0 && totalWidth > availableWidth; i--)
            {
                groups[i].IsCompact = true;
                totalWidth = MeasureChildrenWidth();
            }
        }
        finally
        {
            _isCompactionUpdateInProgress = false;
        }
    }

    private double MeasureChildrenWidth()
    {
        var totalWidth = 0d;
        foreach (var child in _ChildrenHost.Children)
        {
            if (child is not UIElement element)
            {
                continue;
            }

            element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
            totalWidth += element.DesiredSize.Width;
        }

        return totalWidth;
    }

    private double GetAvailableContentWidth()
    {
        var width = _RootBorder.ActualWidth;
        width -= _RootBorder.Padding.Left + _RootBorder.Padding.Right;
        width -= _RootBorder.BorderThickness.Left + _RootBorder.BorderThickness.Right;
        return width;
    }
}
