using System;
using System.Threading.Tasks;
using System.Windows;
using PdfSharp.Pdf.IO;
using PuppeteerSharp;
using Elwig.Helpers;
using Elwig.Windows;
using System.Diagnostics;

namespace Elwig.Documents {
    public static class Pdf {

        private static readonly string Chromium = @"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe";
        private static readonly string PdfToPrinter = App.ExePath + "PDFtoPrinter.exe";
        private static IBrowser? Browser = null;
        public static bool IsReady => Browser != null;

        public static async Task Init(Action evtHandler) {
            Browser = await Puppeteer.LaunchAsync(new LaunchOptions {
                Headless = true,
                ExecutablePath = Chromium,
                // paged.js uses XHRs to load styles, so this is needed
                Args = new[] { "--allow-file-access-from-files" },
            });
            evtHandler();
        }

        public static async Task Close() {
            if (Browser == null) return;
            await Browser.CloseAsync();
            Browser = null;
        }

        public static async Task Convert(string htmlPath, string pdfPath) {
            if (Browser == null) throw new InvalidOperationException("The puppeteer engine has not been initialized yet");
            using var page = await Browser.NewPageAsync();
            page.Console += OnConsole;
            await page.GoToAsync($"file://{htmlPath}");
            await page.EvaluateFunctionAsync("async () => { await window.PagedPolyfill.preview(); }");
            await page.PdfAsync(pdfPath, new() {
                PreferCSSPageSize = true,
                //Format = PaperFormat.A4,
                DisplayHeaderFooter = false,
                MarginOptions = new() {
                    Top = "0mm",
                    Right = "0mm",
                    Bottom = "0mm",
                    Left = "0mm",
                },
            });
        }

        private static void OnConsole(object? sender, ConsoleEventArgs e) {
            MessageBox.Show(e.Message.Text);
        }

        public static void UpdateMetadata(string path, string title, string author) {
            using var doc = PdfReader.Open(path);
            doc.Info.Title = title;
            doc.Info.Author = author;
            doc.Save(path);
        }

        public static void Show(TempFile file, string title) {
            App.MainDispatcher.BeginInvoke(() => {
                var w = new DocumentViewerWindow(title, file);
                w.Show();
            });
        }

        public static void Show(string path, string title) {
            App.MainDispatcher.BeginInvoke(() => {
                var w = new DocumentViewerWindow(title, path);
                w.Show();
            });
        }

        public static async Task Print(string path, int copies = 1) {
            var p = new Process() { StartInfo = new() { FileName = PdfToPrinter } };
            p.StartInfo.ArgumentList.Add(path);
            p.StartInfo.ArgumentList.Add($"copies={copies}");
            p.Start();
            await p.WaitForExitAsync();
        }
    }
}