using System.Collections;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Windows.Shapes;

using PCL.Core.App.Localization;
namespace PCL;

[ContentProperty("Inlines")]
public partial class MyRadioBox : IMyRadio
{
    public delegate void PreviewChangeEventHandler(object sender, ModBase.RouteEventArgs e);

    public delegate void PreviewCheckEventHandler(object sender, ModBase.RouteEventArgs e);

    // 指向动画

    private const int animationTimeOfMouseIn = 100; // 鼠标指向动画长度
    private const int animationTimeOfMouseOut = 200; // 鼠标指向动画长度

    private const int animationTimeOfCheck = 150; // 勾选状态变更动画长度

    // 在使用 XAML 设置 Checked 属性时，不会触发 Checked_Set 方法，所以需要在这里手动触发 UI 改变
    public static readonly DependencyProperty CheckedProperty = DependencyProperty.Register("Checked", typeof(bool),
        typeof(MyRadioBox), new PropertyMetadata(false, (dRaw, e) =>
        {
            var d = (MyRadioBox)dRaw;
            if (!d.IsLoaded) d.SyncUI();
        }));

    public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string),
        typeof(MyRadioBox), new PropertyMetadata((sender, e) =>
        {
            if (sender is not null) ((MyRadioBox)sender).LabText.Text = (string)e.NewValue;
        }));

    private bool allowMouseDown = true;

    // 点击事件

    private bool mouseDowned;

    // 基础

    public int Uuid = ModBase.GetUuid();

    public MyRadioBox()
    {
        InitializeComponent();
        MouseLeftButtonUp += (_, _) => Radiobox_MouseUp();
        MouseLeftButtonDown += (_, _) => Radiobox_MouseDown();
        MouseLeave += (_, _) => Radiobox_MouseLeave();
        IsEnabledChanged += (_, _) => Radiobox_IsEnabledChanged();
        MouseEnter += (_, _) => Radiobox_MouseEnterAnimation();
        MouseLeave += (_, _) => Radiobox_MouseLeaveAnimation();
    }

    // 自定义属性
    public bool Checked
    {
        get => (bool)GetValue(CheckedProperty);
        set => SetChecked(value, false);
    }

    public InlineCollection Inlines => LabText.Inlines;

    public string Text
    {
        get => (string)GetValue(TextProperty);
        set => SetValue(TextProperty, value);
    } // 内容

    public event IMyRadio.CheckEventHandler? Check;
    public event IMyRadio.ChangedEventHandler? Changed;
    public event PreviewCheckEventHandler? PreviewCheck;
    public event PreviewChangeEventHandler? PreviewChange;

    /// <summary>
    ///     手动设置 Checked 属性。
    /// </summary>
    /// <param name="value">新的 Checked 属性。</param>
    /// <param name="user">是否由用户引发。</param>
    public void SetChecked(bool value, bool user)
    {
        try
        {
            // Preview 事件
            if (value && user)
            {
                var e = new ModBase.RouteEventArgs(user);
                PreviewCheck?.Invoke(this, e);
                if (e.handled)
                {
                    Radiobox_MouseLeave();
                    return;
                }
            }

            // 自定义属性基础
            var isChanged = false;
            if (IsLoaded && value != Checked)
                PreviewChange?.Invoke(this, new ModBase.RouteEventArgs(user));
            if (value != Checked)
            {
                SetValue(CheckedProperty, value);
                isChanged = true;
            }

            // 保证只有一个单选框选中
            if (Parent is null)
                return;
            var radioboxList = new List<MyRadioBox>();
            var checkedCount = 0;
            foreach (var Control in ((Panel)Parent).Children) // 收集控件列表与选中个数
                if (Control is MyRadioBox radioBox)
                {
                    radioboxList.Add(radioBox);
                    if (radioBox.Checked)
                        checkedCount += 1;
                }

            switch (checkedCount) // 判断选中情况
            {
                case 0:
                {
                    // 没有任何单选框被选中，选择第一个
                    radioboxList[0].Checked = true;
                    break;
                }
                case var @case when @case > 1:
                {
                    // 选中项目多于 1 个
                    if (Checked)
                    {
                        // 如果本控件选中，则取消其他所有控件的选中
                        foreach (var Control in radioboxList)
                            if (Control.Checked && !Control.Equals(this))
                                Control.Checked = false;
                    }
                    else
                    {
                        // 如果本控件未选中，则只保留第一个选中的控件
                        var firstChecked = false;
                        foreach (var Control in radioboxList)
                            if (Control.Checked)
                            {
                                if (firstChecked)
                                    Control.Checked = false; // 修改 Checked 会自动触发 Change 事件，所以不用额外触发
                                else
                                    firstChecked = true;
                            }
                    }

                    break;
                }
            }

            // 触发事件
            if (isChanged)
            {
                if (Checked)
                    Check?.Invoke(this, new ModBase.RouteEventArgs(user));
                Changed?.Invoke(this, new ModBase.RouteEventArgs(user));
                ModMain.RaiseCustomEvent(this);
            }

            // 更改动画
            SyncUI();
        }
        catch (Exception ex)
        {
            ModBase.Log(
                ex,
                "单选框勾选改变错误",
                ModBase.LogLevel.Hint,
                userSummary: Lang.Text("Application.Control.Error.OperationFailed"));
        }
    }

    private void SyncUI()
    {
        if (ControlVisualHelpers.ShouldAnimate(this)) // 防止默认属性变更触发动画
        {
            if (Checked)
            {
                // 由无变有
                if (ShapeDot.Opacity < 0.01d)
                    ShapeDot.Opacity = 1d;
                ModAnimation.AniStart(
                    new[]
                    {
                        ModAnimation.AaScale(ShapeBorder, 10d - ShapeBorder.Width, animationTimeOfCheck,
                            ease: new ModAnimation.AniEaseOutFluent(ModAnimation.AniEasePower.Weak), absolute: true),
                        ModAnimation.AaScale(ShapeBorder, 8d, animationTimeOfCheck * 2,
                            (int)Math.Round(animationTimeOfCheck * 0.6d), new ModAnimation.AniEaseOutBack(),
                            absolute: true)
                    }, "MyRadioBox Border " + Uuid);
                ModAnimation.AniStart(
                    new[]
                    {
                        ModAnimation.AaScale(ShapeDot, 9d - ShapeDot.Width,
                            (int)Math.Round(animationTimeOfCheck * 2.6d),
                            ease: new ModAnimation.AniEaseOutBack(ModAnimation.AniEasePower.Weak), absolute: true),
                        ModAnimation.AaOpacity(ShapeDot, 1d - ShapeDot.Opacity,
                            (int)Math.Round(animationTimeOfCheck * 0.5d), (int)Math.Round(animationTimeOfCheck * 0.6d))
                    }, "MyRadioBox Dot " + Uuid);
                ModAnimation.AniStart(
                    ModAnimation.AaColor(ShapeBorder, Shape.StrokeProperty,
                        IsMouseOver ? "ColorBrush3" : IsEnabled ? "ColorBrush2" : "ColorBrushGray4",
                        animationTimeOfCheck),
                    "MyRadioBox BorderColor " + Uuid);
            }
            else
            {
                // 由有变无
                ModAnimation.AniStart(
                    new[]
                    {
                        ModAnimation.AaScale(ShapeBorder, 18d - ShapeBorder.Width, animationTimeOfCheck,
                            ease: new ModAnimation.AniEaseOutFluent(), absolute: true)
                    }, "MyRadioBox Border " + Uuid);
                ModAnimation.AniStart(
                    new[]
                    {
                        ModAnimation.AaScale(ShapeDot, -ShapeDot.Width, animationTimeOfCheck,
                            ease: new ModAnimation.AniEaseInFluent(), absolute: true),
                        ModAnimation.AaOpacity(ShapeDot, -ShapeDot.Opacity,
                            (int)Math.Round(animationTimeOfCheck * 0.5d), (int)Math.Round(animationTimeOfCheck * 0.2d))
                    }, "MyRadioBox Dot " + Uuid);
                ModAnimation.AniStart(
                    ModAnimation.AaColor(ShapeBorder, Shape.StrokeProperty,
                        IsMouseOver ? "ColorBrush3" : IsEnabled ? "ColorBrush1" : "ColorBrushGray4",
                        animationTimeOfCheck),
                    "MyRadioBox BorderColor " + Uuid);
            }
        }
        else
        {
            // 不使用动画
            ModAnimation.AniStop("MyRadioBox Border " + Uuid);
            ModAnimation.AniStop("MyRadioBox Dot " + Uuid);
            ModAnimation.AniStop("MyRadioBox BorderColor " + Uuid);
            if (Checked)
            {
                ShapeDot.Width = 9d;
                ShapeDot.Height = 9d;
                ShapeDot.Opacity = 1d;
                ShapeDot.Margin = new Thickness(5.5d, 0d, 0d, 0d);
                ShapeBorder.SetResourceReference(Shape.StrokeProperty, IsEnabled ? "ColorBrush2" : "ColorBrushGray4");
            }
            else
            {
                ShapeDot.Width = 0d;
                ShapeDot.Height = 0d;
                ShapeDot.Opacity = 0d;
                ShapeDot.Margin = new Thickness(10d, 0d, 0d, 0d);
                ShapeBorder.SetResourceReference(Shape.StrokeProperty, IsEnabled ? "ColorBrush1" : "ColorBrushGray4");
            }
        }
    }

    private void Radiobox_MouseUp()
    {
        if (!mouseDowned)
            return;
        ModBase.Log("[Control] 按下单选框：" + Text);
        SetChecked(true, true);
        mouseDowned = false;
        ModAnimation.AniStart(ModAnimation.AaColor(ShapeBorder, Shape.FillProperty, "ColorBrushHalfWhite", 100),
            "MyRadioBox Background " + Uuid);
    }

    private void Radiobox_MouseDown()
    {
        mouseDowned = true;
        Focus();
        ModAnimation.AniStart(ModAnimation.AaColor(ShapeBorder, Shape.FillProperty, "ColorBrushBg1", 100),
            "MyRadioBox Background " + Uuid);
        if (!Checked)
            ModAnimation.AniStart(
                ModAnimation.AaScale(ShapeBorder, 16.5d - ShapeBorder.Width, 1000,
                    ease: new ModAnimation.AniEaseOutFluent(ModAnimation.AniEasePower.Strong), absolute: true),
                "MyRadioBox Border " + Uuid);
    }

    private void Radiobox_MouseLeave()
    {
        if (!mouseDowned)
            return;
        mouseDowned = false;
        ModAnimation.AniStart(ModAnimation.AaColor(ShapeBorder, Shape.FillProperty, "ColorBrushHalfWhite", 100),
            "MyRadioBox Background " + Uuid);
        if (!Checked)
            ModAnimation.AniStart(
                ModAnimation.AaScale(ShapeBorder, 18d - ShapeBorder.Width,
                    ease: new ModAnimation.AniEaseOutFluent(ModAnimation.AniEasePower.Strong), absolute: true),
                "MyRadioBox Border " + Uuid);
    }

    private void Radiobox_IsEnabledChanged()
    {
        if (ControlVisualHelpers.ShouldAnimate(this)) // 防止默认属性变更触发动画
        {
            // 有动画
            if (IsEnabled)
            {
                // 可用
                Radiobox_MouseLeaveAnimation();
            }
            else
            {
                // 不可用
                ModAnimation.AniStart(
                    ModAnimation.AaColor(ShapeBorder, Shape.StrokeProperty, ThemeManager.colorGray4 - ShapeBorder.Stroke,
                        animationTimeOfMouseOut), "MyRadioBox BorderColor " + Uuid);
                ModAnimation.AniStart(
                    ModAnimation.AaColor(LabText, TextBlock.ForegroundProperty,
                        ThemeManager.colorGray4 - LabText.Foreground, animationTimeOfMouseOut),
                    "MyRadioBox TextColor " + Uuid);
            }
        }
        else
        {
            // 无动画
            ModAnimation.AniStop("MyRadioBox BorderColor " + Uuid);
            ModAnimation.AniStop("MyRadioBox TextColor " + Uuid);
            LabText.SetResourceReference(TextBlock.ForegroundProperty, IsEnabled ? "ColorBrush1" : "ColorBrushGray4");
            ShapeBorder.SetResourceReference(Shape.StrokeProperty,
                IsEnabled ? Checked ? "ColorBrush2" : "ColorBrush1" : "ColorBrushGray4");
        }
    }

    private void Radiobox_MouseEnterAnimation()
    {
        ModAnimation.AniStart(
            ModAnimation.AaColor(ShapeBorder, Shape.StrokeProperty, "ColorBrush3", animationTimeOfMouseIn),
            "MyRadioBox BorderColor " + Uuid);
        ModAnimation.AniStart(
            ModAnimation.AaColor(LabText, TextBlock.ForegroundProperty, "ColorBrush3", animationTimeOfMouseIn),
            "MyRadioBox TextColor " + Uuid);
    }

    private void Radiobox_MouseLeaveAnimation()
    {
        if (!IsEnabled)
            return; // MouseLeave 比 IsEnabledChanged 后执行，所以如果自定义事件修改了 IsEnabled，将导致显示错误
        if (ControlVisualHelpers.ShouldAnimate(this))
        {
            ModAnimation.AniStart(
                ModAnimation.AaColor(ShapeBorder, Shape.StrokeProperty,
                    IsEnabled ? Checked ? "ColorBrush2" : "ColorBrush1" : "ColorBrushGray4", animationTimeOfMouseOut),
                "MyRadioBox BorderColor " + Uuid);
            ModAnimation.AniStart(
                ModAnimation.AaColor(LabText, TextBlock.ForegroundProperty,
                    IsEnabled ? "ColorBrush1" : "ColorBrushGray4", animationTimeOfMouseOut),
                "MyRadioBox TextColor " + Uuid);
        }
        else
        {
            ModAnimation.AniStop("MyRadioBox BorderColor " + Uuid);
            ModAnimation.AniStop("MyRadioBox TextColor " + Uuid);
            ShapeBorder.SetResourceReference(Shape.StrokeProperty,
                IsEnabled ? Checked ? "ColorBrush2" : "ColorBrush1" : "ColorBrushGray4");
            LabText.SetResourceReference(TextBlock.ForegroundProperty, IsEnabled ? "ColorBrush1" : "ColorBrushGray4");
        }
    }
}
