using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;

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

public class MyComboBox : ComboBox
{
    public delegate void TextChangedEventHandler(object sender, TextChangedEventArgs e);

    public static readonly DependencyProperty HintTextProperty = DependencyProperty.Register("HintText", typeof(string),
        typeof(MyComboBox), new PropertyMetadata("", (d, e) =>
        {
            var c = (MyComboBox)d;
            if (c.textBox is not null)
                c.textBox.HintText = (string)e.NewValue;
        }));

    private string _Text;

    // 鼠标按下接口
    private bool isMouseDown;

    // 修复 WPF Bug：下拉框文本修改后，依然误认为还选择着此前的选项，导致再次点击该选项时内容不变
    private bool isTextChanging;
    private double realWidth; // 由于下拉框 Popup 宽度与 Width 一致，故不能为 NaN（Auto）
    private MyTextBox textBox;

    // 基础
    public int Uuid = ModBase.GetUuid();

    public MyComboBox()
    {
        _Text = SelectedItem?.ToString() ?? "";
        PreviewMouseLeftButtonDown += MyComboBox_PreviewMouseLeftButtonDown;
        PreviewMouseLeftButtonUp += MyComboBox_PreviewMouseLeftButtonUp;
        MouseLeave += MyComboBox_PreviewMouseLeftButtonUp;
        IsEnabledChanged += (_, _) => RefreshColor();
        MouseEnter += (_, _) => RefreshColor();
        MouseLeave += (_, _) => RefreshColor();
        PreviewMouseLeftButtonDown += (_, _) => RefreshColor();
        PreviewMouseLeftButtonUp += (_, _) => RefreshColor();
        GotKeyboardFocus += (_, _) => RefreshColor();
        DropDownOpened += MyComboBox_DropDownOpened;
        DropDownClosed += MyComboBox_DropDownClosed;
        TextChanged += MyComboBox_TextChanged;
    }

    public string HintText
    {
        get => (string)GetValue(HintTextProperty);
        set => SetValue(HintTextProperty, value);
    }

    public new string Text
    {
        get
        {
            if (IsEditable)
            {
                if (textBox is null) return _Text ?? "";
                return textBox.Text ?? "";
            }

            return (SelectedItem ?? "").ToString();
        }
        set
        {
            if (IsEditable)
            {
                if (textBox is null)
                    _Text = value;
                else
                    textBox.Text = value;
            }
            else
            {
                throw new NotSupportedException("该 ComboBox 不支持修改文本。");
            }
        }
    }

    public bool DropDownWidthSync { get; set; } = true;

    public ContentPresenter ContentPresenter => (ContentPresenter)Template.FindName("PART_Content", this);
    public event TextChangedEventHandler? TextChanged;

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        if (!IsEditable)
            return;
        try
        {
            textBox = (MyTextBox)Template.FindName("PART_EditableTextBox", this);
            textBox.AddHandler(LostFocusEvent, new RoutedEventHandler((_, _) => RefreshColor()));
            textBox.changedEventList.Add((sender, e) => TextChanged?.Invoke(sender, (TextChangedEventArgs)e));
            textBox.Tag = Tag; // 有时需要用文本框的 Tag 来写入设置
            if (string.IsNullOrEmpty(Text))
                textBox.Text = _Text;
            else
                TextChanged?.Invoke(this, null);
            if (HintText.Length > 0)
                textBox.HintText = HintText;
            textBox.SetResourceReference(TextBoxBase.CaretBrushProperty, "ColorBrushGray1");
        }
        catch (Exception ex)
        {
            ModBase.Log(
                ex,
                "初始化可编辑文本框失败（" + (Name ?? "") + "）",
                ModBase.LogLevel.Feedback,
                userSummary: Lang.Text("Application.Control.Error.OperationFailed"));
        }
    }

    private void MyComboBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        isMouseDown = true;
    }

    private void MyComboBox_PreviewMouseLeftButtonUp(object sender, EventArgs e)
    {
        isMouseDown = false;
    }

    // 指向动画
    public void RefreshColor()
    {
        // 判断当前颜色
        string foreColorName;
        string backColorName;
        int time;
        if (IsEnabled)
        {
            if (isMouseDown || IsDropDownOpen ||
                (IsEditable && ((MyTextBox)Template.FindName("PART_EditableTextBox", this)).IsFocused))
            {
                foreColorName = "ColorBrush3";
                backColorName = "ColorBrush7";
                time = 10;
            }
            else if (IsMouseOver)
            {
                foreColorName = "ColorBrush4";
                backColorName = "ColorBrush7";
                time = 100;
            }
            else
            {
                foreColorName = "ColorBrushBg0";
                backColorName = "ColorBrushHalfWhite";
                time = 100;
            }
        }
        else
        {
            foreColorName = "ColorBrushGray5";
            backColorName = "ColorBrushGray6";
            time = 200;
        }

        // 触发颜色动画
        if (IsLoaded && ModAnimation.AniControlEnabled == 0) // 防止默认属性变更触发动画
        {
            // 有动画
            ModAnimation.AniStart(
                new[]
                {
                    ModAnimation.AaColor(this, ForegroundProperty, foreColorName, time),
                    ModAnimation.AaColor(this, BackgroundProperty, backColorName, time)
                }, "MyComboBox Color " + Uuid);
        }
        else
        {
            // 无动画
            ModAnimation.AniStop("MyComboBox Color " + Uuid);
            SetResourceReference(ForegroundProperty, foreColorName);
            SetResourceReference(BackgroundProperty, backColorName);
        }
    }

    private void MyComboBox_DropDownOpened(object sender, EventArgs e)
    {
        realWidth = Width;
        if (DropDownWidthSync)
            Width = ActualWidth;
        try
        {
            var popup = (Grid)Template.FindName("PanPopup", this);
            popup.Opacity = ModMain.frmMain.Opacity;
            if (!DropDownWidthSync)
                popup.MinWidth = ActualWidth;
        }
        catch (Exception ex)
        {
            ModBase.Log(
                ex,
                "设置下拉框属性失败",
                ModBase.LogLevel.Feedback,
                userSummary: Lang.Text("Application.Control.Error.OperationFailed"));
        }
    }

    private void MyComboBox_DropDownClosed(object sender, EventArgs e)
    {
        Width = realWidth;
    }

    private void MyComboBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        if (isTextChanging || !IsEditable)
            return;
        if (SelectedItem is null || Text == SelectedItem.ToString()) return;
        {
            var rawText = Text;
            var rawSelectionStart = textBox.SelectionStart;
            isTextChanging = true;
            SelectedItem = null;
            Text = rawText;
            textBox.SelectionStart = rawSelectionStart;
            isTextChanging = false;
        }
    }

    // 用于 ItemsSource 的自定义容器
    protected override DependencyObject GetContainerForItemOverride()
    {
        return new MyComboBoxItem();
    }
    
    private void MyComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (IsLoaded && ModAnimation.AniControlEnabled == 0) ModMain.RaiseCustomEvent(this);
    }
    
    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return item is MyComboBoxItem || base.IsItemItsOwnContainerOverride(item);
    }
}