using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using Gtk;
using Hiperscan.GtkExtensions.Widgets;
using Hiperscan.Unix;
using Microsoft.Win32;

namespace Hiperscan.Extensions.Acquisition
{
    public partial class TestProcess
    {
        public static event EventHandler Started = null;
        public static event EventHandler Succeded = null;
        public static event EventHandler Failed = null;
        public static event EventHandler ExecutionFailed = null;

        public static void Init()
        {
            bool is_windows = Environment.OSVersion.Platform != PlatformID.Unix;

            string quick_step_path = new FileInfo(Assembly.GetEntryAssembly().Location).Directory.FullName;

            if (is_windows)
            {
                TestProcess.MonoPath = Path.Combine(quick_step_path, "Mono", "bin", "mono.exe");
                TestProcess.Encoding = Encoding.GetEncoding(850);
            }
            else
            {
                TestProcess.MonoPath = "mono";
                TestProcess.Encoding = Encoding.UTF8;
            }


            TestProcess.CorrectiontoolExe = TestProcess.GetCorrectionToolExe(is_windows);
            TestProcess.EvaluationRegex = new Regex(@"\d+ spectra were successfully processed in this run\.");

            TestProcess.Started += TestProcess.OnStarted;
            TestProcess.Succeded += TestProcess.OnSucceded;
            TestProcess.Failed += TestProcess.OnFailed;
            TestProcess.ExecutionFailed += TestProcess.OnExecutionFailed;

            if (TestProcess.IsAvailable)
                Console.WriteLine("Acquisition plugin found correctiontool");
            else
                Console.WriteLine("Acquisition plugin found no correctiontool");

            Console.WriteLine("Acquisition plugin correctiontool: {0}", TestProcess.CorrectiontoolExe);
        }

        private static string GetCorrectionToolExe(bool is_windows)
        {
            try
            {
                if (is_windows == false)
                {
                    return "/usr/lib/correctiontool/CorrectionTool.exe";
                }

                string key_path = @"Software\Hiperscan\HiperScan CorrectionTool";
                RegistryKey correction_tool = Registry.LocalMachine.OpenSubKey(key_path);

                string name = (string)correction_tool.GetValue("InstallPath");
                return name;
            }
            catch(Exception)
            {
                return String.Empty;
            }
        }

        public static bool IsAvailable
        {
            get
            {
                try
                {
                    return FileIO.ExistsFile(TestProcess.CorrectiontoolExe);
                }
                catch(Exception)
                {
                    return false;
                }

            }
        }

        private static void OnStarted(object sender, EventArgs e)
        {
            Application.Invoke((sender2, e2) =>
            {
                TestProcess test_process = sender as TestProcess;

                string message = String.Format(Catalog.GetString("Processing spectra for series {0} ..."), test_process.SequenceNumber);
                TestProcess.WaitWindow = new WaitAndProgressWindow(Plugin.host.MainWindow, message);
                TestProcess.WaitWindow.BackgroundColor = new Gdk.Color(52, 53, 63);
                TestProcess.WaitWindow.FontColor = new Gdk.Color(255, 255, 255);
                TestProcess.WaitWindow.Pulse();
            });
        }

        private static void OnSucceded(object sender, EventArgs e)
        {
            Application.Invoke((sender2, e2) =>
            {
                TestProcess test_process = sender as TestProcess;
                TestProcess.WaitWindow?.Destroy();

                string message = Catalog.GetString("All spectra were successfully processed.");

                MessageDialog mdlg = new MessageDialog(Plugin.host.MainWindow,
                                                       Gtk.DialogFlags.Modal,
                                                       Gtk.MessageType.Info,
                                                       Gtk.ButtonsType.Ok,
                                                       message);

                mdlg.Run();
                mdlg.Destroy();
            });
        }

        private static void OnFailed(object sender, EventArgs e)
        {
            Application.Invoke((sender2, e2) =>
            {
                TestProcess test_process = sender as TestProcess;
                TestProcess.WaitWindow?.Destroy();



                string message = String.Format(Catalog.GetString("Could only process {0} of {1} spectra. Do you want delete the series {2}?"),
                                               test_process.NumberOfProcessed,
                                               test_process.NumberOfAcquisitions,
                                               test_process.sequence_number);

                MessageDialog mdlg = new MessageDialog(Plugin.host.MainWindow,
                                                      Gtk.DialogFlags.Modal,
                                                       Gtk.MessageType.Error,
                                                       Gtk.ButtonsType.YesNo,
                                                      message);

                Gtk.ResponseType response = (Gtk.ResponseType) mdlg.Run();
                mdlg.Destroy();

                if (response == ResponseType.Yes)
                {
                    TestProcess.DeleteSeries(test_process);
                }
            });
        }

        private static void OnExecutionFailed(object sender, EventArgs e)
        {
            Application.Invoke((sender2, e2) =>
            {
                TestProcess test_process = sender as TestProcess;
                TestProcess.WaitWindow?.Destroy();


                string message = String.Format(Catalog.GetString("Could not evaluate spectra: {0}"), 
                                               test_process.LastException.Message);

                MessageDialog mdlg = new MessageDialog(Plugin.host.MainWindow,
                                                       Gtk.DialogFlags.Modal,
                                                       Gtk.MessageType.Error,
                                                       Gtk.ButtonsType.Ok,
                                                       message);

                mdlg.Run();
                mdlg.Destroy();
            });
        }

        private static void DeleteSeries(TestProcess test_process)
        {
            try
            {
                string[] files = FileIO.GetFiles(test_process.RawDateDir, test_process.SequenceNumber + "*", SearchOption.AllDirectories);
                for (int i = 0; i < files.Length; i++)
                {
                    FileIO.DeleteFile(files[i]);
                }

            }
            catch (Exception ex)
            {
                string message = String.Format(Catalog.GetString("Could not delete spectra in series {0}: {1}"),
                                               test_process,
                                               ex.Message);

                MessageDialog mdlg = new MessageDialog(Plugin.host.MainWindow,
                                                       Gtk.DialogFlags.Modal,
                                                       Gtk.MessageType.Error,
                                                       Gtk.ButtonsType.Ok,
                                                       message);

                mdlg.Run();
                mdlg.Destroy();
            }
        }

        private static Regex EvaluationRegex { get; set; }

        private static string MonoPath { get; set; } = String.Empty;
        private static string CorrectiontoolExe { get; set; }
        private static bool? IsWindows { get; set; }
        public static Encoding Encoding { get; set; }

        private static WaitAndProgressWindow WaitWindow { get; set; }
    }
}
