using System.Threading.Tasks;
using Elwig.Helpers;
using Elwig.Windows;
using System.Diagnostics;
using System;
using System.IO;
using System.Collections.Generic;
using System.Windows;
using System.Text.RegularExpressions;
using System.Linq;

namespace Elwig.Documents {
    public static class Pdf {

        private static readonly string PdfToPrinter = App.ExePath + "PDFtoPrinter.exe";
        private static readonly string WinziPrint = App.ExePath + "WinziPrint.exe";
        private static Process? WinziPrintProc;
        public static bool IsReady => WinziPrintProc != null;


        public static async Task Init(Action evtHandler) {
            var p = new Process() { StartInfo = new() {
                FileName = WinziPrint,
                Arguments = $"-p -e utf-8 -d \"{App.TempPath}\" -",
                CreateNoWindow = true,
                UseShellExecute = false,
                RedirectStandardInput = true,
                RedirectStandardOutput = true
            } };
            p.Start();
            WinziPrintProc = p;
            evtHandler();
        }

        public static async Task<IEnumerable<int>> Convert(string htmlPath, string pdfPath, IProgress<double>? progress = null) {
            return await Convert(new string[] { htmlPath }, pdfPath, progress);
        }

        public static async Task<IEnumerable<int>> Convert(IEnumerable<string> htmlPath, string pdfPath, IProgress<double>? progress = null) {
            if (WinziPrintProc == null) throw new InvalidOperationException("The WinziPrint process has not been initialized yet");
            progress?.Report(0.0);
            await WinziPrintProc.StandardInput.WriteLineAsync($"{string.Join(';', htmlPath)};{pdfPath}");
            while (true) {
                var line = await WinziPrintProc.StandardOutput.ReadLineAsync() ?? throw new IOException("Invalid response from WinziPrint");
                if (line.StartsWith("error:")) {
                    MessageBox.Show(line[6..].Trim(), "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
                    return Array.Empty<int>();
                } else if (line.StartsWith("progress:")) {
                    var parts = line[9..].Trim().Split('/').Select(int.Parse).ToArray();
                    progress?.Report(parts[0] / (double)parts[1]);
                } else if (line.StartsWith("success:")) {
                    var m = Regex.Match(line, @"\(([0-9, ]+)\)");
                    return m.Groups[1].Value.Split(", ").Select(int.Parse);
                }
            }
        }

        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("/s");
            p.StartInfo.ArgumentList.Add($"copies={copies}");
            p.Start();
            await p.WaitForExitAsync();
        }
    }
}