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.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace NEIntelligentControl2.Views.Basic
{
    /// <summary>
    /// 可框选的UniformGrid
    /// </summary>
    public partial class OptionalUniformGrid : UserControl
    {
        // ----------依赖项属性-------------
        public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register("Columns", typeof(int), typeof(OptionalUniformGrid));
        /// <summary>
        /// 获取或设置网格中的列数
        /// </summary>
        public int Columns { get => (int)GetValue(ColumnsProperty); set => SetValue(ColumnsProperty, value); }
        /// <summary>
        /// 获取子元素
        /// </summary>
        public UIElementCollection Children { get => _UGMain.Children; }

        private IOptional _CurrentSelected;         // 当前选中的卡片
        private List<IOptional> _Optionals;         // 控件集合

        private Point _StartPoint;                  // 开始框选鼠标位置

        private int _MoveTimes;                     // 移动次数
        public OptionalUniformGrid()
        {
            InitializeComponent();
            _Optionals = new List<IOptional>();
        }

        public void Add(UIElement element)
        {
            _UGMain.Children.Add(element);
            var v = element as IOptional;
            if (v == null) return;
            _Optionals.Add(v);
            v.SelectedChanged += ItemSelectedChanged;
            if (_CurrentSelected == null)
                _CurrentSelected = v;
        }

        internal void Remove(UIElement ue)
        {
            if (ue == null) return;
            var v = ue as IOptional;
            if (v != null)
            {
                _Optionals.Remove(v);
            }
            _UGMain.Children.Remove(ue);
        }

        private void ItemSelectedChanged(IOptional sender, bool isMultiSelect)
        {
            if (isMultiSelect)
            {
                SelectAll(sender);
            }
            else
            {
                _CurrentSelected = sender;
                sender.IsSelected = !sender.IsSelected;
            }
        }

        private void SelectAll(IOptional sender)
        {
            int index1 = _Optionals.IndexOf(_CurrentSelected);
            int index2 = _Optionals.IndexOf(sender);

            if (index1 > index2)
            {
                int i = index1;
                index1 = index2;
                index2 = i;
            }

            for (int i = 0; i < _Optionals.Count; ++i)
            {
                bool b = i >= index1 && i <= index2;
                _Optionals[i].IsSelected = b;
            }
        }


        private void Grid_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton != MouseButtonState.Pressed) return;
            ++_MoveTimes;
            if (_MoveTimes < 2) return;
            var ct = sender as Grid;
            if (ct == null) return;
            if (_RTMain.Visibility != Visibility.Visible)
            {
                _RTMain.Visibility = Visibility.Visible;
            }

            var ponit = e.GetPosition(ct);

            Point p1 = new Point();
            p1.X = _StartPoint.X < ponit.X ? _StartPoint.X : ponit.X;
            p1.Y = _StartPoint.Y < ponit.Y ? _StartPoint.Y : ponit.Y;

            Point p2 = new Point();
            p2.X = _StartPoint.X > ponit.X ? _StartPoint.X : ponit.X;
            p2.Y = _StartPoint.Y > ponit.Y ? _StartPoint.Y : ponit.Y;


            _RTMain.Margin = new Thickness(p1.X, p1.Y, ct.ActualWidth - p2.X, ct.ActualHeight - p2.Y);

            CheckSelected(new Rect(p1, p2));
        }

        private void CheckSelected(Rect rect)
        {
            var pt = new Point();
            foreach (var v in _UGMain.Children)
            {
                var o = v as IOptional;
                var ct = v as Control;
                if (o == null || ct == null) continue;

                var tt = ct.TransformToAncestor(_UGMain).Transform(pt);
                Rect rt = new Rect(tt.X, tt.Y, ct.ActualWidth, ct.ActualHeight);

                var b = rect.IntersectsWith(rt);
                if (Keyboard.Modifiers == ModifierKeys.Control)
                {
                    if (b) o.IsSelected = true;
                }
                else
                {
                    o.IsSelected = b;
                }
            }
        }

        private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var ct = sender as Grid;
            if (ct == null) return;
            _StartPoint = e.GetPosition(ct);
        }

        private void Grid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            _MoveTimes = 0;
            _RTMain.Visibility = Visibility.Collapsed;

            if (sender != e.OriginalSource) return;

            foreach (var v in _UGMain.Children)
            {
                (v as IOptional).IsSelected = false;
            }
        }

        private void Grid_MouseLeave(object sender, MouseEventArgs e)
        {
            _MoveTimes = 0;
            _RTMain.Visibility = Visibility.Collapsed;
            if (e.LeftButton != MouseButtonState.Pressed) return;
            foreach (var v in _Optionals)
            {
                v.IsSelected = false;
            }
        }

        internal void Clear()
        {
            _UGMain.Children.Clear();
            _Optionals.Clear();
        }
    }


    /// <summary>
    /// 可选择的
    /// </summary>
    public interface IOptional
    {
        /// <summary>
        /// 是否被选中
        /// </summary>
        bool IsSelected { get; set; }

        /// <summary>
        /// 选择改变事件
        /// </summary>
        event SelectedEventHandler SelectedChanged;
    }

    /// <summary>
    /// 卡片被选择事件
    /// </summary>
    /// <param name="sender">发送者</param>
    /// <param name="isMultiSelect">是否多选</param>
    public delegate void SelectedEventHandler(IOptional sender, bool isMultiSelect);
}
