using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.BL; using Tango.BL.Entities; using Tango.Integration.Operation; using Tango.Settings; using Tango.PPC.Common.Application; using Tango.Core.DI; using Tango.PPC.Common; using System.Windows; using Tango.Core; using System.IO; using Tango.Core.Helpers; using Tango.PPC.Common.Modules; using System.Windows.Threading; using Tango.Transport.Adapters; using Tango.PMR.Connection; using Tango.PPC.Common.Connection; using Tango.SQLExaminer; using System.Data.SqlClient; using Tango.BL.Builders; using Tango.PPC.Common.Threading; using System.Diagnostics; using Tango.PPC.Common.EventLogging; using Tango.BL.Enumerations; namespace Tango.PPC.UI.PPCApplication { /// /// Represents the default PPC application manager. /// /// /// public class DefaultPPCApplicationManager : ExtendedObject, IPPCApplicationManager { private List _notifiedViewModels; private IMachineProvider _machineProvider; private Machine _machine; private IDispatcherProvider _dispatcher; private IEventLogger _eventLogger; /// /// Occurs when the application has started. /// public event EventHandler ApplicationStarted; /// /// Occurs when all PPC modules are ready and initialized. /// public event EventHandler ModulesInitialized; /// /// Occurs when the application is ready and all modules are views are loaded. /// public event EventHandler ApplicationReady; /// /// Occurs when machine setup is required. /// public event EventHandler SetupRequired; /// /// Occurs when the main window content has been rendered. /// public event EventHandler ContentRendered; /// /// Occurs when the application has encountered an error when initializing. /// public event EventHandler ApplicationInitializationError; /// /// Gets a value indicating whether the application is shutting down. /// public bool IsShuttingDown { get; private set; } /// /// Gets the application version. /// public Version Version { get { return AssemblyHelper.GetCurrentAssemblyVersion(); } } /// /// Gets the application build date. /// public String BuildDate { get { return AssemblyHelper.GetCurrentAssemblyBuildDate().ToShortDateString(); } } /// /// Initializes a new instance of the class. /// public DefaultPPCApplicationManager(IMachineProvider machineProvider, IDispatcherProvider dispatcherProvider, IEventLogger eventLogger) { _machineProvider = machineProvider; _dispatcher = dispatcherProvider; _eventLogger = eventLogger; ; if (!DesignMode) { _notifiedViewModels = new List(); MainWindow.Instance.ContentRendered += (_, __) => { OnMainWindowContentRendered(); }; } } /// /// Called when the main window content has been rendered /// private void OnMainWindowContentRendered() { LogManager.Log("Main window content rendered."); ContentRendered?.Invoke(this, new EventArgs()); StartApplication(); } private async void StartApplication() { PPCSettings settings = null; bool initialized = false; await Task.Factory.StartNew(() => { try { LogManager.Log("Reading PPC settings..."); settings = SettingsManager.Default.GetOrCreate(); LogManager.Log(settings.ToJsonString()); LogManager.Log("Reading Core settings..."); var coreSettings = SettingsManager.Default.GetOrCreate(); if (!SettingsManager.Default.IsFileExists()) { LogManager.Log("Settings file does not exists. creating..."); settings.Save(); } if (App.StartupArgs.Contains("-update_ok")) { LogManager.Log("Application started with '-update_ok' startup arguments. The application has been successfully updated."); settings.ApplicationState = ApplicationStates.Ready; settings.Save(); } if (settings.ApplicationState == ApplicationStates.Ready) { LogManager.Log("Initializing ObservablesStaticCollections..."); ObservablesStaticCollections.Instance.Initialize(); LogManager.Log("Loading machine from database..."); _machine = new MachineBuilder(ObservablesContext.CreateDefault()).SetFirst().WithOrganization().WithConfiguration().Build(); } initialized = true; } catch (Exception ex) { LogManager.Log(ex, "Application Initialization Error!"); ApplicationInitializationError?.Invoke(this, ex); return; } }); if (initialized) { try { if (settings.ApplicationState == ApplicationStates.PreSetup) { LogManager.Log($"The application is in {settings.ApplicationState} state. database initialization skipped. Invoking setup required event!"); SetupRequired?.Invoke(this, new EventArgs()); } else { PostDbInitialize(); } } catch (Exception ex) { LogManager.Log(ex, "Application Post Initialization Error!"); ApplicationInitializationError?.Invoke(this, ex); return; } } } /// /// Called when the database has been initialized /// private void PostDbInitialize() { LogManager.Log($"Raising {nameof(ApplicationStarted)} event..."); _eventLogger.Log(EventTypes.ApplicationStarted, "Application Started!"); ApplicationStarted?.Invoke(this, new EventArgs()); LogManager.Log("Invoking PPC view models OnApplicationStarted methods..."); foreach (var vm in TangoIOC.Default.GetAllInstancesByBase()) { if (!_notifiedViewModels.Contains(vm)) { LogManager.Log($"Invoking {vm.GetType().Name}.OnApplicationStarted..."); vm.OnApplicationStarted(); _notifiedViewModels.Add(vm); } } LogManager.Log("Waiting for IPPCModuleLoader instance injection..."); TangoIOC.Default.GetInstanceWhenAvailable((loader) => { LogManager.Log("Module loader instance has been registered. Registering for the ModulesLoaded event..."); loader.ModulesLoaded += (x, y) => { LogManager.Log("Loading modules views"); _dispatcher.InvokeBlock(() => { foreach (var module in TangoIOC.Default.GetInstance().UserModules) { if (!Views.LayoutView.Instance.NavigationControl.Elements.ToList().Exists(m => m.GetType() == module.MainViewType)) { LogManager.Log("Loading module view " + module.Name + "..."); FrameworkElement view = Activator.CreateInstance(module.MainViewType) as FrameworkElement; SharedUI.Controls.NavigationControl.SetNavigationName(view, module.Name); Views.LayoutView.Instance.NavigationControl.Elements.Add(view); } } }); LogManager.Log($"{loader.UserModules.Count} modules loaded."); LogManager.Log($"Invoking {nameof(ModulesInitialized)} event."); ModulesInitialized?.Invoke(this, new EventArgs()); FinalizeModuleInitialization(); }; }); } /// /// Finalizes the module initialization. /// private void FinalizeModuleInitialization() { LogManager.Log("Finalizing application initialization..."); LogManager.Log("Initializing Machine Provider..."); _machineProvider.Init(_machine); LogManager.Log("Applications initialization completed!"); LogManager.Log("Checking for un-notified PPC view models..."); foreach (var vm in TangoIOC.Default.GetAllInstancesByBase()) { if (!_notifiedViewModels.Contains(vm)) { LogManager.Log($"Invoking {vm.GetType().Name}.OnApplicationStarted..."); vm.OnApplicationStarted(); _notifiedViewModels.Add(vm); } } _dispatcher.Invoke(() => { LogManager.Log($"Invoking {nameof(ApplicationReady)} event."); ApplicationReady?.Invoke(this, new EventArgs()); LogManager.Log("Notifying view models about application ready..."); foreach (var vm in TangoIOC.Default.GetAllInstancesByBase()) { LogManager.Log($"Invoking {vm.GetType().Name}.OnApplicationReady..."); vm.OnApplicationReady(); } }); } /// /// Shutdown the application. /// public void ShutDown() { //TODO: Needs some work on logging and shutdown procedures! Do I really need this? LogManager.Log("Shutting down application..."); IsShuttingDown = true; foreach (var vm in TangoIOC.Default.GetAllInstancesByBase()) { vm.OnApplicationShuttingDown(); } } /// /// Restarts the application. /// public void Restart() { Process.Start(Application.ResourceAssembly.Location); Environment.Exit(0); } } }