using ComPDFKit.PDFDocument;
using ComPDFKit.PDFDocument.Action;
using ComPDFKit.PDFPage;
using ComPDFKitViewer.PdfViewer;
using PDF_Office.Model;
using PDF_Office.Model.BOTA;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace PDF_Office.ViewModels.BOTA
{
    class OutLineControlViewModel : BindableBase, INavigationAware
    {
        private string PageDefaultName = "";
        //缩略图相关全局变量，减少内存申请次数
        private WriteableBitmap WirteBitmap;
        private byte[] bmpData;

        private CPDFViewer PDFViewer;

        public ObservableCollection<OutlineNode> Outlinelist { get; set; }

        private bool isInsertHead = false;
        /// <summary>
        /// 是否为插入最顶部
        /// </summary>
        public bool IsInsertHead
        {
            get { return isInsertHead; }
            set
            {
                SetProperty(ref isInsertHead, value);
            }
        }

        private bool isOnDrop = false;

        public bool IsOnDrop
        {
            get { return isOnDrop; }
            set { isOnDrop = value; }
        }

        public DelegateCommand<ObservableCollection<OutlineNode>> CollapseAllCommand { get; set; }
        public DelegateCommand<ObservableCollection<OutlineNode>> ExpandAllCommand { get; set; }
        public DelegateCommand DeleteAllCommand { get; set; }
        public DelegateCommand<OutlineNode> DowngradeCommand { get; set; }

        public OutLineControlViewModel()
        {
            Outlinelist = new ObservableCollection<OutlineNode>();
            DeleteAllCommand = new DelegateCommand(DeleteAll);
            CollapseAllCommand = new DelegateCommand<ObservableCollection<OutlineNode>>(CollapseAll);
            ExpandAllCommand = new DelegateCommand<ObservableCollection<OutlineNode>>(ExpandAll);
        }

        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return true;
        }

        public void OnNavigatedFrom(NavigationContext navigationContext)
        {
            return;
        }

        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            navigationContext.Parameters.TryGetValue<CPDFViewer>(ParameterNames.PDFViewer, out PDFViewer);
            if (PDFViewer == null)
            {
                return;
            }
            List<CPDFOutline> datasource = PDFViewer.Document.GetOutlineList();
            Outlinelist.Clear();
            foreach (CPDFOutline item in datasource)
            {
                OutlineNode dto = ConvertCPDFToOutlineNode(item, null, false);
                if (dto != null)
                {
                    Outlinelist.Add(dto);
                }
            }
            PDFViewer.GetCreateOutLineInfo();
        }

        /// <summary>
        /// 更新大纲数据，并保存状态设置为true
        /// </summary>
        public void Updata(bool IsMoveData)
        {
            PDFViewer.Document.ReleaseOutlineList();
            ObservableCollection<OutlineNode> list = new ObservableCollection<OutlineNode>();
            List<CPDFOutline> datasource = PDFViewer.Document.GetOutlineList();

            //遍历，转换UI状态存入临时数组
            foreach (CPDFOutline item in datasource)
            {
                OutlineNode dto = ConvertCPDFToOutlineNode(item, null, IsMoveData);
                if (dto != null)
                {
                    list.Add(dto);
                }
            }

            //清空绑定数组，并填充新数据
            Outlinelist.Clear();
            foreach (OutlineNode item in list)
            {
                Outlinelist.Add(item);
            }

            PDFViewer.UndoManager.CanSave = true;
        }

        /// <summary>
        /// 设置当前大纲对象的Title
        /// </summary>
        public bool SetTitle(CPDFOutline cPDFOutline, string Title)
        {
            if (cPDFOutline == null)
            {
                return false;
            }
            return cPDFOutline.SetTitle(Title);
        }

        /// <summary>
        /// 跳转到指定位置或者URL动作
        /// </summary>
        public void GoToPage(TreeViewItem treeViewItem)
        {
            OutlineNode outline = treeViewItem.DataContext as OutlineNode;
            if (outline == null)
            {
                return;
            }
            CPDFAction action = outline.Outline.GetAction();
            if (action != null && action.ActionType != C_ACTION_TYPE.ACTION_TYPE_UNKNOWN)
            {
                PDFViewer.ProcessAction(action);
            }
            else
            {
                Size size = PDFViewer.Document.GetPageSize(Convert.ToInt32(outline.PageIndex) - 1);
                PDFViewer.GoToPage(Convert.ToInt32(outline.PageIndex) - 1, new Point(size.Width - outline.PositionX, size.Height - outline.PositionY));
            }
        }

        /// <summary>
        /// 收起所有展开
        /// </summary>
        public void CollapseAll(ObservableCollection<OutlineNode> outlineNodes)
        {
            foreach (var item in outlineNodes)
            {
                item.IsExpanded = false;
                if (item.Chlidlist.Count > 0)
                {
                    CollapseAll(item.Chlidlist);
                }
            }
        }

        /// <summary>
        /// 展开所有大纲
        /// </summary>
        public void ExpandAll(ObservableCollection<OutlineNode> outlineNodes)
        {
            foreach (var item in outlineNodes)
            {
                item.IsExpanded = true;
                if (item.Chlidlist.Count > 0)
                {
                    ExpandAll(item.Chlidlist);
                }
            }
        }

        /// <summary>
        /// 更改目标位置
        /// </summary>
        public void ChangeOutLineDestination(OutlineNode outline)
        {
            List<TextSelectNode> textSelectNodes = PDFViewer.GetCreateOutLineInfo();
            CPDFDestination info = new CPDFDestination();
            info.PageIndex = textSelectNodes[0].PageIndex;
            Size size = PDFViewer.Document.GetPageSize(textSelectNodes[0].PageIndex);
            info.Position_X = (float)(size.Width - textSelectNodes[0].StartPoint.X);
            info.Position_Y = (float)(size.Height - textSelectNodes[0].StartPoint.Y);
            outline.Outline.SetDestination(PDFViewer.Document, info);
            Updata(false);
        }

        /// <summary>
        /// 添加大纲
        /// </summary>
        public int AddOutLine(OutlineNode outline)
        {
            int ItemIndex = 0;
            List<TextSelectNode> textSelectNodes = PDFViewer.GetCreateOutLineInfo();
            CPDFDestination info = new CPDFDestination();
            if (textSelectNodes.Count <= 0)
            {
                //SDK出错了
                return -1;
            }
            info.PageIndex = textSelectNodes[0].PageIndex;
            Size size = PDFViewer.Document.GetPageSize(info.PageIndex);
            info.Position_X = (float)(size.Width - textSelectNodes[0].StartPoint.X);
            info.Position_Y = (float)(size.Height - textSelectNodes[0].StartPoint.Y);
            CPDFOutline dto = null;
            //当前有选中大纲列表
            if (outline != null)
            {
                CPDFOutline parentoutline = outline.Outline.GetParent();
                if (parentoutline == null)
                {
                    //获取父级失败，直接添加在根节点最下方
                    PDFViewer.Document.GetOutlineList();
                    CPDFOutline parent = PDFViewer.Document.GetOutlineRoot();
                    if (!parent.InsertChildAtIndex(PDFViewer.Document, parent.ChildList.Count, ref dto))
                    {
                        //SDK出错了
                        return -1;
                    }
                    ItemIndex = parent.ChildList.Count;
                }
                else
                {
                    //获取父节点成功，添加在父节点中选中项下方
                    int index = GetOutlinesIndexFormParent(parentoutline, outline.Outline);
                    parentoutline.InsertChildAtIndex(PDFViewer.Document, index, ref dto);
                    ItemIndex = index + 1;
                }
            }
            else
            {
                //未选中数据，直接添加在根节点最下方
                PDFViewer.Document.GetOutlineList();
                CPDFOutline parent = PDFViewer.Document.GetOutlineRoot();
                if (!parent.InsertChildAtIndex(PDFViewer.Document, parent.ChildList.Count, ref dto))
                {
                    //SDK出错了
                    return -1;
                }
                ItemIndex = parent.ChildList.Count;
            }
            ///当前没有选中文字
            if (string.IsNullOrEmpty(textSelectNodes[0].SelectText))
            {
                string addPageName = PageDefaultName + (textSelectNodes[0].PageIndex + 1).ToString();
                if (!dto.SetTitle(addPageName))
                {
                    //SDK出错了
                    return -1;
                }
            }
            else
            {
                string addPageName = PageDefaultName + textSelectNodes[0].SelectText;
                if (!dto.SetTitle(addPageName))
                {
                    //SDK出错了
                    return -1;
                }
            }

            dto.SetDestination(PDFViewer.Document, info);
            Updata(false);
            return ItemIndex;
        }

        /// <summary>
        /// 添加大纲到子节点的最后一位
        /// </summary>
        public int InsertParentOutline(OutlineNode outline)
        {
            int ItemIndex = 0;

            List<TextSelectNode> textSelectNodes = PDFViewer.GetCreateOutLineInfo();
            CPDFDestination info = new CPDFDestination();
            if (textSelectNodes.Count <= 0)
            {
                //SDK出错了
                return -1;
            }
            info.PageIndex = textSelectNodes[0].PageIndex;
            info.Position_X = (float)textSelectNodes[0].StartPoint.X;
            info.Position_Y = (float)textSelectNodes[0].StartPoint.Y;

            CPDFOutline dto = null;
            CPDFOutline parent = outline.Outline.GetParent();
            if (parent != null)
            {
                CPDFOutline trueparent = parent.GetParent();
                if (trueparent != null)
                {
                    ItemIndex = GetOutlinesIndexFormParent(trueparent, parent);
                    if (!trueparent.InsertChildAtIndex(PDFViewer.Document, ItemIndex, ref dto))
                    {
                        return -1;
                    }
                    ItemIndex = ItemIndex + 1;
                }
            }
            ///当前没有选中文字
            if (string.IsNullOrEmpty(textSelectNodes[0].SelectText))
            {
                string addPageName = PageDefaultName + (textSelectNodes[0].PageIndex + 1).ToString();
                if (!dto.SetTitle(addPageName))
                {
                    //SDK出错了
                    return -1;
                }
            }
            else
            {
                string addPageName = PageDefaultName + textSelectNodes[0].SelectText;
                if (!dto.SetTitle(addPageName))
                {
                    //SDK出错了
                    return -1;
                }
            }

            dto.SetDestination(PDFViewer.Document, info);
            Updata(false);
            return ItemIndex;
        }

        /// <summary>
        /// 添加大纲到父节点的下一位
        /// </summary>
        public int InsertChlidOutline(OutlineNode outline)
        {
            int ItemIndex = 0;
            if (outline == null)
            {
                return -1;
            }
            if (outline.Outline.ChildList != null)
            {
                ItemIndex = outline.Outline.ChildList.Count;
            }

            List<TextSelectNode> textSelectNodes = PDFViewer.GetCreateOutLineInfo();
            CPDFDestination info = new CPDFDestination();
            if (textSelectNodes.Count <= 0)
            {
                //SDK出错了
                return -1;
            }
            info.PageIndex = textSelectNodes[0].PageIndex;
            info.Position_X = (float)textSelectNodes[0].StartPoint.X;
            info.Position_Y = (float)textSelectNodes[0].StartPoint.Y;
            CPDFOutline dto = null;
            if (!outline.Outline.InsertChildAtIndex(PDFViewer.Document, ItemIndex, ref dto))
            {
                return -1;
            }
            ///当前没有选中文字
            if (string.IsNullOrEmpty(textSelectNodes[0].SelectText))
            {
                string addPageName = PageDefaultName + (textSelectNodes[0].PageIndex + 1).ToString();
                if (!dto.SetTitle(addPageName))
                {
                    //SDK出错了
                    return -1;
                }
            }
            else
            {
                string addPageName = PageDefaultName + textSelectNodes[0].SelectText;
                if (!dto.SetTitle(addPageName))
                {
                    //SDK出错了
                    return -1;
                }
            }

            dto.SetDestination(PDFViewer.Document, info);
            Updata(false);
            return ItemIndex;
        }


        /// <summary>
        /// 删除所有大纲
        /// </summary>
        public void DeleteAll()
        {
            foreach (var item in Outlinelist)
            {
                item.Outline.RemoveFromParent(this.PDFViewer.Document);
            }
            Updata(false);
        }

        /// <summary>
        /// 升级当前大纲
        /// </summary>
        public void Downgrade(OutlineNode outline)
        {
            if (outline != null)
            {
                CPDFOutline parent = outline.Outline.GetParent();
                int index = GetOutlinesIndexFormParent(parent, outline.Outline);
                CPDFOutline newparent = parent.ChildList[index - 2];
                int insertindex = newparent.ChildList.Count;
                newparent.MoveChildAtIndex(PDFViewer.Document, outline.Outline, insertindex);
                Updata(false);
            }
        }

        /// <summary>
        /// 降级当前大纲
        /// </summary>
        public void Upgrade(OutlineNode outline)
        {
            if (outline != null)
            {
                CPDFOutline parent = outline.Outline.GetParent();
                CPDFOutline newparent = parent.GetParent();
                int index = GetOutlinesIndexFormParent(parent.GetParent(), parent);
                newparent.MoveChildAtIndex(PDFViewer.Document, outline.Outline, index);
                Updata(false);
            }
        }

        /// <summary>
        /// 删除当前大纲
        /// </summary>
        public void RemoveOutline(OutlineNode outline)
        {
            outline.Outline.RemoveFromParent(PDFViewer.Document);
            Updata(false);
        }

        /// <summary>
        /// 移动大纲到目标节点
        /// </summary>
        /// <param name="target">目标节点</param>
        /// <param name="soure">需要插入的数据</param>
        /// <returns></returns>
        public bool MoveOutLine(OutlineNode target, OutlineNode soure)
        {
            bool Tag = true;
            if (IsInsertHead)
            {
                CPDFOutline root = PDFViewer.Document.GetOutlineRoot();
                if (root != null)
                {
                    Tag = root.MoveChildAtIndex(PDFViewer.Document, soure.Outline, 0);
                }
            }
            else
            {
                if (target.IsInsertNextLayer)
                {
                    target.IsExpanded = true;
                    Tag = target.Outline.MoveChildAtIndex(PDFViewer.Document, soure.Outline, target.Outline.ChildList.Count);
                }
                else
                {
                    CPDFOutline parent = target.Outline.GetParent();
                    if (parent != null && parent.ChildList.Count > 0)
                    {
                        int index = parent.ChildList.IndexOf(target.Outline);
                        int sourceindex = parent.ChildList.IndexOf(soure.Outline);
                        //源数据不在目标节点树中的情况
                        if (sourceindex == -1)
                        {
                            Tag = parent.MoveChildAtIndex(PDFViewer.Document, soure.Outline, index + 1);
                        }
                        //分向上和向下移动
                        else if (sourceindex > index)
                        {
                            Tag = parent.MoveChildAtIndex(PDFViewer.Document, soure.Outline, index + 1);
                        }
                        else
                        {
                            Tag = parent.MoveChildAtIndex(PDFViewer.Document, soure.Outline, index);
                        }
                    }
                }
            }
            return Tag;
        }

        /// <summary>
        /// 获取对应大纲所需的缩略图数据
        /// </summary>
        public WriteableBitmap LoadPreview(OutlineNode outlineNode)
        {
            CPDFPage page = PDFViewer.Document.PageAtIndex(Convert.ToInt32(outlineNode.PageIndex) - 1);
            Size size = PDFViewer.Document.GetPageSize(Convert.ToInt32(outlineNode.PageIndex) - 1);
            Point zoomXY = new Point(outlineNode.PositionX * outlineNode.Zoom, outlineNode.PositionY * outlineNode.Zoom);
            //数据校验，暂不确定SDK会不会给垃圾值。说是从底层返回的。
            if (zoomXY.X > size.Width || zoomXY.X < 0)
            {
                zoomXY.X = 0;
            }
            if (zoomXY.Y > size.Height || zoomXY.Y < 0)
            {
                zoomXY.Y = 0;
            }
            Size zoomSize = new Size((int)(size.Width * outlineNode.Zoom), (int)(size.Height * outlineNode.Zoom));
            bmpData = new byte[(int)(zoomSize.Width * zoomSize.Height * 4)];
            WirteBitmap = new WriteableBitmap((int)zoomSize.Width, (int)zoomSize.Height, 96, 96, PixelFormats.Bgra32, null);

            if (!page.IsValid())
            {
                return null;
            }
            page.RenderPageBitmapWithMatrix((float)outlineNode.Zoom, new Rect(zoomXY.X, zoomXY.Y, zoomSize.Width, zoomSize.Height), 0xFFFFFFFF, bmpData, 1, true);
            WirteBitmap.WritePixels(new Int32Rect(0, 0, (int)zoomSize.Width, (int)zoomSize.Height), bmpData, WirteBitmap.BackBufferStride, 0);
            WirteBitmap.Freeze();
            return WirteBitmap;
        }

        /// <summary>
        /// 将PDF对象转换为自定义数据类型，并存储
        /// </summary>
        private OutlineNode ConvertCPDFToOutlineNode(CPDFOutline outline, OutlineNode parent, bool IsMoveData)
        {
            OutlineNode node = new OutlineNode();
            if (outline != null)
            {
                node.IsInsertNextLayer = false;
                node.IsInsertCurrentLayer = false;
                node.IsExpanded = false;
                node.IsSelected = false;
                node.Outline = outline;
                node.CanUp = outline.Level == 0 ? false : true;
                node.CanAddParent = outline.Level == 0 ? false : true;
                CPDFAction action = outline.GetAction();
                if (action != null)
                {
                    if (action.ActionType != C_ACTION_TYPE.ACTION_TYPE_URI)
                    {
                        CPDFDestination cPDFDestination = outline.GetDestination(PDFViewer.Document);
                        if (cPDFDestination != null)
                        {
                            //存储大纲相关属性
                            node.PageIndex = (cPDFDestination.PageIndex + 1).ToString();
                            node.PositionX = cPDFDestination.Position_X;
                            node.PositionY = cPDFDestination.Position_Y;
                            if (cPDFDestination.Zoom <= 0)
                            {
                                node.Zoom = 1;
                            }
                            else
                            {
                                node.Zoom = cPDFDestination.Zoom;
                            }
                        }
                        else
                        {
                            node.PageIndex = "";
                            node.PositionX = 0;
                            node.PositionY = 0;
                            node.Zoom = 1;
                        }
                    }
                    else
                    {
                        node.PageIndex = "";
                        node.PositionX = 0;
                        node.PositionY = 0;
                        node.Zoom = 1;
                    }

                }
                else
                {
                    node.PageIndex = "";
                    node.PositionX = 0;
                    node.PositionY = 0;
                    node.Zoom = 1;
                }

                if (parent != null)
                {
                    node.Parent = parent;
                }
                if (Outlinelist != null && Outlinelist.Count > 0)
                {
                    OutlineNode oldnode = FindOutlineFromDto(Outlinelist, node.Outline, IsMoveData);
                    if (oldnode != null)
                    {
                        node.IsExpanded = oldnode.IsExpanded;
                        node.IsSelected = oldnode.IsSelected;
                    }
                }
                node.Chlidlist = new ObservableCollection<OutlineNode>();
                if (outline.ChildList.Count > 0)
                {
                    foreach (CPDFOutline item in outline.ChildList)
                    {
                        node.Chlidlist.Add(ConvertCPDFToOutlineNode(item, node, IsMoveData));
                    }
                }
                else
                {
                    node.CanDown = false;
                }
            }
            return node;
        }

        /// <summary>
        /// 从当前列表中找到和SDK大纲对象相同的数据
        /// </summary>
        public OutlineNode FindOutlineFromDto(ObservableCollection<OutlineNode> list, CPDFOutline outline, bool IsMoveData)
        {
            foreach (OutlineNode item in list)
            {
                CPDFOutline parent = outline.GetParent();
                CPDFOutline PARENT = item.Outline.GetParent();

                int i = GetIndexFromParent(parent.ChildList, outline);
                int I = GetIndexFromParent(PARENT.ChildList, item.Outline);
                if (IsMoveData)
                {
                    if (item.Outline.Title == outline.Title)
                    {
                        return item;
                    }
                    else if (item.Chlidlist.Count > 0)
                    {
                        OutlineNode retdto = FindOutlineFromDto(item.Chlidlist, outline, IsMoveData);
                        if (retdto != null)
                        {
                            return retdto;
                        }
                    }
                }
                else
                {
                    if (item.Outline.Title == outline.Title && i == I && outline.Level == item.Outline.Level && ((parent.Title == PARENT.Title) || (parent.Title == null && PARENT.Title == null)))
                    {
                        return item;
                    }
                    else if (item.Chlidlist.Count > 0)
                    {
                        OutlineNode retdto = FindOutlineFromDto(item.Chlidlist, outline, IsMoveData);
                        if (retdto != null)
                        {
                            return retdto;
                        }
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// 从当前列表中找到对应的OutlineNode对象
        /// </summary>
        public OutlineNode FindOutlineFromList(ObservableCollection<OutlineNode> list, OutlineNode outline, int outlineindex)
        {
            //如果传入比对数据为null，则返回最后一项
            if (outline == null)
            {
                return list.Last();
            }
            int index = list.IndexOf(outline);
            if (index >= 0)
            {
                if (outlineindex <= index)
                {
                    return list[index];
                }
                else
                {
                    return list[outlineindex - 1];
                }
            }
            else
            {
                foreach (var item in list)
                {
                    OutlineNode node = FindOutlineFromList(item.Chlidlist, outline, outlineindex);
                    if (node != null)
                    {
                        return node;
                    }
                }
            }
            return null;
        }

        private int GetIndexFromParent(List<CPDFOutline> parentlist, CPDFOutline outline)
        {
            for (int i = 0; i < parentlist.Count; i++)
            {
                if (parentlist[i] == outline)
                {
                    return i;
                }
            }
            return -1;
        }

        private int GetOutlinesIndexFormParent(CPDFOutline parentoutline, CPDFOutline outline)
        {
            if (parentoutline != null)
            {
                if (parentoutline.ChildList.Count > 0)
                {
                    for (int i = 0; i < parentoutline.ChildList.Count; i++)
                    {
                        if (parentoutline.ChildList[i] == outline)
                        {
                            return i + 1;
                        }
                    }
                }
                return parentoutline.ChildList.Count;
            }
            return 0;
        }
    }
}
