using ComPDFKitViewer.AnnotEvent;
using ComPDFKitViewer.PdfViewer;
using Microsoft.Win32;
using PDF_Office.Model;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Ink;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace PDF_Office.ViewModels.PropertyPanel.AnnotPanel
{
    class SignatureCreateDialogViewModel : BindableBase, IDialogAware
    {
        public string Title => "";
        private CPDFViewer PDFViewer;
        public event Action<IDialogResult> RequestClose;
        public DelegateCommand CancelCommand { get; set; }

        public DelegateCommand CreateCommnad { get; set; }

        public DelegateCommand<object> CheckedCommnad { get; set; }

        public DelegateCommand OpenImageCommnad { get; set; }
        public ObservableCollection<string> FontNameList { get; set; }
        public ObservableCollection<string> ThicknessList { get; set; }

        private int fontNameIndex = 0;

        public int FontNameIndex
        {
            get { return fontNameIndex; }
            set
            {
                SetProperty(ref fontNameIndex, value);
            }
        }



        private int radioButtonIndex = 1;

        public int RadioButtonIndex
        {
            get { return radioButtonIndex; }
            set
            {
                SetProperty(ref radioButtonIndex, value);
            }
        }


        private int tabItemIndex;

        public int TabItemIndex
        {
            get { return tabItemIndex; }
            set
            {
                SetProperty(ref tabItemIndex, value);
            }
        }

        private string inputText = "";

        public string InputText
        {
            get { return inputText; }
            set
            {
                SetProperty(ref inputText, value);
            }
        }

        private Visibility showImageButton = Visibility.Visible;

        public Visibility ShowImageButton
        {
            get { return showImageButton; }
            set
            {
                SetProperty(ref showImageButton, value);
            }
        }
        private BitmapSource imagePreviewSource;
        public BitmapSource ImagePreviewSource
        {
            get { return imagePreviewSource; }
            set
            {
                SetProperty(ref imagePreviewSource, value);
            }
        }
        private bool issRemoveBackground;

        public bool IsRemoveBackground
        {
            get { return issRemoveBackground; }
            set
            {
                SetProperty(ref issRemoveBackground, value);
                if (issRemoveBackground)
                {
                    if (IsNewFile)
                    {
                        removeBackgroundImagePreviewSource = ToBitmapImage(KnockOutGzf());
                    }
                    ImagePreviewSource = removeBackgroundImagePreviewSource;
                }
                else
                {
                    ImagePreviewSource = originalimagePreviewSource;
                }
            }
        }

        private DrawingAttributes drawingAttributes;

        public DrawingAttributes DrawingAttributeObject
        {
            get { return drawingAttributes; }
            set
            {
                SetProperty(ref drawingAttributes, value);
            }
        }
        

        private StrokeCollection strokes;

        public StrokeCollection StrokesObject
        {
            get { return strokes; }
            set
            {
                SetProperty(ref strokes, value);
            }
        }

        private int imageRadioButtonIndex = 1;

        public int ImageRadioButtonIndex
        {
            get { return imageRadioButtonIndex; }
            set
            {
                SetProperty(ref imageRadioButtonIndex, value);
                switch (imageRadioButtonIndex)
                {
                    case 1:
                        DrawingAttributeObject.Color = Colors.Black;
                        break;
                    case 2:
                        DrawingAttributeObject.Color = Colors.Red;
                        break;
                    case 3:
                        DrawingAttributeObject.Color = Colors.Green;
                        break;
                    case 4:
                        DrawingAttributeObject.Color = Colors.Blue;
                        break;
                    default:
                        break;
                }
                UpDataToStrokesObject();
            }
        }

        private int thicknessListIndex = 0;

        public int ThicknessListIndex
        {
            get { return thicknessListIndex; }
            set
            {
                SetProperty(ref thicknessListIndex, value);
                if (thicknessListIndex>=0)
                {
                    DrawingAttributeObject.Width = DrawingAttributeObject.Height = Convert.ToDouble(ThicknessList[thicknessListIndex].Substring(0, 3));
                    UpDataToStrokesObject();
                }
            }
        }


        public string SaveToPath { get; private set; }

        public string RemoveBackgroundSaveToPath { get; private set; }

        public string DrawingSaveToPath { get; private set; }



        /// <summary>
        /// 用于判断是否更换了文件,更换了文件则需要重新计算去背功能
        /// </summary>
        private bool IsNewFile = false;

        //去背图片和原图的图片数据
        private BitmapSource originalimagePreviewSource = null;
        private BitmapSource removeBackgroundImagePreviewSource = null;
        public SignatureCreateDialogViewModel()
        {
            DrawingAttributeObject = new DrawingAttributes();
            StrokesObject = new StrokeCollection();
            FontNameList = new ObservableCollection<string>();
            ThicknessList = new ObservableCollection<string>() { "1.0pt", "2.0pt", "4.0pt", "6.0pt", "8.0pt" };//改了这里记得去改ThicknessListIndex的Set方法里面的取值
            CancelCommand = new DelegateCommand(Cancel);
            CreateCommnad = new DelegateCommand(Create);
            CheckedCommnad = new DelegateCommand<object>(Checked);
            OpenImageCommnad = new DelegateCommand(OpenImage);
            DrawingAttributeObject.Color = Colors.Black;
            DrawingAttributeObject.Width = 1;
            DrawingAttributeObject.Height = 1;
            WeakEventManager<StrokeCollection, StrokeCollectionChangedEventArgs>.AddHandler(StrokesObject, "StrokesChanged", StrokesObject_StrokesChanged);
            InitFontNameList();
        }

        private void StrokesObject_StrokesChanged(object sender, StrokeCollectionChangedEventArgs e)
        {
            int x1 =1;
        }

        private void InitFontNameList()
        {
            System.Drawing.Text.InstalledFontCollection objFont = new System.Drawing.Text.InstalledFontCollection();
            foreach (var item in objFont.Families)
            {
                FontNameList.Add(item.Name);
            }
        }

        private void Checked(object index)
        {
            RadioButtonIndex = Convert.ToInt32(index);
        }

        public void UpDataImageRadioButtonIndex(int Index)
        {
            ImageRadioButtonIndex = Index;
        }

        public void UpDataRadioButtonIndex(int Index)
        {
            RadioButtonIndex = Index;
        }

        private void UpDataToStrokesObject()
        {
            foreach (var item in StrokesObject)
            {
                item.DrawingAttributes = DrawingAttributeObject;
            }
        }

        private void OpenImage()
        {
            OpenFileDialog openFile = new OpenFileDialog();
            openFile.Filter = "All Image Files(*.bmp;*.gif;*.jpeg;*.jpg;*.png;*.tiff)|*.bmp;*.gif;*.jpeg;*.jpg;*.png;*.tiff|(*.bmp)|*.bmp|" +
                "(*.gif)|*.gif|" +
                "(*.jpeg)|*.jpeg|" +
                "(*.jpg)|*.jpg|" +
                "(*.png)|*.png|" +
                "(*.tiff)|*.tiff";
            if (openFile.ShowDialog() == false)
            {
                return;
            }
            string path = App.CachePath.CustomStampPath;
            string name = Guid.NewGuid().ToString();
            if (!string.IsNullOrEmpty(path))
            {
                BitmapImage image = new BitmapImage(new Uri(openFile.FileName));
                double scale = Math.Min((double)600 / image.PixelWidth, (double)600 / image.PixelHeight);
                scale = Math.Min(scale, 1);
                string ext = Path.GetExtension(openFile.FileName);
                if (ext.ToUpper() == ".PNG")
                {
                    BitmapEncoder encoder = new PngBitmapEncoder();
                    var targetBitmap = new TransformedBitmap(image, new ScaleTransform(scale, scale));
                    encoder.Frames.Add(BitmapFrame.Create(targetBitmap));
                    path = System.IO.Path.Combine(path, name);
                    using (FileStream stream = new FileStream(path, FileMode.Create))
                    {
                        encoder.Save(stream);
                    }
                    if (!string.IsNullOrEmpty(SaveToPath))
                    {
                        App.CachePath.AddToDeleteFiles(SaveToPath);
                    }
                    IsNewFile = true;
                    SaveToPath = path;
                    ImagePreviewSource = originalimagePreviewSource = targetBitmap;
                    ShowImageButton = Visibility.Collapsed;
                }
                else
                {
                    BitmapEncoder encoder = new JpegBitmapEncoder();
                    TransformedBitmap targetBitmap = new TransformedBitmap(image, new ScaleTransform(scale, scale));
                    encoder.Frames.Add(BitmapFrame.Create(targetBitmap));
                    path = System.IO.Path.Combine(path, name);
                    using (FileStream stream = new FileStream(path, FileMode.Create))
                    {
                        encoder.Save(stream);
                    }
                    if (!string.IsNullOrEmpty(SaveToPath))
                    {
                        App.CachePath.AddToDeleteFiles(SaveToPath);
                    }
                    IsNewFile = true;
                    SaveToPath = path;
                    ImagePreviewSource = originalimagePreviewSource = targetBitmap;
                    ShowImageButton = Visibility.Collapsed;
                }
            }
            else
            {
                SaveToPath = "";
            }
        }

        /// <summary>
        /// 去除白底
        /// </summary>
        private Bitmap KnockOutGzf()
        {
            System.Drawing.Image image = System.Drawing.Image.FromFile(SaveToPath);
            Bitmap bitmapProxy = new Bitmap(image);
            image.Dispose();
            for (int i = 0; i < bitmapProxy.Width; i++)
            {
                for (int j = 0; j < bitmapProxy.Height; j++)
                {
                    System.Drawing.Color c = bitmapProxy.GetPixel(i, j);
                    if (!(c.R < 240 || c.G < 240 || c.B < 240))
                    {
                        bitmapProxy.SetPixel(i, j, System.Drawing.Color.Transparent);
                    }
                }
            }
            return bitmapProxy;
        }

        /// <summary>
        /// 将 Bitmap 转化为 BitmapSource
        /// </summary>
        /// <param name="bmp"/>要转换的 Bitmap
        /// <returns>转换后的 BitmapImage</returns>
        private BitmapImage ToBitmapImage(System.Drawing.Bitmap bmp)
        {
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);

            BitmapImage image = new BitmapImage();
            image.BeginInit();
            image.StreamSource = ms;
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.EndInit();
            //编码，缓存到本地
            string path = App.CachePath.CustomStampPath;
            string name = Guid.NewGuid().ToString();
            BitmapEncoder encoder = new PngBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(image));
            path = System.IO.Path.Combine(path, name);
            using (FileStream stream = new FileStream(path, FileMode.Create))
            {
                encoder.Save(stream);
            }
            if (!string.IsNullOrEmpty(RemoveBackgroundSaveToPath))
            {
                App.CachePath.AddToDeleteFiles(RemoveBackgroundSaveToPath);
            }
            RemoveBackgroundSaveToPath = path;
            IsNewFile = false;
            return image;
        }
        /// <summary>
        /// 把文字转换成Bitmap
        /// </summary>
        /// <param name="text"></param>
        /// <param name="font"></param>
        /// <param name="rect">用于输出的矩形，文字在这个矩形内显示，为空时自动计算</param>
        /// <param name="fontcolor">字体颜色</param>
        /// <param name="backColor">背景颜色</param>
        /// <returns></returns>
        private Bitmap TextToBitmap(string text, Font font, Rectangle rect, System.Drawing.Color fontcolor, System.Drawing.Color backColor)
        {
            Graphics g;
            Bitmap bmp;
            StringFormat format = new StringFormat(StringFormatFlags.NoClip);
            if (rect == Rectangle.Empty)
            {
                bmp = new Bitmap(1, 1);
                g = Graphics.FromImage(bmp);
                //计算绘制文字所需的区域大小（根据宽度计算长度），重新创建矩形区域绘图
                SizeF sizef = g.MeasureString(text, font, PointF.Empty, format);

                int width = (int)(sizef.Width + 1);
                int height = (int)(sizef.Height + 1);
                rect = new Rectangle(0, 0, width, height);
                bmp.Dispose();

                bmp = new Bitmap(width, height);
            }
            else
            {
                bmp = new Bitmap(rect.Width, rect.Height);
            }

            g = Graphics.FromImage(bmp);

            //使用ClearType字体功能
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
            g.FillRectangle(new SolidBrush(backColor), rect);
            g.DrawString(text, font, new SolidBrush(fontcolor), rect, format);
            return bmp;
        }

        private void Cancel()
        {
            RequestClose.Invoke(new DialogResult(ButtonResult.Cancel));
        }

        private void Create()
        {
            switch (TabItemIndex)
            {
                case 0:
                    {
                        System.Drawing.Color fontcolor = System.Drawing.Color.Black;
                        switch (RadioButtonIndex)
                        {
                            case 1:
                                fontcolor = System.Drawing.Color.Black;
                                break;
                            case 2:
                                fontcolor = System.Drawing.Color.Red;
                                break;
                            case 3:
                                fontcolor = System.Drawing.Color.Green;
                                break;
                            case 4:
                                fontcolor = System.Drawing.Color.Blue;
                                break;
                            default:
                                break;
                        }

                        Bitmap bmp = TextToBitmap(InputText, new Font(FontNameList[fontNameIndex], 48), Rectangle.Empty, fontcolor, System.Drawing.Color.Transparent);
                        string guid = Guid.NewGuid().ToString();
                        string path = System.IO.Path.Combine(App.CachePath.SignatureStampPath, guid);
                        bmp.Save(path, ImageFormat.Png);
                        SaveToPath = path;
                    }
                    break;
                case 1:
                    {

                        var FreeHandpath = App.CachePath.SignatureFreeHandPath;
                        string name = Guid.NewGuid().ToString();
                        FreeHandpath = System.IO.Path.Combine(FreeHandpath, name);
                        using (System.IO.FileStream stream = new System.IO.FileStream(FreeHandpath, System.IO.FileMode.Create))
                        {
                            StrokesObject.Save(stream);
                        }

                        StampAnnotArgs stampArgs = new StampAnnotArgs();

                        List<List<System.Windows.Point>> RawPointList = new List<List<System.Windows.Point>>();
                        for (int kk = 0; kk < StrokesObject.Count; kk++)
                        {
                            List<System.Windows.Point> p = new List<System.Windows.Point>();
                            RawPointList.Add(p);
                            for (int gg = 0; gg < StrokesObject[kk].StylusPoints.Count; gg++)
                            {
                                var point = StrokesObject[kk].StylusPoints[gg].ToPoint();

                                if (point.X >= 0 && point.Y >= 0)
                                    RawPointList[kk].Add(point);

                            }
                        }
                        DrawingSaveToPath = FreeHandpath;

                        stampArgs.SetInkData(RawPointList, drawingAttributes.Width, drawingAttributes.Color);
                        var writeStamp = stampArgs.GetStampDrawing();

                        FreeHandpath = App.CachePath.SignatureStampPath;
                        string thumbnailName = Guid.NewGuid().ToString();
                        FreeHandpath = System.IO.Path.Combine(FreeHandpath, thumbnailName);
                        using (FileStream stream5 = new FileStream(FreeHandpath, FileMode.Create))
                        {
                            PngBitmapEncoder encoder5 = new PngBitmapEncoder();
                            encoder5.Frames.Add(BitmapFrame.Create(writeStamp));
                            encoder5.Save(stream5);
                        }
                        SaveToPath = FreeHandpath;
                    }
                    break;
                case 2:
                    break;
                default:
                    break;
            }
            DialogParameters valuePairs = new DialogParameters();
            valuePairs.Add(ParameterNames.DataModel, this);
            RequestClose.Invoke(new DialogResult(ButtonResult.OK, valuePairs));
        }

        public bool CanCloseDialog()
        {
            return true;
        }

        public void OnDialogClosed()
        {
            return;
        }

        public void OnDialogOpened(IDialogParameters parameters)
        {
            if (parameters != null)
            {
                PDFViewer = parameters.GetValue<CPDFViewer>(ParameterNames.PDFViewer);
                if (PDFViewer != null)
                {

                }
            }
            return;
        }
    }
}
