using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using MainShell.Resources.CustomControl;

namespace MainShell.Common.ControlAttribute
{
    public static class ControlBehavior
    {
        public static bool GetIsEnable(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsEnableProperty);
        }

        public static void SetIsEnable(DependencyObject obj, bool value)
        {
            obj.SetValue(IsEnableProperty, value);
        }

        // Using a DependencyProperty as the backing store for IsEnable.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsEnableProperty =
            DependencyProperty.RegisterAttached("IsEnable", typeof(bool), typeof(ControlBehavior), new PropertyMetadata(true, OnProppertyChanged));

        public static bool GetIsNumericOnly(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsNumericOnlyProperty);
        }

        public static void SetIsNumericOnly(DependencyObject obj, bool value)
        {
            obj.SetValue(IsNumericOnlyProperty, value);
        }

        public static readonly DependencyProperty IsNumericOnlyProperty =
            DependencyProperty.RegisterAttached("IsNumericOnly", typeof(bool), typeof(ControlBehavior), new PropertyMetadata(false, OnIsNumericOnlyChanged));

        public static bool GetRouteDieMapMouseWheel(DependencyObject obj)
        {
            return (bool)obj.GetValue(RouteDieMapMouseWheelProperty);
        }

        public static void SetRouteDieMapMouseWheel(DependencyObject obj, bool value)
        {
            obj.SetValue(RouteDieMapMouseWheelProperty, value);
        }

        public static readonly DependencyProperty RouteDieMapMouseWheelProperty =
            DependencyProperty.RegisterAttached("RouteDieMapMouseWheel", typeof(bool), typeof(ControlBehavior), new PropertyMetadata(false, OnRouteDieMapMouseWheelChanged));


        private static void OnProppertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is TabControl tabControl)
            {
                if (e.NewValue is bool isenable)
                {
                    if (isenable)
                        foreach (var item in tabControl.Items)
                        {
                            if (tabControl.ItemContainerGenerator.ContainerFromItem(item) is TabItem tabItem)
                            {
                                tabItem.IsEnabled = isenable;
                            }
                        }
                    else
                        foreach (var item in tabControl.Items)
                        {
                            if (tabControl.ItemContainerGenerator.ContainerFromItem(item) is TabItem tabItem)
                            {
                                if (tabItem.IsSelected)
                                {
                                    tabItem.IsEnabled = true;
                                }
                                else
                                    tabItem.IsEnabled = isenable;
                            }
                        }
                }

            }
        }

        private static void OnIsNumericOnlyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (!(d is TextBox textBox))
                return;

            if ((bool)e.NewValue)
            {
                InputMethod.SetIsInputMethodEnabled(textBox, false);
                textBox.PreviewTextInput += TextBox_PreviewTextInput;
                DataObject.AddPastingHandler(textBox, OnTextBoxPaste);
            }
            else
            {
                InputMethod.SetIsInputMethodEnabled(textBox, true);
                textBox.PreviewTextInput -= TextBox_PreviewTextInput;
                DataObject.RemovePastingHandler(textBox, OnTextBoxPaste);
            }
        }

        private static void OnRouteDieMapMouseWheelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ScrollViewer scrollViewer = d as ScrollViewer;
            if (scrollViewer == null)
            {
                return;
            }

            bool isEnabled = e.NewValue is bool && (bool)e.NewValue;
            MouseWheelEventHandler mouseWheelEventHandler = new MouseWheelEventHandler(ScrollViewer_PreviewMouseWheel);
            if (isEnabled)
            {
                scrollViewer.RemoveHandler(UIElement.PreviewMouseWheelEvent, mouseWheelEventHandler);
                scrollViewer.AddHandler(UIElement.PreviewMouseWheelEvent, mouseWheelEventHandler, true);
            }
            else
            {
                scrollViewer.RemoveHandler(UIElement.PreviewMouseWheelEvent, mouseWheelEventHandler);
            }
        }

        private static void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
        {
            ScrollViewer scrollViewer = sender as ScrollViewer;
            if (scrollViewer == null)
            {
                return;
            }

            DieMapControl dieMapControl = FindDieMapControl(scrollViewer, e);
            if (dieMapControl == null)
            {
                return;
            }

            e.Handled = true;

            MouseWheelEventArgs mouseWheelEventArgs = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
            mouseWheelEventArgs.RoutedEvent = UIElement.MouseWheelEvent;
            mouseWheelEventArgs.Source = dieMapControl;
            dieMapControl.RaiseEvent(mouseWheelEventArgs);
        }

        private static DieMapControl FindDieMapControl(ScrollViewer scrollViewer, MouseWheelEventArgs e)
        {
            DependencyObject dependencyObject = e.OriginalSource as DependencyObject;
            DieMapControl dieMapControl = FindAncestor<DieMapControl>(dependencyObject);
            if (dieMapControl != null)
            {
                return dieMapControl;
            }

            dependencyObject = Mouse.DirectlyOver as DependencyObject;
            dieMapControl = FindAncestor<DieMapControl>(dependencyObject);
            if (dieMapControl != null)
            {
                return dieMapControl;
            }

            IInputElement inputElement = scrollViewer.InputHitTest(e.GetPosition(scrollViewer));
            dependencyObject = inputElement as DependencyObject;
            return FindAncestor<DieMapControl>(dependencyObject);
        }

        private static T FindAncestor<T>(DependencyObject dependencyObject) where T : DependencyObject
        {
            while (dependencyObject != null)
            {
                T target = dependencyObject as T;
                if (target != null)
                {
                    return target;
                }

                DependencyObject parent = VisualTreeHelper.GetParent(dependencyObject);
                if (parent == null && dependencyObject is FrameworkContentElement)
                {
                    parent = ((FrameworkContentElement)dependencyObject).Parent;
                }

                dependencyObject = parent;
            }

            return null;
        }

        private static void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            if (sender is TextBox textBox)
            {
                e.Handled = !IsValidNumericText(GetPreviewText(textBox, e.Text));
            }
        }

        private static void OnTextBoxPaste(object sender, DataObjectPastingEventArgs e)
        {
            if (!(sender is TextBox textBox))
                return;

            if (!e.DataObject.GetDataPresent(typeof(string)))
            {
                e.CancelCommand();
                return;
            }

            var pasteText = e.DataObject.GetData(typeof(string)) as string ?? string.Empty;
            if (!IsValidNumericText(GetPreviewText(textBox, pasteText)))
            {
                e.CancelCommand();
            }
        }

        private static string GetPreviewText(TextBox textBox, string newText)
        {
            var currentText = textBox.Text ?? string.Empty;
            if (textBox.SelectionLength > 0)
            {
                currentText = currentText.Remove(textBox.SelectionStart, textBox.SelectionLength);
            }

            return currentText.Insert(textBox.CaretIndex, newText);
        }

        private static bool IsValidNumericText(string text)
        {
            if (string.IsNullOrWhiteSpace(text) || text == "-" || text == "." || text == "-.")
                return true;

            return double.TryParse(text, out _);
        }

    }
}
