using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using Ghostscript.NET;
using Ghostscript.NET.Processor;
using InABox.Clients;
using InABox.Core;
using InABox.WPF;
using Microsoft.Win32;
using Syncfusion.Pdf;
using Syncfusion.Pdf.Graphics;
using Syncfusion.Pdf.Interactive;
using Syncfusion.Pdf.Parsing;
using Syncfusion.Windows.PdfViewer;
using ColorConverter = System.Windows.Media.ColorConverter;
using Image = System.Windows.Controls.Image;

namespace InABox.DynamicGrid
{
    public delegate void PDFSettingsChangedEvent(object sender, string linecolor, int fontsize);

    public delegate void PDFDocumentLoadedEvent(object sender, IEntityDocument document);

    /// <summary>
    ///     Interaction logic for PDFEditorControl.xaml
    /// </summary>
    public partial class PDFEditorControl : UserControl, IDocumentEditor
    {
        private IEntityDocument _document;

        //private PdfDocumentView PdfViewer = null;
        private readonly List<Guid> currentAnnotations = new();

        private byte[] pdfdocument;

        public PDFEditorControl()
        {
            InitializeComponent();
            SaveAllowed = false;
            ButtonsVisible = true;

            PdfViewer.ReferencePath =
                AppDomain.CurrentDomain.BaseDirectory; // System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "pdfium");
            PdfViewer.PrinterSettings.PageSize = PdfViewerPrintSize.Fit;
        }

        public string LineColor { get; set; }
        public int TextSize { get; set; }

        //public bool PrintAllowed { get; set; }

        public bool SaveAllowed { get; set; }
        
        public bool ButtonsVisible { get; set; }

        public string Watermark { get; set; }

        public PDFSettingsChangedEvent PDFSettingsChanged { get; set; }

        public PDFDocumentLoadedEvent PDFDocumentLoaded { get; set; }

        public IEntityDocument? Document
        {
            get => _document;
            set
            {
                UnloadPDF();
                _document = value;
                LoadPDF();
                PDFDocumentLoaded?.Invoke(this, value);
            }
        }

        #region Unload / Save PDF Document

        private void UnloadCurrentPDF()
        {
            UnloadPDFAnnotations();
            pdfdocument = null;
        }

        private string CurrentAnnotations = "";

        private string AnnotationsToString()
        {
            var ms1 = new MemoryStream();
            PdfViewer.LoadedDocument.Save(ms1);
            ms1.Position = 0;
            var doc = new PdfLoadedDocument(ms1);

            var sb = new StringBuilder();
            for (var i = 0; i < doc.Pages.Count; i++)
            {
                var page = doc.Pages[i] as PdfLoadedPage;
                try
                {
                    foreach (PdfLoadedAnnotation a in page.Annotations)
                        sb.Append(SaveAnnotation(doc, a));
                }
                catch (Exception e)
                {
                    Logger.Send(LogType.Error, ClientFactory.UserID, string.Format("*** Unable to retreive Annotations ***\n{0}", e.StackTrace));
                }
            }

            return sb.ToString();
        }

        private void UnloadPDFAnnotations()
        {
            try
            {
                if (_document != null && PdfViewer.IsDocumentEdited)
                    //if ((PdfViewer != null) && (documentid != Guid.Empty) && (pdfdocument != null) && (PdfViewer.Visibility == Visibility.Visible) && (PdfViewer.IsDocumentEdited))
                {
                    var ms1 = new MemoryStream();
                    PdfViewer.LoadedDocument.Save(ms1);
                    ms1.Position = 0;
                    var doc = new PdfLoadedDocument(ms1);

                    //SetoutDocument document = documents.FirstOrDefault(x => x.DocumentLink.ID.Equals(documentid));
                    if (_document != null)
                    {
                        var annotations = new Client<EntityDocumentAnnotation>()
                            .Load(new Filter<EntityDocumentAnnotation>(x => x.EntityDocument).IsEqualTo(_document.ID)).ToList();
                        for (var i = 0; i < doc.Pages.Count; i++)
                        {
                            var page = doc.Pages[i] as PdfLoadedPage;
                            foreach (PdfLoadedAnnotation a in page.Annotations)
                            {
                                var a_id = Guid.Empty;
                                if (!string.IsNullOrWhiteSpace(a.Author))
                                    Guid.TryParse(a.Author, out a_id);

                                if (currentAnnotations.Contains(a_id))
                                    currentAnnotations.Remove(a_id);

                                var annotation = a_id.Equals(Guid.Empty) ? null : annotations.FirstOrDefault(x => x.ID.Equals(a_id));
                                if (annotation == null)
                                {
                                    annotation = new EntityDocumentAnnotation { EntityDocument = _document.ID };
                                    annotations.Add(annotation);
                                }

                                annotation.Page = i;
                                annotation.Type = GetAnnotationType(a);
                                annotation.Data = SaveAnnotation(doc, a);
                            }
                        }

                        new Client<EntityDocumentAnnotation>().Save(annotations.Where(x => x.IsChanged()), "");

                        foreach (var annotation in annotations.Where(x => currentAnnotations.Contains(x.ID)))
                            new Client<EntityDocumentAnnotation>().Delete(annotation, "");
                    }
                }
            }
            catch (Exception e)
            {
                MessageBox.Show("Unable to Save Annotations: " + e.Message + "\n" + e.StackTrace);
            }
        }

        public EntityDocumentAnnotationType GetAnnotationType(PdfAnnotation annotation)
        {
            if (annotation is PdfLoadedLineAnnotation)
                return EntityDocumentAnnotationType.Line;
            if (annotation is PdfLoadedEllipseAnnotation)
                return EntityDocumentAnnotationType.Ellipse;
            if (annotation is PdfLoadedRectangleAnnotation)
                return EntityDocumentAnnotationType.Rectangle;
            if (annotation is PdfLoadedSquareAnnotation)
                return EntityDocumentAnnotationType.Rectangle;
            if (annotation is PdfLoadedFreeTextAnnotation)
                return EntityDocumentAnnotationType.Text;
            if (annotation is PdfLoadedInkAnnotation)
                return EntityDocumentAnnotationType.Ink;
            if (annotation is PdfLoadedRubberStampAnnotation)
            {
                if (!string.IsNullOrWhiteSpace(annotation.Subject))
                {
                    if (annotation.Subject.Equals("Warning"))
                        return EntityDocumentAnnotationType.WarningStamp;
                    if (annotation.Subject.Equals("Error"))
                        return EntityDocumentAnnotationType.ErrorStamp;
                }

                return EntityDocumentAnnotationType.OKStamp;
            }

            throw new Exception("Unknown Annotation: " + annotation.GetType().Name);
        }

        public string SaveAnnotation(PdfLoadedDocument doc, PdfLoadedAnnotation annotation)
        {
            annotation.Author = CoreUtils.FullGuid.ToString();
            var ms = new MemoryStream();
            var collection = new PdfExportAnnotationCollection();
            collection.Add(annotation);
            doc.ExportAnnotations(ms, AnnotationDataFormat.XFdf, collection);
            var result = Encoding.UTF8.GetString(ms.GetBuffer());
            return result;
        }

        public void LoadAnnotation(PdfLoadedDocument doc, string encoded, Guid id)
        {
            //PdfLoadedAnnotation annot = new PdfLoadedAnnotation();
            var data = encoded.Replace(CoreUtils.FullGuid.ToString(), id.ToString());
            var buffer = Encoding.UTF8.GetBytes(data);
            var ms = new MemoryStream(buffer);
            doc.ImportAnnotations(ms, AnnotationDataFormat.XFdf);
        }

        private void UnloadPDF()
        {
            if (_document != null)
                try
                {
                    UnloadPDFAnnotations();
                    PdfViewer.Unload(true);
                }
                catch (Exception e)
                {
                    Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
                }
        }

        #endregion

        #region Reload / Preprocess PDF Document

        private bool DownloadNeeded(Guid id)
        {
            var cachefile = Path.Combine(CoreUtils.GetPath(), string.Format("{0}.ffd", id.ToString()));

            if (!File.Exists(cachefile))
                return true;

            var indexfile = Path.Combine(CoreUtils.GetPath(), "pdfindex.json");
            if (!File.Exists(indexfile))
                return true;

            var json = File.ReadAllText(indexfile);
            var index = Serialization.Deserialize<Dictionary<Guid, string>>(json);
            if (!index.ContainsKey(id))
                return true;
            var entry = new Client<Document>().Query(
                new Filter<Document>(x => x.ID).IsEqualTo(id),
                Columns.None<Document>().Add(x => x.CRC)
            ).Rows.FirstOrDefault();
            if (entry == null)
                return true;
            if (!String.Equals(entry.Get<Document, string>(x => x.CRC),index[id]))
            {
                Dispatcher.BeginInvoke(() => 
                { 
                    MessageBox.Show("This PDF has been revised, and will now refresh.\n\nPlease check the drawing for any applicable changes."); 
                });                
                return true;
            }

            return false;
        }

        private bool AnnotationError;

        private void LoadPDF()
        {
            if (_document == null)
                return;

            var cachefile = Path.Combine(CoreUtils.GetPath(), string.Format("{0}.ffd", _document.DocumentLink.ID.ToString()));

            using (new WaitCursor())
            {
                if (DownloadNeeded(_document.DocumentLink.ID))
                {
                    CoreTable table = new Client<Document>().Query(new Filter<Document>(x => x.ID).IsEqualTo(_document.DocumentLink.ID));
                    if (!table.Rows.Any())
                    {
                        MessageBox.Show("Unable to Load File!");
                        return;
                    }
                    var dbdoc = table.Rows.FirstOrDefault().ToObject<Document>();

                    var indexfile = Path.Combine(CoreUtils.GetPath(), "pdfindex.json");
                    var index = new Dictionary<Guid, string>();
                    if (File.Exists(indexfile))
                    {
                        var json = File.ReadAllText(indexfile);
                        index = Serialization.Deserialize<Dictionary<Guid, string>>(json);
                    }

                    index[_document.DocumentLink.ID] = dbdoc.CRC;
                    File.WriteAllText(indexfile, Serialization.Serialize(index));

                    AnnotationError = false;

                    pdfdocument = dbdoc.Data;
                    try
                    {
                        pdfdocument = GhostScriptIt(pdfdocument);
                    }
                    catch (Exception eGhostscript)
                    {
                        Logger.Send(LogType.Information, "", "Ghostscript: " + eGhostscript.Message + "\n" + eGhostscript.StackTrace);
                    }

                    try
                    {
                        pdfdocument = FlattenPdf(pdfdocument);
                    }
                    catch (Exception eFlatten)
                    {
                        Logger.Send(LogType.Error, "", "Flatten Error: " + eFlatten.Message + "\n" + eFlatten.StackTrace);
                    }

                    try
                    {
                        if (AnnotationError)
                            pdfdocument = RasterizePDF(pdfdocument);
                    }
                    catch (Exception eRasterize)
                    {
                        Logger.Send(LogType.Error, "", "Rasterize Error: " + eRasterize.Message + "\n" + eRasterize.StackTrace);

                    }

                    File.WriteAllBytes(cachefile, pdfdocument);
                }
                else
                {
                    pdfdocument = File.ReadAllBytes(cachefile);
                }

                if (pdfdocument.Any())
                {

                    var doc = new PdfLoadedDocument(pdfdocument);

                    currentAnnotations.Clear();

                    var watermark = !_document.Superceded.IsEmpty() ? "SUPERCEDED" : Watermark;
                    if (!string.IsNullOrWhiteSpace(watermark))
                        foreach (PdfPageBase page in doc.Pages)
                        {
                            var rect = new RectangleF(0, 0, page.Size.Width, page.Size.Height);
                            var graphics = page.Graphics;
                            PdfFont font = new PdfStandardFont(PdfFontFamily.Helvetica, page.Size.Width / 10,
                                PdfFontStyle.Bold);
                            var state = graphics.Save();
                            graphics.SetTransparency(0.2f);
                            var format = new PdfStringFormat();
                            format.Alignment = PdfTextAlignment.Center;
                            format.LineAlignment = PdfVerticalAlignment.Middle;

                            var lineheight = (int)Math.Round(font.Height * 2.5);
                            var lines = new List<string>();
                            while (lines.Count * lineheight < page.Size.Height)
                                lines.Add(watermark);
                            graphics.DrawString(string.Join("\n\n", lines), font, PdfBrushes.Red, rect, format);
                        }

                    //foreach (PdfPageBase page in doc.Pages)
                    //{
                    //    RectangleF rect = new RectangleF(0, 0, page.Size.Width, page.Size.Height);
                    //    PdfGraphics graphics = page.Graphics;
                    //    PdfFont font = new PdfStandardFont(PdfFontFamily.Helvetica, page.Size.Width / 10, PdfFontStyle.Bold);
                    //    PdfGraphicsState state = graphics.Save();
                    //    graphics.SetTransparency(0.2f);
                    //    PdfStringFormat format = new PdfStringFormat();
                    //    format.Alignment = PdfTextAlignment.Center;
                    //    format.LineAlignment = PdfVerticalAlignment.Middle;

                    //    int lineheight = (int)Math.Round(font.Height * 2.5);
                    //    List<String> lines = new List<string>();
                    //    while (lines.Count * lineheight < page.Size.Height)
                    //        lines.Add("SUPERCEDED");
                    //    graphics.DrawString(String.Join("\n\n", lines), font, PdfBrushes.Red, rect, format);
                    //}


                    var annotations = new Client<EntityDocumentAnnotation>()
                        .Load(new Filter<EntityDocumentAnnotation>(x => x.EntityDocument).IsEqualTo(_document.ID))
                        .ToList();
                    foreach (var annotation in annotations)
                        try
                        {
                            currentAnnotations.Add(annotation.ID);
                            if (!string.IsNullOrWhiteSpace(annotation.Data))
                            {
                                if (annotation.Data.Contains("<freetext") && !annotation.Data.Contains("date=\""))
                                {
                                    Logger.Send(LogType.Information, ClientFactory.UserID,
                                        string.Format("Annotation #{0} has no date - inserting now..", annotation.ID));
                                    annotation.Data = annotation.Data.Replace("<freetext",
                                        string.Format("<freetext date=\"D:{0:yyyyMMddHHmmss}+08\'00\'\"",
                                            DateTime.Now));
                                    //annotation.Data = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<xfdf xmlns=\"http://ns.adobe.com/xfdf/\" xml:space=\"preserve\">\r\n  <annots>\r\n    <freetext page=\"0\" rect=\"635.782,231.8206,812.7407,282.311\" rotation=\"0\" color=\"#FFFFFF\" title=\"ffffffff-ffff-ffff-ffff-ffffffffffff\" subject=\"Free Text\" date=\"D:20220715001146+08'00'\" name=\"800eae13-14f4-4db9-a60e-6d5d2d2adb55\" fringe=\"0,0,0,0\" border=\"0,0,1\" q=\"0\" IT=\"FreeTextCallout\" head=\"None\">\r\n      <defaultappearance>0.2901961 0.5647059 0.8862745 rg </defaultappearance>\r\n      <defaultstyle>font:Arial 8pt;style:Regular;color:#FF0000</defaultstyle>\r\n      <contents-richtext><body xmlns=\"http://www.w3.org/1999/xhtml\"><p dir=\"ltr\">MC'd by BW\r\nTrolley H18\r\n8 July 2022\r\nNOTE: 3032 Doorleaf is also on Trolley H18</p></body></contents-richtext>\r\n      <contents>MC'd by BW\r\nTrolley H18\r\n8 July 2022\r\nNOTE: 3032 Doorleaf is also on Trolley H18</contents>\r\n    </freetext>\r\n  </annots>\r\n  <f href=\"\" />\r\n</xfdf>";
                                    //annotation.Data = "<?xml version =\"1.0\" encoding=\"utf-8\"?>\r\n<xfdf xmlns=\"http://ns.adobe.com/xfdf/\" xml:space=\"preserve\">\r\n  <annots>\r\n    <freetext page=\"0\" rect=\"768.7103,558.5799,898.9603,642.3299\" rotation=\"0\" color=\"#FFFFFF\" title=\"ffffffff-ffff-ffff-ffff-ffffffffffff\" subject=\"Free Text\" date=\"D:20220715001146+08'00'\" flags=\"print\" name=\"690a16b1-647b-45a9-80a5-17f83f63bc93\" fringe=\"18,2,20,16.5\" border=\"0,0,1.5\" justification=\"0\" IT=\"FreeTextCallout\" head=\"OpenArrow\" callout=\"786.7103,625.8299,768.7103,593.2049,786.7103,593.2049\">\r\n      <defaultappearance>0.2901961 0.5647059 0.8862745 rg </defaultappearance>\r\n      <defaultstyle>font:Arial 12pt;style:Regular;color:#FF0000</defaultstyle>\r\n      <contents-richtext><body xmlns=\"http://www.w3.org/1999/xhtml\"><p dir=\"ltr\">Hi Thjere\r\n\r\nawd.flae\r\nsdfgljsdlkfg</p></body></contents-richtext>\r\n      <contents>Hi Thjere\r\n\r\nawd.flae\r\nsdfgljsdlkfg</contents>\r\n    </freetext>\r\n  </annots>\r\n  <f href=\"\" />\r\n</xfdf>";
                                }

                                LoadAnnotation(doc, annotation.Data.Replace("&", "+"), annotation.ID);
                            }
                        }
                        catch (Exception e)
                        {
                            Logger.Send(LogType.Error, "",
                                string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
                        }

                    var ms = new MemoryStream();
                    doc.Save(ms);
                    PdfViewer.ZoomMode = ZoomMode.FitWidth;
                    PdfViewer.Load(ms);
                    CurrentAnnotations = AnnotationsToString();
                }
                UpdateButtons(PdfNoneImage);
            }
        }

        private byte[] GhostScriptIt(byte[] data)
        {
            var input = Path.GetTempFileName();
            File.WriteAllBytes(input, data);

            byte[] result = { };

            var gv = new GhostscriptVersionInfo(
                new Version(0, 0, 0),
                "gsdll64.dll",
                "",
                GhostscriptLicense.GPL
            );

            var gsPipedOutput = new GhostscriptPipedOutput();

            // pipe handle format: %handle%hexvalue
            var outputPipeHandle = "%handle%" + int.Parse(gsPipedOutput.ClientHandle).ToString("X2");
            using (var processor = new GhostscriptProcessor(gv, true))
            {
                var switches = new List<string>();
                switches.Add("-empty");
                switches.Add("-dQUIET");
                switches.Add("-dSAFER");
                switches.Add("-dBATCH");
                switches.Add("-dNOPAUSE");
                switches.Add("-dNOPROMPT");
                switches.Add("-dCompatibilityLevel=1.4");
                switches.Add("-dPreserveAnnots=false");
                switches.Add("-sDEVICE=pdfwrite");
                switches.Add("-o" + outputPipeHandle);
                switches.Add("-q");
                switches.Add("-f");
                switches.Add(input);

                try
                {
                    processor.StartProcessing(switches.ToArray(), null);
                    result = gsPipedOutput.Data;
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                finally
                {
                    gsPipedOutput.Dispose();
                    gsPipedOutput = null;
                }
            }

            File.Delete(input);
            return result;
        }

        private byte[] RasterizePDF(byte[] data)
        {
            var source = PresentationSource.FromVisual(this);

            var dpiX = source != null ? 96.0 * source.CompositionTarget.TransformToDevice.M11 : 0.0F;
            var dpiY = source != null ? 96.0 * source.CompositionTarget.TransformToDevice.M22 : 0.0F;

            var gsdata = GhostScriptIt(data);

            var doc = new PdfLoadedDocument(gsdata);

            Bitmap[] bitmaps = doc.ExportAsImage(0, doc.Pages.Count - 1, (float)dpiX, (float)dpiY);

            PdfSection section = null;
            var pdf = new PdfDocument();
            pdf.PageSettings.Margins.All = 0;
            for (var i = 0; i < doc.Pages.Count; i++)
            {
                var oldpage = doc.Pages[i] as PdfLoadedPage;

                if (section == null || section.PageSettings.Size.Height != oldpage.Size.Height ||
                    section.PageSettings.Size.Width != oldpage.Size.Width)
                {
                    section = pdf.Sections.Add();
                    section.PageSettings.Size = oldpage.Size;
                    section.PageSettings.Orientation =
                        oldpage.Size.Height > oldpage.Size.Width ? PdfPageOrientation.Portrait : PdfPageOrientation.Landscape;
                }

                var newpage = section.Pages.Add();
                var graphics = newpage.Graphics;
                var bitmap = new PdfBitmap(bitmaps[i]);
                graphics.DrawImage(bitmap, new RectangleF(0, 0, section.PageSettings.Size.Width, section.PageSettings.Size.Height));
            }

            var ms = new MemoryStream();
            pdf.Save(ms);
            return ms.GetBuffer();
        }

        private byte[] FlattenPdf(byte[] data)
        {
            var doc = new PdfLoadedDocument(data);
            foreach (PdfLoadedPage page in doc.Pages)
                try
                {
                    foreach (PdfLoadedAnnotation annotation in page.Annotations) annotation.Flatten = true;
                }
                catch (Exception e)
                {
                    AnnotationError = true;
                    Logger.Send(LogType.Error, ClientFactory.UserID, string.Format("*** Unable to Flatten PDF ***\n{0}", e.Message));
                }

            var ms = new MemoryStream();
            doc.Save(ms);
            //doc.Save(filename);
            //return File.ReadAllBytes(filename);
            return ms.GetBuffer();
        }

        private void RefreshPDF_Click(object sender, RoutedEventArgs e)
        {
            UnloadPDF();
            var cachefile = Path.Combine(CoreUtils.GetPath(), string.Format("{0}.ffd", _document.DocumentLink.ID.ToString()));
            if (File.Exists(cachefile))
                File.Delete(cachefile);
            LoadPDF();
        }

        #endregion


        #region PDF Editing

        private Bitmap SizeBitmap()
        {
            var b = new Bitmap(32, 32);
            using (var g = Graphics.FromImage(b))
            {
                g.SmoothingMode = SmoothingMode.AntiAlias;

                g.FillRectangle(new SolidBrush(Color.White), 0, 0, 32, 32);

                var text = TextSize.ToString();
                var font = new Font("Arial", 12, System.Drawing.FontStyle.Bold);
                var size = g.MeasureString(text, font);
                var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
                g.DrawString(text, font, new SolidBrush(Color.DimGray), new RectangleF(4, 6, 24, 20), sf);

                var pen = new Pen(Color.DimGray, 2);
                g.DrawRectangle(pen, 4, 4, 24, 24);
            }

            return b;
        }

        private Bitmap ColorBitmap()
        {
            var b = new Bitmap(32, 32);
            using (var g = Graphics.FromImage(b))
            {
                g.SmoothingMode = SmoothingMode.AntiAlias;

                g.FillRectangle(new SolidBrush(Color.White), 0, 0, 32, 32);
                var color = ColorTranslator.FromHtml(LineColor);
                var brush = new SolidBrush(color);
                g.FillRectangle(brush, 4, 4, 24, 24);
                var pen = new Pen(Color.Black, 1);
                g.DrawRectangle(pen, 4, 4, 24, 24);
            }

            return b;
        }

        private void UpdateButtons(Image selected)
        {
            PDFButtonStack.Width = Document != null && Document.Superceded.IsEmpty() && ButtonsVisible
                ? new GridLength(44, GridUnitType.Pixel)
                : new GridLength(0, GridUnitType.Pixel);

            PdfColorImage.Source = ColorBitmap().AsBitmapImage(32, 32, false);

            PdfSizeImage.Source = SizeBitmap().AsBitmapImage(32, 32, false);

            PdfPrint.Visibility = Visibility.Collapsed; //PrintAllowed ? Visibility.Visible : Visibility.Collapsed;
            PdfSave.Visibility = SaveAllowed ? Visibility.Visible : Visibility.Collapsed;

            ColorButton(PdfNoneImage, selected,Wpf.Resources.hand);
            ColorButton(PdfInkImage, selected,Wpf.Resources.draw);
            ColorButton(PdfLineImage, selected,Wpf.Resources.line);
            ColorButton(PdfRectangleImage, selected,Wpf.Resources.square);
            ColorButton(PdfCircleImage, selected,Wpf.Resources.circle);
            ColorButton(PdfFreeTextImage, selected,Wpf.Resources.text);
            ColorButton(PdfOKImage, selected,Wpf.Resources.tick);
            ColorButton(PdfWarningImage, selected,Wpf.Resources.warning);
            ColorButton(PdfErrorImage, selected,Wpf.Resources.delete);
        }

        private void ColorButton(Image button, Image selected, Bitmap bitmap)
        {
            button.Source = selected == button
                ? bitmap.ChangeColor(Color.White, Color.Yellow).AsBitmapImage(32, 32, false)
                : bitmap.AsBitmapImage(32, 32, false);
        }

        private void PdfPrint_Click(object sender, RoutedEventArgs e)
        {
            PdfViewer.AnnotationMode = PdfDocumentView.PdfViewerAnnotationMode.None;
            PdfViewer.CursorMode = PdfViewerCursorMode.HandTool;
            UpdateButtons(PdfNoneImage);

            PdfViewer.PrinterSettings.ShowPrintStatusDialog = true;
            PdfViewer.PrinterSettings.PageSize = PdfViewerPrintSize.Fit;
            //String printer = "";
            //if (PrinterSelection.Execute(ref printer))
            //    PdfViewer.Print(printer);

            //PdfViewer.PrintCommand.Execute(PdfViewer);

            PrintDialog dialog = new PrintDialog();
            if (dialog.ShowDialog() == true)
                dialog.PrintDocument(PdfViewer.PrintDocument.DocumentPaginator, "PRS Factory Floor Printout");

            //var ms = new MemoryStream();
            //PdfViewer.LoadedDocument.Save(ms);

            //PdfViewer.Print();

            //byte[] data = ms.GetBuffer();
            //data = FlattenPdf(data);

            //String filename = System.IO.Path.ChangeExtension(System.IO.Path.GetTempFileName(), "pdf");
            //File.WriteAllBytes(filename, data);
            ////PdfViewer.Save(filename);
            //PDFPreview preview = new PDFPreview(filename);
            //preview.ShowDialog();
        }

        private void PdfSave_Click(object sender, RoutedEventArgs e)
        {
            PdfViewer.AnnotationMode = PdfDocumentView.PdfViewerAnnotationMode.None;
            PdfViewer.CursorMode = PdfViewerCursorMode.HandTool;
            UpdateButtons(PdfNoneImage);

            var dlg = new SaveFileDialog();
            dlg.Filter = "PDF Files (*.pdf)|*.pdf";
            dlg.FileName = Path.ChangeExtension(Document.DocumentLink.FileName, ".pdf");
            if (dlg.ShowDialog() == true)
            {
                var ms = new MemoryStream();
                PdfViewer.LoadedDocument.Save(ms);
                var data = ms.GetBuffer();
                data = FlattenPdf(data);
                var filename = dlg.FileName;
                File.WriteAllBytes(filename, data);
                
                var gsProcessInfo = new ProcessStartInfo();
                gsProcessInfo.Verb = "open";
                gsProcessInfo.WindowStyle = ProcessWindowStyle.Normal;
                gsProcessInfo.FileName = filename;
                gsProcessInfo.UseShellExecute = true;

                Process.Start(gsProcessInfo);
                
            }
        }

        private void PdfZoomIn_Click(object sender, RoutedEventArgs e)
        {
            PdfViewer.AnnotationMode = PdfDocumentView.PdfViewerAnnotationMode.None;
            ;
            PdfViewer.CursorMode = PdfViewerCursorMode.HandTool;
            UpdateButtons(PdfNoneImage);
            PdfViewer.IncreaseZoomCommand.Execute(null);
        }

        private void PdfZoomWidth_Click(object sender, RoutedEventArgs e)
        {
            PdfViewer.AnnotationMode = PdfDocumentView.PdfViewerAnnotationMode.None;
            ;
            PdfViewer.CursorMode = PdfViewerCursorMode.HandTool;
            UpdateButtons(PdfNoneImage);
            PdfViewer.ZoomMode = ZoomMode.FitWidth;
        }

        private void PdfZoomPage_Click(object sender, RoutedEventArgs e)
        {
            PdfViewer.AnnotationMode = PdfDocumentView.PdfViewerAnnotationMode.None;
            ;
            PdfViewer.CursorMode = PdfViewerCursorMode.HandTool;
            UpdateButtons(PdfNoneImage);
            PdfViewer.ZoomMode = ZoomMode.FitPage;
        }

        private void PdfZoomOut_Click(object sender, RoutedEventArgs e)
        {
            PdfViewer.AnnotationMode = PdfDocumentView.PdfViewerAnnotationMode.None;
            PdfViewer.CursorMode = PdfViewerCursorMode.HandTool;
            UpdateButtons(PdfNoneImage);
            PdfViewer.DecreaseZoomCommand.Execute(null);
        }

        private void PdfColor_Click(object sender, RoutedEventArgs e)
        {
            var color = ColorTranslator.FromHtml(LineColor);
            if (ColorEdit.Execute("Edit Color", ref color))
            {
                LineColor = ColorTranslator.ToHtml(color);
                PdfColorImage.Source = ColorBitmap().AsBitmapImage(false);
                PDFSettingsChanged?.Invoke(this, LineColor, TextSize);
            }
        }

        private void PdfSize_Click(object sender, RoutedEventArgs e)
        {
            var size = TextSize;
            if (NumberEdit.Execute("Edit Font Size", 4, 96, ref size))
            {
                TextSize = size;
                PdfSizeImage.Source = SizeBitmap().AsBitmapImage(false);
            }
        }

        private void PdfNone_Click(object sender, RoutedEventArgs e)
        {
            PdfViewer.AnnotationMode = PdfDocumentView.PdfViewerAnnotationMode.None;
            PdfViewer.CursorMode = PdfViewerCursorMode.HandTool;
            UpdateButtons(PdfNoneImage);
        }

        private void PdfInk_Click(object sender, RoutedEventArgs e)
        {
            PdfViewer.InkAnnotationSettings.InkColor = (System.Windows.Media.Color)ColorConverter.ConvertFromString(LineColor);
            PdfViewer.CursorMode = PdfViewerCursorMode.SelectTool;
            PdfViewer.AnnotationMode = PdfDocumentView.PdfViewerAnnotationMode.Ink;
            UpdateButtons(PdfInkImage);
        }

        private void PdfLine_Click(object sender, RoutedEventArgs e)
        {
            if(LineColor is null)
            {
                return;
            }
            PdfViewer.LineAnnotationSettings.LineColor = (System.Windows.Media.Color)ColorConverter.ConvertFromString(LineColor);
            PdfViewer.CursorMode = PdfViewerCursorMode.SelectTool;
            PdfViewer.AnnotationMode = PdfDocumentView.PdfViewerAnnotationMode.Line;
            UpdateButtons(PdfLineImage);
        }

        private void PdfRectangle_Click(object sender, RoutedEventArgs e)
        {
            PdfViewer.RectangleAnnotationSettings.RectangleColor = (System.Windows.Media.Color)ColorConverter.ConvertFromString(LineColor);
            PdfViewer.CursorMode = PdfViewerCursorMode.SelectTool;
            PdfViewer.AnnotationMode = PdfDocumentView.PdfViewerAnnotationMode.Rectangle;
            UpdateButtons(PdfRectangleImage);
        }

        private void PdfCircle_Click(object sender, RoutedEventArgs e)
        {
            PdfViewer.CircleAnnotationSettings.CircleColor = (System.Windows.Media.Color)ColorConverter.ConvertFromString(LineColor);
            PdfViewer.CursorMode = PdfViewerCursorMode.SelectTool;
            PdfViewer.AnnotationMode = PdfDocumentView.PdfViewerAnnotationMode.Circle;
            UpdateButtons(PdfCircleImage);
        }

        private void PdfFreeText_Click(object sender, RoutedEventArgs e)
        {
            PdfViewer.FreeTextAnnotationSettings.FontSize = TextSize;
            PdfViewer.FreeTextAnnotationSettings.FontColor = (System.Windows.Media.Color)ColorConverter.ConvertFromString(LineColor);
            PdfViewer.CursorMode = PdfViewerCursorMode.SelectTool;
            PdfViewer.AnnotationMode = PdfDocumentView.PdfViewerAnnotationMode.FreeText;
            UpdateButtons(PdfFreeTextImage);
        }

        private void PdfOKStamp_Click(object sender, RoutedEventArgs e)
        {
            //PdfViewer.CursorMode = PdfViewerCursorMode.SelectTool;
            //PdfViewer.AnnotationMode = PdfDocumentView.PdfViewerAnnotationMode.None;
            //AnnotationType = EntityDocumentAnnotationType.OKStamp;
            //UpdateButtons(PdfOKImage);
        }

        private void PdfWarningStamp_Click(object sender, RoutedEventArgs e)
        {
            //PdfViewer.CursorMode = PdfViewerCursorMode.SelectTool;
            //PdfViewer.AnnotationMode = PdfDocumentView.PdfViewerAnnotationMode.None;
            //AnnotationType = EntityDocumentAnnotationType.WarningStamp;
            //UpdateButtons(PdfWarningImage);
        }

        private void PdfErrorStamp_Click(object sender, RoutedEventArgs e)
        {
            //PdfViewer.CursorMode = PdfViewerCursorMode.SelectTool;
            //PdfViewer.AnnotationMode = PdfDocumentView.PdfViewerAnnotationMode.None;
            //PdfViewer.CursorMode = PdfViewerCursorMode.SelectTool;
            //AnnotationType = EntityDocumentAnnotationType.ErrorStamp;
            //UpdateButtons(PdfErrorImage);
        }


        private EntityDocumentAnnotationType AnnotationType = EntityDocumentAnnotationType.OKStamp;

        #endregion
    }
}