using ComPDFKit.Import;
using ComPDFKit.PDFAnnotation;
using ComPDFKit.PDFPage;
using ComPDFKitViewer;
using ComPDFKitViewer.AnnotEvent;
using ComPDFKitViewer.PdfViewer;
using PDF_Master.CustomControl;
using PDF_Master.EventAggregators;
using PDF_Master.Model;
using PDF_Master.Properties;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using Prism.Regions;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace PDF_Master.ViewModels.EditTools.Redaction
{
    public class RedactionContentViewModel : BindableBase, INavigationAware
    {
        public IEventAggregator eventAggregator;

        public IRegionManager redactionRegion;

        public IDialogService dialogs;

        private CPDFViewer PDFViewer;

        private ViewContentViewModel viewContentViewModel;

        private RedactionAnnotArgs redactionArgs = new RedactionAnnotArgs();

        public string RedactionDocumentRegionName { get; set; }
        public string RedactionBottomBarRegionName { get; set; }

        public string RedactionDocumentName = "RedactionDocumentContent";

        public string Unicode = null;

        public DelegateCommand CloseEditToolCommand { get; set; }

        public DelegateCommand<string> ApplyCommmand { get; set; }

        public DelegateCommand PageRedactionCommand { get; set; }

        public DelegateCommand<string> EraseCommand { get; set; }

        public RedactionCommandEventArgs TempArgs { get; set; }

        private int currentPage = 0;

        /// <summary>
        /// 是否因为本身传递值  防止循环调用
        /// </summary>
        private bool isFromSelf = false;

        public int CurrentPage
        {
            get { return currentPage; }
            set
            {
                SetProperty(ref currentPage, value);
                if (value >= 1 && value <= PDFViewer.Document.PageCount && !isFromSelf)
                {
                    PDFViewer.GoToPage(value - 1);
                }
            }
        }

        private int pageCount = 0;

        public int PageCount
        {
            get { return pageCount; }
            set
            {
                SetProperty(ref pageCount, value);
            }
        }

        private bool isEnable = false; 

        /// <summary>
        /// 按钮是否启用
        /// </summary>
        public bool IsEnable
        {
            get { return isEnable; }
            set
            {
                SetProperty(ref isEnable, value);
            }
        }



        public RedactionContentViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, IDialogService dialogService)
        {
            this.redactionRegion = regionManager;
            this.eventAggregator = eventAggregator;
            this.dialogs = dialogService;

            RedactionDocumentRegionName = Guid.NewGuid().ToString();
            Unicode = App.mainWindowViewModel.SelectedItem.Unicode;
            CloseEditToolCommand = new DelegateCommand(CloseEditTool);
            ApplyCommmand = new DelegateCommand<string>(apply,CanExcute).ObservesProperty(() => IsEnable);
            EraseCommand = new DelegateCommand<string>(erase, CanExcute).ObservesProperty(() => IsEnable);
            PageRedactionCommand = new DelegateCommand(pageMark);

            eventAggregator.GetEvent<RedactionCommandEvent>().Subscribe(SetContextMenu, e => e.UniCode == Unicode);
        }

        private void SetContextMenu(RedactionCommandEventArgs obj)
        {
            var contextmenu = App.Current.FindResource("RedactionContextMenu") as ContextMenu;
            obj.args.PopupMenu = contextmenu;
            TempArgs = obj;
            for(int i=0;i<contextmenu.Items.Count;i++)
            {
                if(contextmenu.Items[i] is MenuItem) 
                {
                    var item = contextmenu.Items[i] as MenuItem;
                    switch (item.Name)
                    {
                        case "MenuDelete":
                            item.Command = ApplicationCommands.Delete;
                            item.CommandParameter = (UIElement)obj.Sender;
                            break;
                        case "MenuSetDeufalt":
                            item.Command = new DelegateCommand<RedactionCommandEventArgs>(SetDefualtProperty);
                            item.CommandParameter = obj;
                            break;
                        case "MenuProperties":
                            item.Command = new DelegateCommand<RedactionCommandEventArgs>(ShowProperty);
                            item.CommandParameter = obj;
                            break;
                        case "MenuRepeat":
                            item.Command = new DelegateCommand<RedactionCommandEventArgs>(RepreatMark);
                            item.CommandParameter = obj;
                            break;
                        case "MenuApply":
                            item.Command = this.ApplyCommmand;
                            item.CommandParameter = "Single";
                            break;
                        case "MenuErase":
                            item.Command = this.EraseCommand;
                            item.CommandParameter = "Single";
                            break;
                        default:
                            break;
                    }

                }
            }
        }

        /// <summary>
        /// 设置当前为默认属性
        /// </summary>
        /// <param name="args"></param>
        private void SetDefualtProperty(RedactionCommandEventArgs args)
        {
            var annoteargs = args.args.AnnotEventArgsList[0] as RedactionAnnotArgs;
            DialogParameters keyValues = new DialogParameters();
            keyValues.Add(ParameterNames.DataModel,args.args.AnnotEventArgsList[0] as RedactionAnnotArgs);

            Settings.Default.RedactionsSettings.SetDefualtValue(
                annoteargs.Content,
                annoteargs.LineColor,
                annoteargs.BgColor,
                annoteargs.FontColor, 
                (int)annoteargs.FontSize,
                string.IsNullOrEmpty(annoteargs.Content) ? false : true,
                annoteargs.Align, 
                annoteargs.FontName,
                annoteargs.FontWeight);

            PDFViewer.SetMouseMode(MouseModes.AnnotCreate);
            PDFViewer.SetToolParam(annoteargs);
        }

        /// <summary>
        /// 显示属性弹窗
        /// </summary>
        /// <param name="args"></param>
        private void ShowProperty(RedactionCommandEventArgs args)
        {
            DialogParameters keyValues = new DialogParameters();
            keyValues.Add(ParameterNames.DataModel, args.args.AnnotEventArgsList[0] as RedactionAnnotArgs);
            dialogs.ShowDialog(DialogNames.MarkSettingDialog,keyValues,null);
        }

        /// <summary>
        /// 显示跨页标记弹窗
        /// </summary>
        /// <param name="args"></param>
        private void RepreatMark(RedactionCommandEventArgs args)
        {
            DialogParameters keyValues = new DialogParameters();
            keyValues.Add(ParameterNames.PageCount,PDFViewer.Document.PageCount);
            dialogs.ShowDialog(DialogNames.RepeatMarkDialog, keyValues, e=> {
                if (e.Result == ButtonResult.OK)
                {
                    PDFViewer.AddRedaction(e.Parameters.GetValue<List<int>>(ParameterNames.PageList), args.args);
                }
            });
        }
        /// <summary>
        /// 应用
        /// </summary>
        private void apply(string type)
        {
            AlertsMessage alertsMessage = new AlertsMessage();
            alertsMessage.ShowDialog("Apply Redactions", "Use blank blocks to remove selected sensitive content." +

"This action will permanently delete the marked ciphertext information from this document and you will not be able to retrieve the marked ciphertext information.", "Cancel", "Apply & Save As");
            if (alertsMessage.result == ContentResult.Ok)
            {
                if (!string.IsNullOrEmpty(type) && type == "All")
                {
                    viewContentViewModel.saveAsFile(applyAll);
                }
                else
                {
                    viewContentViewModel.saveAsFile(applySingle);
                }
            }
        }



        /// <summary>
        /// 擦除
        /// </summary>
        private void erase(string type)
        {
            AlertsMessage alertsMessage = new AlertsMessage();
            alertsMessage.ShowDialog("","Replace selected sensitive content with color blocks."+

"This action will permanently delete the marked ciphertext information from this document and you will not be able to retrieve the marked ciphertext information.", "Cancel", "Apply & Save As");
            if (alertsMessage.result == ContentResult.Ok)
            {
                if (!string.IsNullOrEmpty(type) && type == "All")
                {
                    viewContentViewModel.saveAsFile(eraseAll);
                }
                else
                {
                    viewContentViewModel.saveAsFile(eraseSingle);
                }
            }
        }

        /// <summary>
        /// 应用所有密文块
        /// </summary>
        private void applyAll()
        {
            PDFViewer.Document.ApplyRedaction();
            PDFViewer.Document.ReleasePages();
            PDFViewer.ReloadDocument();
        }


        /// <summary>
        /// 擦除所有密文块
        /// </summary>
        private void eraseAll()
        {
            for (int i = 0; i < PDFViewer.Document.PageCount; i++)
            {
                //获取页面Page对象
                var page = PDFViewer.Document.PageAtIndex(i);
                var annots = PDFViewer.GetAnnotCommentList(i, PDFViewer.Document);
                //循环擦除当前页的标记密文
                for (int j = 0; j < annots.Count; j++)
                {
                    if (annots[j].EventType == AnnotArgsType.AnnotRedaction)
                    {
                        foreach (var rect in (annots[j] as RedactionAnnotArgs).QuardRects)
                        {
                            page.ErasureRedaction(rect);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 应用选中的密文块
        /// </summary>
        private void applySingle()
        {
            AnnotCommandArgs annotCommand =TempArgs.args;
            if (annotCommand != null)
            {
                List<RedactionAnnotArgs> redactionList = new List<RedactionAnnotArgs>();
                foreach (AnnotHandlerEventArgs annotArgs in annotCommand.AnnotEventArgsList)
                {
                    if (annotArgs.EventType == AnnotArgsType.AnnotRedaction)
                    {
                        redactionList.Add((RedactionAnnotArgs)annotArgs);
                    }
                }
                PDFViewer.ApplyRedaction(redactionList);
            }
        }

        /// <summary>
        /// 擦除选中的密文块
        /// </summary>
        private void eraseSingle()
        {
            AnnotCommandArgs annotCommand = TempArgs.args;
            if (annotCommand != null)
            {
                List<RedactionAnnotArgs> redactionList = new List<RedactionAnnotArgs>();
                foreach (AnnotHandlerEventArgs annotArgs in annotCommand.AnnotEventArgsList)
                {
                    if (annotArgs.EventType == AnnotArgsType.AnnotRedaction)
                    {
                        foreach (var rect in (annotArgs as RedactionAnnotArgs).QuardRects)
                        {
                            var page = PDFViewer.Document.PageAtIndex((annotArgs as RedactionAnnotArgs).PageIndex);
                            page.ErasureRedaction(rect);
                        }
                    }
                }
            }
        }

        private bool CanExcute(string type)
        {
            return IsEnable;
        }

        private void pageMark()
        {
            DialogParameters valuePairs = new DialogParameters();
            valuePairs.Add(ParameterNames.PageCount,PDFViewer.Document.PageCount);
            valuePairs.Add(ParameterNames.CurrentPageIndex,PDFViewer.CurrentIndex);
            dialogs.ShowDialog(DialogNames.PageMarkDialog,valuePairs,e=> { 
                if(e.Result == ButtonResult.OK)
                {
                    var pagelist = e.Parameters.GetValue<List<int>>(ParameterNames.PageList);
                    addMarkToPages(pagelist);
                }
            });
        }

        private void addMarkToPages(List<int> list)
        {
            foreach (var page in list)
            {

                //根据页面大小,创建标记密文注释
                CPDFPage docPage = PDFViewer.Document.PageAtIndex(page);

                CPDFRedactAnnotation redactionAnnot = docPage.CreateAnnot(C_ANNOTATION_TYPE.C_ANNOTATION_REDACT) as CPDFRedactAnnotation;
                if (redactionAnnot == null)
                {
                    //TODO 操作失败
                    return;
                }

                redactionAnnot.SetQuardRects(new List<CRect>() { new CRect(0, (float)docPage.PageSize.Height, (float)docPage.PageSize.Width,0)});

                if (redactionArgs == null)
                    return;

                byte[] lineColor = { redactionArgs.LineColor.R, redactionArgs.LineColor.G, redactionArgs.LineColor.B };
                redactionAnnot.SetOutlineColor(lineColor);

                if (redactionArgs.BgColor != Colors.Transparent)
                {
                    byte[] bgColor = { redactionArgs.BgColor.R, redactionArgs.BgColor.G, redactionArgs.BgColor.B };
                    redactionAnnot.SetFillColor(bgColor);
                }
                else
                {
                    // redactionAnnot.ClearBgColor();
                }

                CTextAttribute textAttr = new CTextAttribute();
                byte[] fontColor = { redactionArgs.FontColor.R, redactionArgs.FontColor.G, redactionArgs.FontColor.B };
                textAttr.FontColor = fontColor;
                textAttr.FontSize = (float)redactionArgs.FontSize;
                redactionAnnot.SetTextAttribute(textAttr);
                switch (redactionArgs.Align)
                {
                    case TextAlignment.Left:
                        redactionAnnot.SetTextAlignment(C_TEXT_ALIGNMENT.ALIGNMENT_LEFT);
                        break;
                    case TextAlignment.Center:
                        redactionAnnot.SetTextAlignment(C_TEXT_ALIGNMENT.ALIGNMENT_CENTER);
                        break;
                    case TextAlignment.Right:
                        redactionAnnot.SetTextAlignment(C_TEXT_ALIGNMENT.ALIGNMENT_RIGHT);
                        break;
                    default:
                        redactionAnnot.SetTextAlignment(C_TEXT_ALIGNMENT.ALIGNMENT_LEFT);
                        break;
                }

                //byte transparency = (byte)Math.Round(redactionArgs.Transparency * 255);
                //redactionAnnot.SetTransparency(transparency);
                redactionAnnot.SetBorderWidth(1);
                //redactionAnnot.SetRect(new CRect(Left, Bottom, Right, Top));

                //redactionAnnot.SetCreationDate(Helpers.GetCurrentPdfTime());
                if (string.IsNullOrEmpty(Settings.Default.AppProperties.Description.Author))
                {
                    redactionAnnot.SetAuthor(Settings.Default.AppProperties.Description.Author);
                }

                if (redactionArgs.Content != null && redactionArgs.Content != string.Empty)
                {
                    redactionAnnot.SetOverlayText(redactionArgs.Content);
                }

                if (redactionAnnot.GetIsLocked() != redactionArgs.Locked)
                {
                    redactionAnnot.SetIsLocked(redactionArgs.Locked);
                }

                redactionAnnot.UpdateAp();
                redactionAnnot.ReleaseAnnot();
            }
        }



        public void CloseEditTool()
        {
            bool isClose = true;
            if (CheckHasRedactionAnnote())
            {
                AlertsMessage alertsMessage = new AlertsMessage();
                alertsMessage.ShowDialog("", "There are unapplied redactions in this file. Exit will not save redaction.", "Cancel", "Exit");
                if (alertsMessage.result != ContentResult.Ok)
                {
                    isClose = false;
                }
            }

            if(isClose)
            {
                PDFViewer.SetMouseMode(MouseModes.PanTool);
                redactionRegion.Regions[RegionNames.ViwerRegionName].Remove(PDFViewer);
                redactionRegion.Regions[RedactionDocumentRegionName].Remove(PDFViewer);
                this.eventAggregator.GetEvent<CloseEditToolEvent>().Publish(new EnumCloseModeUnicode { Unicode = this.Unicode, Status = EnumCloseMode.StatusCancel });
                App.mainWindowViewModel.SelectedItem.IsInReadctonMode = false;
            }
        }

        /// <summary>
        /// 检查是否有未应用的标记密文
        /// </summary>
        private bool CheckHasRedactionAnnote()
        {
            for (int i = 0; i < PDFViewer.Document.PageCount; i++)
            {
                var items = PDFViewer.GetAnnotCommentList(i, PDFViewer.Document);
                for (int j = 0; j < items.Count; j++)
                {
                    if (items[j].EventType == AnnotArgsType.AnnotRedaction)
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        #region Navigation

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

        public void OnNavigatedFrom(NavigationContext navigationContext)
        {
        }

        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            App.mainWindowViewModel.SelectedItem.IsInReadctonMode = true;
            navigationContext.Parameters.TryGetValue<CPDFViewer>(ParameterNames.PDFViewer, out PDFViewer);
            navigationContext.Parameters.TryGetValue<ViewContentViewModel>(ParameterNames.ViewContentViewModel, out viewContentViewModel);
            PDFViewer.InfoChanged -= PDFViewer_InfoChanged;
            PDFViewer.InfoChanged += PDFViewer_InfoChanged;
            PDFViewer.AnnotEditHandler -= PDFViewer_AnnotEditHandler;
            PDFViewer.AnnotEditHandler += PDFViewer_AnnotEditHandler;
            CurrentPage = PDFViewer.CurrentIndex + 1;
            PageCount = PDFViewer.Document.PageCount;
            if (!redactionRegion.Regions[RedactionDocumentRegionName].Views.Contains(PDFViewer))
            {
                redactionArgs = new RedactionAnnotArgs();
                AnnotHandlerEventArgs annotArgs = null;
                redactionArgs.LineColor = Settings.Default.RedactionsSettings.LineColor;
                redactionArgs.BgColor = Settings.Default.RedactionsSettings.BgColor;
                redactionArgs.FontColor = Settings.Default.RedactionsSettings.FontColor;
                redactionArgs.Align = Settings.Default.RedactionsSettings.Align;
                redactionArgs.FontSize = Settings.Default.RedactionsSettings.FontSize;
                redactionArgs.Content = Settings.Default.RedactionsSettings.Content;
                if (!Settings.Default.RedactionsSettings.isUseText)
                {
                    redactionArgs.Content = "";
                }
                annotArgs = redactionArgs;
                if (annotArgs != null)
                {
                    //设置注释作者
                    annotArgs.Author = Settings.Default.AppProperties.Description.Author;
                    PDFViewer.SetMouseMode(MouseModes.AnnotCreate);
                    PDFViewer.SetToolParam(annotArgs);
                }
                redactionRegion.AddToRegion(RedactionDocumentRegionName, PDFViewer);
            }
  
        }

        private void PDFViewer_AnnotEditHandler(object sender, List<AnnotEditEvent> e)
        {
            //添加注释后检测是否有未应用的标记密文注释
            IsEnable = false;
            for(int i=0;i<PDFViewer.Document.PageCount;i++)
            {
                var annotes = PDFViewer.GetAnnotCommentList(i,PDFViewer.Document);
                for(int j=0;j<annotes.Count;j++)
                {
                    if(annotes[j].EventType == AnnotArgsType.AnnotRedaction)
                    {
                        IsEnable = true;
                        return;
                    }
                }
            }
   
        }

        private void PDFViewer_InfoChanged(object sender, KeyValuePair<string, object> e)
        {
            isFromSelf = true;
           if(e.Key=="PageNum")
            {
                var data = e.Value as RenderData;
                CurrentPage = data.PageIndex;
            }
            isFromSelf = false;
        }
        #endregion
    }
}