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);
}
}
}