using PDF_Office.EventAggregators;
using PDF_Office.Helper;
using PDF_Office.Model.PageEdit;
using Prism.Events;
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.Controls.Primitives;
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;
using System.Windows.Threading;
using WpfToolkit.Controls;

namespace PDF_Office.Views.PageEdit
{
    /// <summary>
    /// PageEditContent.xaml 的交互逻辑
    /// </summary>
    public partial class PageEditContent : UserControl
    {
        /// <summary>
        /// 用于通知刷新图片的事件
        /// 因为目前的图片刷新策略依赖很多UI事件判断，因为将主要判断逻辑放在UI层，VM负责图片刷新，非必要情况尽量不要采用这种形式
        /// </summary>
        private IEventAggregator eventor;

        /// <summary>
        /// 暂存的唯一索引值,用于区分多页签
        /// </summary>
        private string unicode;

        /// <summary>
        /// 是否是加载时第一次触发滚动
        /// </summary>
        private bool isFirstScrollChange = true;

        /// <summary>
        /// 用于判断滚轮停止的计时器
        /// </summary>
        private DispatcherTimer timer = new DispatcherTimer();

        /// <summary>
        /// 判断是否开始框选
        /// </summary>
        private bool startChoose = false;

        /// <summary>
        /// 框选的起始位置
        /// </summary>
        private Point starPosition = new Point();

        /// <summary>
        /// 记录当前滑块的状态
        /// </summary>
        private ScrollEventType scrolltype = ScrollEventType.EndScroll;

        public PageEditContent()
        {
            InitializeComponent();
        }


        public PageEditContent(IEventAggregator eventAggregator) :this()
        {
            eventor = eventAggregator;
            unicode = App.mainWindowViewModel.SelectedItem.Unicode;

            timer.Interval = TimeSpan.FromSeconds(0.3);
            timer.Tick += Timer_Tick;

            //订阅页面刷新事件
            eventor.GetEvent<PageEditNotifyEvent>().Subscribe(OneNotifyEvent, e => e.Unicode == unicode);
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            PulishEvent();
            timer.Stop();
        }

        private void OneNotifyEvent(PageEditNotifyEventArgs  e)
        {
            PulishEvent();
        }


        #region UI事件
        /// <summary>
        /// 每次显示的时候就触发事件，刷新所有图片
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void PageEdit_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if((bool)e.NewValue)
            {
                //当前页面没有发生变化时，刷新图片 这种情况下会拿两次图，需要留意
                PulishEvent();
                //当前页面发生变化时通过ScrollChanged事件来刷新图片
                isFirstScrollChange = true;
            }
        }

        /// <summary>
        /// 鼠标滚轮滚动时触发的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ListPageEdit_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            if (isFirstScrollChange)
            {
                PulishEvent();//第一次加载时触发的Scollchange 直接刷新界面，减少白板显示时间
                isFirstScrollChange = false;
                return;
            }
            else
            {
                if (e.VerticalChange != 0)
                    timer.Start();//暂时找不到比较好的 判断Scroller停止的方法，先用计时器粗略判断
            }
        }

        /// <summary>
        /// 拖动右侧滑块时触发的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ListPageEdit_Scroll(object sender, System.Windows.Controls.Primitives.ScrollEventArgs e)
        {
            scrolltype = e.ScrollEventType;
            if (scrolltype != System.Windows.Controls.Primitives.ScrollEventType.EndScroll)
            {
                timer.Stop();
                return;
            }
            PulishEvent();
        }

        #endregion

        #region 方法
        /// <summary>
        /// 发布事件
        /// </summary>
        private void PulishEvent()
        {
            var itemSize = (ListPageEdit.Items[0] as PageEditItem).ItemSize;
            var range = GetRoughFromView(ListPageEdit, itemSize, new Thickness(5, 10, 5, 10));
            eventor.GetEvent<PageEditRefreshEvent>().Publish(new PageEditRefreshEventArgs() { Unicode = unicode, PageRange = range });
        }

        /// <summary>
        /// 获取滑轨的垂直偏移量，结合item总数和Item尺寸以及间隔，来估算实际展示的item范围
        /// 返回值为页面范围  从1开始
        /// </summary>
        /// <param name="view"></param>
        /// <param name="itemSize"></param>
        /// <param name="itemMargin"></param>
        /// <returns></returns>
        private Tuple<int, int, int> GetRoughFromView(ListBox view, Size itemSize, Thickness itemMargin)
        {
            //var scrollViewer = GetScrollHost(view);
            var scrollViewer = CommonHelper.FindVisualChild<ScrollViewer>(view);
            if (scrollViewer == null || scrollViewer.ActualHeight == 0 || scrollViewer.ActualWidth == 0)//视图展开
                return new Tuple<int, int, int>(0, 0, 0);
            try
            {
                var currentHeight = scrollViewer.ActualHeight - view.Padding.Top;
                var currentWidth = scrollViewer.ActualWidth;
                //计算当前窗口大小能显示的行数和列数
                var columnCount = (int)(currentWidth / (itemSize.Width + itemMargin.Left));
                var rowCount = (int)Math.Ceiling(currentHeight / (itemSize.Height + itemMargin.Bottom));

                var preItemCount = (int)((scrollViewer.VerticalOffset / scrollViewer.ExtentHeight) * ((view.Items.Count + columnCount - 1) / columnCount));//滑动百分比*行数 = 大概的垂直位置
                preItemCount = preItemCount * columnCount;
                var preEnd = (int)(((scrollViewer.VerticalOffset + scrollViewer.ActualHeight) / scrollViewer.ExtentHeight) * ((view.Items.Count + columnCount - 1) / columnCount));
                preEnd = preEnd * columnCount + columnCount - 1;

                var middle = (int)Math.Ceiling(preItemCount + preEnd / 2d);

                return new Tuple<int, int, int>(
                    Math.Max(preItemCount, 0),
                    Math.Min(view.Items.Count, preEnd),
                    middle);
            }
            catch { }
            return new Tuple<int, int, int>(0, 0, 0);
        }

        /// <summary>
        /// 获取listbox里的ScrollViewer对象
        /// 留意如果有重写ListBox对象,该方法可能无效
        /// </summary>
        /// <param name="listBox"></param>
        /// <returns></returns>
        private ScrollViewer GetScrollHost(ListBox listBox)
        {
            if (VisualTreeHelper.GetChildrenCount(listBox) > 0)
            {
                int s = VisualTreeHelper.GetChildrenCount(listBox);

                Border border = VisualTreeHelper.GetChild(listBox, 0) as Border;
                if (border != null)
                {
                    return VisualTreeHelper.GetChild(border, 0) as ScrollViewer;
                }
            }
            return null;
        }

        #endregion

        /// <summary>
        /// 输入框显示时，自动获取焦点
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TextBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if((bool)e.NewValue)
            {
                (sender as Control).Focus();
            }
        }

        private void ListPageEdit_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            try
            {
                if (e.LeftButton == MouseButtonState.Pressed)
                {
                    if (startChoose)
                    {
                        var position = e.GetPosition(ListPageEdit);
                        if (position.X < 5 || position.X > ListPageEdit.ActualWidth - 5 || position.Y < 5 || position.Y > ListPageEdit.ActualHeight - 5)
                        {
                            startChoose = false;
                            RectChoose.Visibility = Visibility.Collapsed;
                            Mouse.Capture(null);//暂时未想到靠近顶部和底部自动翻滚的好方法，只能先屏蔽这部分功能
                            return;
                        }
                        DoSelectItems();
                        return;
                    }
                    //拖拽排序的逻辑
                    //var pos = e.GetPosition(ListPageEdit);
                    //if (pos.Y < 0 || pos.Y > ListPageEdit.ActualHeight)
                    //{
                    //    MidLane.Visibility = Visibility.Collapsed;
                    //    return;
                    //}
                    //HitTestResult result = VisualTreeHelper.HitTest(PageEditListBox, pos);
                    //if (result == null)
                    //{
                    //    return;
                    //}
                    //var listBoxItem = CommonHelper.FindVisualParent<ListBoxItem>(result.VisualHit);
                    //if (listBoxItem == null)
                    //{
                    //    return;
                    //}
                    //isDragingEnter = false;
                    //tempItem = listBoxItem;
                    //var panel = GetPanel(tempItem);

                    //var item_pos = e.GetPosition(panel);
                    //if (item_pos != null)
                    //{
                    //    item_x = item_pos.X;
                    //    item_y = item_pos.Y;
                    //}
                    //var scroll = GetScrollHost(PageEditListBox);
                    //DataObject dataObj = new DataObject(listBoxItem.Content as StackPanel);
                    //DragDrop.DoDragDrop(PageEditListBox, dataObj, DragDropEffects.Move);
                    //Mouse.Capture(PageEditListBox);
                    //return;
                }
                RectChoose.Visibility = Visibility.Collapsed;
                startChoose = false;
                Mouse.Capture(null);
            }
            catch (Exception ex)
            {
               // MidLane.Visibility = Visibility.Collapsed;
            }
        }

        private void ListPageEdit_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var pos = e.GetPosition(ListPageEdit);
            HitTestResult result = VisualTreeHelper.HitTest(ListPageEdit, pos);
            if (result == null)
            {
                return;
            }
            //未选中item  并且不是点击滑轨时 开始框选
            var listBoxItem = CommonHelper.FindVisualParent<ListBoxItem>(result.VisualHit);
            var scroller = CommonHelper.FindVisualParent<ScrollBar>(result.VisualHit);
            if (listBoxItem == null)
            {
                if (scroller != null)
                {
                    startChoose = false;
                    return;
                }
                //点击空白处时开始框选
                startChoose = true;
                ListPageEdit.SelectedItems.Clear();
                starPosition = e.GetPosition(ListPageEdit);
                starPosition = new Point(starPosition.X, starPosition.Y + GetWrapPanel(ListPageEdit).VerticalOffset);
                Mouse.Capture(ListPageEdit);
                return;
            }
            startChoose = false;//选中了item 时，不能框选
        }

        private void ListPageEdit_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            startChoose = false;
            Mouse.Capture(null);
            RectChoose.Visibility = Visibility.Collapsed;
        }

        /// <summary>
        /// 获取Listobox的Wrappanel容器
        /// </summary>
        /// <param name="listBox"></param>
        /// <returns></returns>
        public VirtualizingWrapPanel GetWrapPanel(ListBox listBox)
        {
            Border border = VisualTreeHelper.GetChild(listBox, 0) as Border;
            var panel = CommonHelper.FindVisualChild<VirtualizingWrapPanel>(border);
            return panel;
        }

        /// <summary>
        ///根据鼠标拖选的框 选中里面的Item
        /// </summary>
        private void DoSelectItems()
        {
            var s = GetScrollHost(ListPageEdit);
            Point start = new Point();
            //通过 实时的垂直偏移量和第一次的偏移量抵消，来获取准确的垂直偏移值。
            start = new Point(starPosition.X, starPosition.Y - s.VerticalOffset);
            var rec = new Rect(start, Mouse.GetPosition(ListPageEdit));
            RectChoose.Margin = new Thickness(rec.Left, rec.Top, 0, 0);
            RectChoose.Width = rec.Width;
            RectChoose.Height = rec.Height;
            RectChoose.Visibility = Visibility.Visible;

            //检测遍历所有项,筛选在矩形框中的Item
            for (int i = 0; i < ListPageEdit.Items.Count; i++)
            {
                var _item = ListPageEdit.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem;
                //通过这一步来避免重复误选中
                var parent = CommonHelper.FindVisualParent<VirtualizingWrapPanel>(_item);
                if (parent == null)
                    continue;

                var v = VisualTreeHelper.GetOffset(_item);
                if (rec.IntersectsWith(new Rect(v.X, v.Y, _item.ActualWidth, _item.ActualHeight)))
                {
                    ListPageEdit.SelectedItems.Add(ListPageEdit.Items[i]);
                }
                else
                {
                    ListPageEdit.SelectedItems.Remove(ListPageEdit.Items[i]);
                }
            }
            return;
        }

    }
}
