using System.Diagnostics;
using Valg.EVA.Skanning.Configuration;
using Valg.EVA.Skanning.ContainerExtensions;
using Valg.EVA.Skanning.UserInterfaceElements.ApplicationEvents;
using Valg.EVA.Skanning.UserInterfaceElements.Bootstrapping;

using Unity;
using CommonServiceLocator;
using System;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows;
using Prism.Events;
using Valg.EVA.Skanning.Diagnostics;
using Valg.EVA.Skanning.UserInterfaceElements;
using Valg.EVA.Skanning.UserInterfaceElements.ErrorHandling;
using Unity.ServiceLocation;

namespace Valg.EVA.Skanning.JobManagement.Startup
{
    public partial class App
    {
        private UnityContainer container;

        protected override void OnStartup(StartupEventArgs e)
        {
            var processName = Process.GetCurrentProcess().ProcessName;

            var applicationConfigurationReader = new ApplicationConfigurationReader(new DefaultConfigurationFileProvider());
            var configurator = new InProcessLoggingSinkConfigurator(new DiagnosticsConfiguration(applicationConfigurationReader));
            configurator.ConfigureLoggingSinks(processName);

            EvaSkanningEventSource.Log.StartupInitiated(processName);

            Task.Run(() => SystemInformationCollector.CollectAndReportSystemInformation());

            base.OnStartup(e);

            try
            {
                var assemblyName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().ManifestModule.Name);
                WebBrowserHelper.FixBrowserVersion(assemblyName);

                container = new UnityContainer();
                container.RegisterInstance(typeof(IApplicationConfigurationReader), applicationConfigurationReader, ContainerLifetimes.CreateContainerControlledLifetimeManager());

                AssemblyInstaller.ForceLoadAssemblies();

                AssemblyInstaller.InstallAssemblies(container);

                container.RegisterInstance(typeof(IUnityContainer), container);
                ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container));
                AssemblyInstaller.StartStartableComponents(container);

                SubscribeToApplicationWideEvents(container);

                PublishBootstrappingCompletedEvent(container);
            }
            catch (Exception exception)
            {
                ApplicationUnhandledExceptionHandler.LogErrorAndShowMessageBox(exception);
                Environment.Exit(0);
            }
            finally
            {
                EvaSkanningEventSource.Log.StartupCompleted(processName);
            }
        }

        private void SubscribeToApplicationWideEvents(UnityContainer container)
        {
            var eventAggregator = container.Resolve<IEventAggregator>();
            var restartApplicationRequestedEvent = eventAggregator.GetEvent<RestartApplicationRequestedEvent>();
            restartApplicationRequestedEvent.Subscribe(p => RestartApplication());
        }

        private void RestartApplication()
        {                        
            Process.Start(ResourceAssembly.Location);
            Current.Shutdown();
        }

        private static void PublishBootstrappingCompletedEvent(UnityContainer container)
        {
            var eventAggregator = container.Resolve<IEventAggregator>();
            var bootCompleted = eventAggregator.GetEvent<ContainerBootstrappingCompletedEvent>();
            bootCompleted.Publish(new ContainerBootstrappingCompletedEventArgs());
        }
    }
}
