aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.CodeGeneration/ObservablesAdapterFile.cs
blob: f621497577efb1834d8cfc2b6c8db929def02bae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Tango.CodeGeneration
{
    /// <summary>
    /// Represents the Tango DAL layer observables adapter code file.
    /// </summary>
    /// <seealso cref="Tango.CodeGeneration.Class" />
    public class ObservablesAdapterFile : Class
    {

    }
}
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;
using Tango.PPC.Common.Notifications;
using Tango.PPC.Common.WatchDog;
using Tango.PPC.UI.Dialogs;
using Tango.Core.Threading;
using Tango.PPC.Common.Messages;
using Tango.Core.ExtensionMethods;

namespace Tango.PPC.UI.PPCApplication
{
    /// <summary>
    /// Represents the default PPC application manager.
    /// </summary>
    /// <seealso cref="Tango.Core.ExtendedObject" />
    /// <seealso cref="Tango.PPC.Common.Application.IPPCApplicationManager" />
    public class DefaultPPCApplicationManager : ExtendedObject, IPPCApplicationManager
    {
        private List<PPCViewModel> _notifiedViewModels;
        private IMachineProvider _machineProvider;
        private Machine _machine;
        private IDispatcherProvider _dispatcher;
        private IEventLogger _eventLogger;
        private IPPCModuleLoader _moduleLoader;
        private INotificationProvider _notificationProvider;
        private WatchDogServer _watchdogServer;
        private ObservablesContext _machineContext;
        private ActionTimer _screenLockTimer;

        /// <summary>
        /// Occurs when a system restart is required.
        /// </summary>
        public event EventHandler SystemRestartRequired;

        /// <summary>
        /// Occurs when the application has started.
        /// </summary>
        public event EventHandler ApplicationStarted;

        /// <summary>
        /// Occurs when all PPC modules are ready and initialized.
        /// </summary>
        public event EventHandler ModulesInitialized;

        /// <summary>
        /// Occurs when the application is ready and all modules are views are loaded.
        /// </summary>
        public event EventHandler ApplicationReady;

        /// <summary>
        /// Occurs when machine setup is required.
        /// </summary>
        public event EventHandler SetupRequired;

        /// <summary>
        /// Occurs when the main window content has been rendered.
        /// </summary>
        public event EventHandler ContentRendered;

        /// <summary>
        /// Occurs when the application has encountered an error when initializing.
        /// </summary>
        public event EventHandler<Exception> ApplicationInitializationError;

        /// <summary>
        /// Gets a value indicating whether the application is shutting down.
        /// </summary>
        public bool IsShuttingDown { get; private set; }

        private bool _isInTechnicianMode;
        /// <summary>
        /// Gets a value indicating whether the application is in technician mode.
        /// </summary>
        public bool IsInTechnicianMode
        {
            get { return _isInTechnicianMode; }
            set { _isInTechnicianMode = value; RaisePropertyChangedAuto(); }
        }

        /// <summary>
        /// Gets the application version.
        /// </summary>
        public Version Version
        {
            get
            {
                return AssemblyHelper.GetCurrentAssemblyVersion();
            }
        }

        /// <summary>
        /// Gets the application build date.
        /// </summary>
        public String BuildDate
        {
            get
            {
                return AssemblyHelper.GetCurrentAssemblyBuildDate().ToShortDateString();
            }
        }

        /// <summary>
        /// Gets the application startup date.
        /// </summary>
        public DateTime StartUpDate { get; private set; }

        private bool _isScreenLocked;
        /// <summary>
        /// Gets or sets a value indicating whether the screen is currently locked.
        /// </summary>
        public bool IsScreenLocked
        {
            get { return _isScreenLocked; }
            set { _isScreenLocked = value; RaisePropertyChangedAuto(); }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DefaultPPCApplicationManager"/> class.
        /// </summary>
        public DefaultPPCApplicationManager(IMachineProvider machineProvider, IDispatcherProvider dispatcherProvider, IEventLogger eventLogger, IPPCModuleLoader moduleLoader, INotificationProvider notificationProvider)
        {
            _notificationProvider = notificationProvider;
            _machineProvider = machineProvider;
            _dispatcher = dispatcherProvider;
            _eventLogger = eventLogger;
            _moduleLoader = moduleLoader;

            if (!DesignMode)
            {
                _notifiedViewModels = new List<PPCViewModel>();

                MainWindow.Instance.ContentRendered += (_, __) =>
                {
                    OnMainWindowContentRendered();
                };
            }
        }

        /// <summary>
        /// Called when the main window content has been rendered
        /// </summary>
        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;
            bool isAfterSetup = false;

            StartUpDate = DateTime.Now;

            await Task.Factory.StartNew(() =>
            {
                try
                {
                    LogManager.Log("Reading PPC settings...");
                    settings = SettingsManager.Default.GetOrCreate<PPCSettings>();

                    LogManager.Log(settings.ToJsonString());

                    //Start watchdog
                    _watchdogServer = new WatchDogServer(Application.Current.Dispatcher);
#if !DEBUG

                    if (settings.EnableWatchDog)
                    {
                        _watchdogServer.Start();
                    }
#endif

                    LogManager.Log("Reading Core settings...");
                    var coreSettings = SettingsManager.Default.GetOrCreate<CoreSettings>();

                    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.");

                        if (settings.ApplicationState == ApplicationStates.PreSetup)
                        {
                            isAfterSetup = true;
                            LogManager.Log("System restart is required.");
                        }

                        settings.ApplicationState = ApplicationStates.Ready;
                        settings.Save();

                        if (isAfterSetup)
                        {
                            SystemRestartRequired?.Invoke(this, new EventArgs());
                            return;
                        }
                    }

                    if (settings.ApplicationState == ApplicationStates.Ready)
                    {
                        LogManager.Log("Initializing ObservablesStaticCollections...");
                        ObservablesStaticCollections.Instance.Initialize();
                        LogManager.Log("Loading machine from database...");
                        _machineContext = ObservablesContext.CreateDefault();
                        _machine = new MachineBuilder(_machineContext).SetFirst().WithVersion().WithSettings().WithOrganization().WithConfiguration().WithSpools().WithCats().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 || settings.ApplicationState == ApplicationStates.FactoryRestore)
                    {
                        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;
                }
            }
        }

        /// <summary>
        /// Called when the database has been initialized
        /// </summary>
        private void PostDbInitialize()
        {
            LogManager.Log($"Raising {nameof(ApplicationStarted)} event...");

            _eventLogger.Log(EventTypes.APPLICATION_STARTED, "Application Started!");
            ApplicationStarted?.Invoke(this, new EventArgs());

            LogManager.Log("Invoking PPC view models OnApplicationStarted methods...");
            foreach (var vm in TangoIOC.Default.GetAllInstancesByBase<PPCViewModel>())
            {
                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<IPPCModuleLoader>((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<IPPCModuleLoader>().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();
                };
            });
        }

        /// <summary>
        /// Finalizes the module initialization.
        /// </summary>
        private void FinalizeModuleInitialization()
        {
            var settings = SettingsManager.Default.GetOrCreate<PPCSettings>();

            LogManager.Log("Finalizing application initialization...");

            LogManager.Log("Initializing Machine Provider...");
            _machineProvider.Init(_machine, _machineContext);

            LogManager.Log("Applications initialization completed!");

            LogManager.Log("Checking for un-notified PPC view models...");
            foreach (var vm in TangoIOC.Default.GetAllInstancesByBase<PPCViewModel>())
            {
                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<PPCViewModel>())
                {
                    LogManager.Log($"Invoking {vm.GetType().Name}.OnApplicationReady...");
                    vm.OnApplicationReady();
                }

                if (settings.EnableTechnicianModeByDefault)
                {
                    EnterTechnicianMode(false);
                }

                if (settings.EnableLockScreen)
                {
                    _screenLockTimer = new ActionTimer(settings.LockScreenTimeout);
                    _screenLockTimer.ResetReplace(ScreenLockTimerAction);
                }

                TangoMessenger.Default.Register<MachineSettingsSavedMessage>((msg) =>
                {
                    if (_screenLockTimer != null)
                    {
                        _screenLockTimer.Dispose();
                        _screenLockTimer = null;
                    }

                    if (settings.EnableLockScreen)
                    {
                        _screenLockTimer = new ActionTimer(settings.LockScreenTimeout);
                        _screenLockTimer.ResetReplace(ScreenLockTimerAction);
                    }
                });
            });
        }

        /// <summary>
        /// Shutdown the application.
        /// </summary>
        public void ShutDown()
        {
            if (IsShuttingDown) return;

            IsShuttingDown = true;

            try
            {
                LogManager.Log("Shutting down application...");
                _watchdogServer.Dispose();

                foreach (var vm in TangoIOC.Default.GetAllInstancesByBase<PPCViewModel>())
                {
                    vm.OnApplicationShuttingDown();
                }
            }
            catch { }

            Environment.Exit(0);
        }

        /// <summary>
        /// Restarts the application.
        /// </summary>
        public void Restart()
        {
            if (IsShuttingDown) return;

            IsShuttingDown = true;

            try
            {
                LogManager.Log("Restarting the application...");

                _watchdogServer.Dispose();

                foreach (var vm in TangoIOC.Default.GetAllInstancesByBase<PPCViewModel>())
                {
                    vm.OnApplicationShuttingDown();
                }
            }
            catch { }

            try
            {
                if (_machineProvider.MachineOperator.State == Transport.TransportComponentState.Connected)
                {
                    _machineProvider.MachineOperator.Adapter.Disconnect().Wait();
                }
            }
            catch { }

            Process.Start(Application.ResourceAssembly.Location);
            Environment.Exit(0);
        }

        /// <summary>
        /// Runs the updater utility and exits the application.
        /// </summary>
        public void UpdateApplication(String updaterPath, String arguments)
        {
            if (IsShuttingDown) return;

            IsShuttingDown = true;

            try
            {
                _watchdogServer.Dispose();

                foreach (var vm in TangoIOC.Default.GetAllInstancesByBase<PPCViewModel>())
                {
                    vm.OnApplicationShuttingDown();
                }
            }
            catch { }

            LogManager.Log($"Executing '{updaterPath}' with arguments '{arguments}'...");
            Process.Start(updaterPath, arguments);

            LogManager.Log("Terminating application...");
            Environment.Exit(0);
        }

        /// <summary>
        /// Enteres the application technician mode.
        /// </summary>
        public async void EnterTechnicianMode(bool displayNotification = true)
        {
            if (displayNotification)
            {
                var vm = await _notificationProvider.ShowDialog<TechnicianModeLoginViewVM>();

                if (vm.DialogResult)
                {
                    if (vm.Password == "Aa123456")
                    {
                        IsInTechnicianMode = true;
                        _moduleLoader.AllModules.ToList().ForEach(x => x.OnTechnicianEntered());
                        await _notificationProvider.ShowInfo("Technician mode is now enabled.");
                    }
                    else
                    {
                        await _notificationProvider.ShowError("Invalid technician mode password.");
                        EnterTechnicianMode();
                    }
                }
            }
            else
            {
                IsInTechnicianMode = true;
                _moduleLoader.AllModules.ToList().ForEach(x => x.OnTechnicianEntered());
            }
        }

        /// <summary>
        /// Exits the application technician mode.
        /// </summary>
        public void ExitTechnicianMode()
        {
            IsInTechnicianMode = false;
            _moduleLoader.AllModules.ToList().ForEach(x => x.OnTechnicianExited());
            _notificationProvider.ShowInfo("Technician mode is now disabled.");
        }

        /// <summary>
        /// Invokes a dialog for entering a password and releasing the screen lock.
        /// </summary>
        public async void ReleaseScreenLock()
        {
            if (IsScreenLocked)
            {
                var vm = await _notificationProvider.ShowDialog<ScreenLockViewVM>();

                if (vm.DialogResult)
                {
                    if (vm.Password == SettingsManager.Default.GetOrCreate<PPCSettings>().LockScreenPassword)
                    {
                        IsScreenLocked = false;
                        ResetScreenLockTimer();
                    }
                }
            }
        }

        public void ResetScreenLockTimer()
        {
            if (_screenLockTimer != null)
            {
                _screenLockTimer.ResetReplace(ScreenLockTimerAction);
            }
        }

        private void ScreenLockTimerAction()
        {
            IsScreenLocked = true;
        }
    }
}