using ComPDFKit.PDFAnnotation;
using ComPDFKitViewer.AnnotEvent;
using ComPDFKitViewer.PdfViewer;
using Microsoft.Win32;
using PDF_Office.Model;
using PDF_Office.Model.AnnotPanel;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace PDF_Office.ViewModels.PropertyPanel.AnnotPanel
{
    class CustomCreateDialogViewModel : BindableBase, IDialogAware
    {
        public string Title => ".";

        public event Action<IDialogResult> RequestClose;
        public DelegateCommand CancelCommand { get; set; }

        public DelegateCommand CreateCommnad { get; set; }

        public DelegateCommand UpDataDynamicCommnad { get; set; }
        public DelegateCommand OpenImageCommnad { get; set; }

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

        private BitmapSource textImageSource;
        public BitmapSource TextImageSource
        {
            get { return textImageSource; }
            set
            {
                SetProperty(ref textImageSource, value);
            }
        }
        private BitmapSource imagePreviewSource;
        public BitmapSource ImagePreviewSource
        {
            get { return imagePreviewSource; }
            set
            {
                SetProperty(ref imagePreviewSource, value);
            }
        }
        private string stampText = "Stamp Text";

        public string StampText
        {
            get { return stampText; }
            set
            {
                SetProperty(ref stampText, value);
            }
        }
        private bool isCheckedDate;

        public bool IsCheckedDate
        {
            get { return isCheckedDate; }
            set
            {
                SetProperty(ref isCheckedDate, value);
                UpDataStamp();
            }
        }
        private bool isCheckedTime;

        public bool IsCheckedTime
        {
            get { return isCheckedTime; }
            set
            {
                SetProperty(ref isCheckedTime, value);
                UpDataStamp();
            }
        }

        private Visibility showImageButton = Visibility.Visible;

        public Visibility ShowImageButton
        {
            get { return showImageButton; }
            set
            {
                SetProperty(ref showImageButton, value);
            }
        }

        private int radioButtonIndex = 1;

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

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

        private BitmapSource originalimagePreviewSource;
        private BitmapSource removeBackgroundImagePreviewSource;

        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 C_TEXTSTAMP_SHAPE shape = C_TEXTSTAMP_SHAPE.TEXTSTAMP_RECT;

        public C_TEXTSTAMP_SHAPE Shape
        {
            get { return shape; }
            set { shape = value; }
        }

        private C_TEXTSTAMP_COLOR color = C_TEXTSTAMP_COLOR.TEXTSTAMP_RED;

        public C_TEXTSTAMP_COLOR Color
        {
            get { return color; }
            set { color = value; }
        }

        public string SaveToPath { get; private set; }
        public string RemoveBackgroundSaveToPath { get; private set; }
        public string StampTextDate { get; private set; }
        public int StampWidth { get; private set; }
        public int StampHeight { get; private set; }
        public StampType Type { get; private set; }
        public void SetStampStyle(int index)
        {
            RadioButtonIndex = index;
            switch (index)
            {
                case 1:
                    Color = C_TEXTSTAMP_COLOR.TEXTSTAMP_WHITE;
                    Shape = C_TEXTSTAMP_SHAPE.TEXTSTAMP_NONE;
                    break;
                case 2:
                    Color = C_TEXTSTAMP_COLOR.TEXTSTAMP_WHITE;
                    Shape = C_TEXTSTAMP_SHAPE.TEXTSTAMP_RECT;
                    break;
                case 3:
                    Color = C_TEXTSTAMP_COLOR.TEXTSTAMP_GREEN;
                    Shape = C_TEXTSTAMP_SHAPE.TEXTSTAMP_RECT;
                    break;
                case 4:
                    Color = C_TEXTSTAMP_COLOR.TEXTSTAMP_RED;
                    Shape = C_TEXTSTAMP_SHAPE.TEXTSTAMP_RECT;
                    break;
                case 5:
                    Color = C_TEXTSTAMP_COLOR.TEXTSTAMP_BLUE;
                    Shape = C_TEXTSTAMP_SHAPE.TEXTSTAMP_RECT;
                    break;
                case 6:
                    Color = C_TEXTSTAMP_COLOR.TEXTSTAMP_GREEN;
                    Shape = C_TEXTSTAMP_SHAPE.TEXTSTAMP_LEFT_TRIANGLE;
                    break;
                case 7:
                    Color = C_TEXTSTAMP_COLOR.TEXTSTAMP_RED;
                    Shape = C_TEXTSTAMP_SHAPE.TEXTSTAMP_LEFT_TRIANGLE;
                    break;
                case 8:
                    Color = C_TEXTSTAMP_COLOR.TEXTSTAMP_BLUE;
                    Shape = C_TEXTSTAMP_SHAPE.TEXTSTAMP_LEFT_TRIANGLE;
                    break;
                case 9:
                    Color = C_TEXTSTAMP_COLOR.TEXTSTAMP_GREEN;
                    Shape = C_TEXTSTAMP_SHAPE.TEXTSTAMP_RIGHT_TRIANGLE;
                    break;
                case 10:
                    Color = C_TEXTSTAMP_COLOR.TEXTSTAMP_RED;
                    Shape = C_TEXTSTAMP_SHAPE.TEXTSTAMP_RIGHT_TRIANGLE;
                    break;
                case 11:
                    Color = C_TEXTSTAMP_COLOR.TEXTSTAMP_GREEN;
                    Shape = C_TEXTSTAMP_SHAPE.TEXTSTAMP_RIGHT_TRIANGLE;
                    break;
                default:
                    break;
            }
            UpDataStamp();
        }

        public CustomCreateDialogViewModel()
        {
            CancelCommand = new DelegateCommand(Cancel);
            CreateCommnad = new DelegateCommand(Create);
            UpDataDynamicCommnad = new DelegateCommand(UpDataStamp);
            KeyDown = new DelegateCommand<object>(PreviewKeyDown);
            OpenImageCommnad = new DelegateCommand(OpenImage);
        }
        private void Cancel()
        {
            RequestClose.Invoke(new DialogResult(ButtonResult.Cancel));
        }

        private void Create()
        {
            if (Type == StampType.TEXT_STAMP)
            {
                SaveImageToPath();
            }
            DialogParameters valuePairs = new DialogParameters();
            valuePairs.Add(ParameterNames.DataModel, this);
            RequestClose.Invoke(new DialogResult(ButtonResult.OK, valuePairs));
        }

        private void SaveImageToPath()
        {
            string path = App.CachePath.CustomStampPath;
            string name = Guid.NewGuid().ToString();
            if (!string.IsNullOrEmpty(path))
            {
                BitmapEncoder encoder = new PngBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(TextImageSource));
                path = System.IO.Path.Combine(path, name);
                using (FileStream stream = new FileStream(path, FileMode.Create))
                {
                    encoder.Save(stream);
                }
                SaveToPath = path;
            }
            else
            {
                SaveToPath = "";
            }
        }

        public bool CanCloseDialog()
        {
            return true;
        }

        public void OnDialogClosed()
        {
            return;
        }
        private void PreviewKeyDown(object e)
        {
            var args = e as KeyEventArgs;
            if (args == null)
            {
                return;
            }
            if (args.Key == Key.Enter)
            {
                StampText = (args.OriginalSource as TextBox).Text;
                UpDataStamp();
            }
        }
        public void UpDataStamp()
        {
            string date = "";
            string dateType = "";
            if (IsCheckedDate)
            {
                dateType = "yyyy-MM-dd";
            }
            if (IsCheckedTime)
            {
                dateType = dateType + " HH:mm:ss";
            }
            if (!String.IsNullOrEmpty(dateType))
            {
                date = DateTime.Now.ToString(dateType);
            }

            var bytes = CPDFStampAnnotation.GetTempTextStampImage(StampText, date,
            Shape, Color, out int stampWidth, out int stampHeight, out int width, out int height);
            if (bytes.Length > 0)
            {
                PixelFormat fmt = PixelFormats.Bgra32;
                BitmapSource bps = BitmapSource.Create(width, height, 96, 96, fmt, null, bytes, (width * fmt.BitsPerPixel + 7) / 8);
                TextImageSource = bps;
                StampTextDate = date;
                StampWidth = stampWidth;
                StampHeight = stampHeight;
                Type = StampType.TEXT_STAMP;
            }
            else
            {
                TextImageSource = null;
            }
        }

        public 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;
                    StampWidth = targetBitmap.PixelWidth;
                    StampHeight = targetBitmap.PixelHeight;
                    Type = StampType.IMAGE_STAMP;
                    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);
                    }
                    SaveToPath = path;
                    IsNewFile = true;
                    ImagePreviewSource = originalimagePreviewSource = targetBitmap;
                    StampWidth = targetBitmap.PixelWidth;
                    StampHeight = targetBitmap.PixelHeight;
                    Type = StampType.IMAGE_STAMP;
                    ShowImageButton = Visibility.Collapsed;
                }
            }
            else
            {
                SaveToPath = "";
            }
        }

        /// <summary>
        /// 去除白底
        /// </summary>
        public 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;
        }


        public void OnDialogOpened(IDialogParameters parameters)
        {
            if (parameters != null)
            {
                Stamp stamp = parameters.GetValue<Stamp>(ParameterNames.DataModel);
                if (stamp != null)
                {
                    IsCheckedTime = stamp.IsCheckedTime;
                    IsCheckedDate = stamp.IsCheckedDate;
                    StampText = stamp.StampText;
                    SaveToPath = stamp.SourcePath;
                    Color = (C_TEXTSTAMP_COLOR)(int)stamp.TextColor;
                    Shape = (C_TEXTSTAMP_SHAPE)(int)stamp.TextSharp;
                    UpDataRadioButton(stamp.TextSharp, stamp.TextColor);
                }
            }
            UpDataStamp();
            return;
        }

        private void UpDataRadioButton(TextStampSharp textStampSharp, TextStampColor textStampColor)
        {
            int index = 1;
            switch (textStampColor)
            {
                case TextStampColor.TEXTSTAMP_WHITE:
                    switch (textStampSharp)
                    {
                        case TextStampSharp.TEXTSTAMP_RECT:
                            index = 2;
                            break;
                        case TextStampSharp.TEXTSTAMP_NONE:
                            index = 1;
                            break;
                    }
                    break;
                case TextStampColor.TEXTSTAMP_RED:
                    switch (textStampSharp)
                    {
                        case TextStampSharp.TEXTSTAMP_RECT:
                            index = 4;
                            break;
                        case TextStampSharp.TEXTSTAMP_LEFT_TRIANGLE:
                            index = 7;
                            break;
                        case TextStampSharp.TEXTSTAMP_RIGHT_TRIANGLE:
                            index = 10;
                            break;
                    }
                    break;
                case TextStampColor.TEXTSTAMP_GREEN:
                    switch (textStampSharp)
                    {
                        case TextStampSharp.TEXTSTAMP_RECT:
                            index = 3;
                            break;
                        case TextStampSharp.TEXTSTAMP_LEFT_TRIANGLE:
                            index = 6;
                            break;
                        case TextStampSharp.TEXTSTAMP_RIGHT_TRIANGLE:
                            index = 9;
                            break;
                    }
                    break;
                case TextStampColor.TEXTSTAMP_BLUE:
                    switch (textStampSharp)
                    {
                        case TextStampSharp.TEXTSTAMP_RECT:
                            index = 5;
                            break;
                        case TextStampSharp.TEXTSTAMP_LEFT_TRIANGLE:
                            index = 8;
                            break;
                        case TextStampSharp.TEXTSTAMP_RIGHT_TRIANGLE:
                            index = 11;
                            break;
                    }
                    break;
                default:
                    break;
            }
            RadioButtonIndex = index;
        }
    }
}
