using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Windows;
using System.Windows.Threading;

namespace Valg.EVA.Skanning.Scan.Startup
{
    public class Program
    {
        private static readonly Mutex mutex = new Mutex(true, "3305D8A1-B5FF-4F3D-8BDF-D52B6A3F8BB2");

        private static Thread applicationSplashScreenThread;
        private static SplashWindow applicationSplashScreen;
        private static ManualResetEvent manualResetEventSplashScreen;

        [STAThread]
        public static void Main(string[] args)
        {
            if (mutex.WaitOne(TimeSpan.Zero, true))
            {
                manualResetEventSplashScreen = new ManualResetEvent(false);
                applicationSplashScreenThread = new Thread(DisplayApplicationSplashScreen);
                applicationSplashScreenThread.SetApartmentState(ApartmentState.STA);
                applicationSplashScreenThread.IsBackground = true;

                applicationSplashScreenThread.Start();
                manualResetEventSplashScreen.WaitOne();

                var application = new WpfApplication(args);
                application.DispatcherUnhandledException += DisplayException; 
                application.Activated += ApplicationOnActivated;
                GenerateRpcCertificatesIfNecessary();
                KillAnyExistingScanRpcServers();
                StartScanRpcServer();

                application.Run();

                mutex.ReleaseMutex();
            }
            KillAnyExistingScanRpcServers();
        }

        private static void GenerateRpcCertificatesIfNecessary()
        {
            var psi = new ProcessStartInfo();
            psi.FileName = @"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe";
            psi.Arguments = $"-ExecutionPolicy RemoteSigned -File \"{Path.Combine(AssemblyDirectory, "Generate-RpcCertificates.ps1")}\"";
            psi.UseShellExecute = false;
            psi.CreateNoWindow = true;
            Process process = new Process();
            process.StartInfo = psi;
            process.Start();
            process.WaitForExit(10000);
        }

        public static string AssemblyDirectory
        {
            get
            {
                string codeBase = Assembly.GetExecutingAssembly().CodeBase;
                UriBuilder uri = new UriBuilder(codeBase);
                string path = Uri.UnescapeDataString(uri.Path);
                return Path.GetDirectoryName(path);
            }
        }



        private static void StartScanRpcServer()
        {
#if DEBUG
            var scanningRpcServerExe = Path.Combine(AssemblyDirectory, "../../../../../../","ScanningRpcService","bin","x86","debug","ScanningRpcService.exe");
            Process.Start(scanningRpcServerExe);

#else
            Process.Start(Path.Combine(AssemblyDirectory,"ScanningRpcService.exe"));
#endif
        }

        private static void KillAnyExistingScanRpcServers()
        {
            foreach (var process in Process.GetProcessesByName("ScanningRpcService"))
            {
                try
                {
                    process.Kill();
                }
                catch (Win32Exception)
                {
                }
                catch (NotSupportedException)
                {
                }
                catch (InvalidOperationException)
                {

                }

            }
        }

        private static void ApplicationOnActivated(object sender, EventArgs e)
        {
            try
            {
                var sdf = Application.Current;
                applicationSplashScreen?.Dispatcher?.BeginInvoke(DispatcherPriority.ContextIdle, (Action)(() =>
                {
                    applicationSplashScreen?.Close();
                    
                }));
            }
            catch (Exception)
            {
                
            }
        }

        private static void DisplayException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            var splashScreenDispatcher = applicationSplashScreen.Dispatcher;
            splashScreenDispatcher.BeginInvoke(DispatcherPriority.Normal,
                new Action(() => MessageBox.Show(applicationSplashScreen, $"Exception: {e.Exception.Message}" + Environment.NewLine + $"Details: {e.Exception.StackTrace}"))
                );

        }

        private static void DisplayApplicationSplashScreen()
        {
            applicationSplashScreen = new SplashWindow();
            applicationSplashScreen.Show();
            manualResetEventSplashScreen.Set();
            Dispatcher.Run();
        }
    }
}

