using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Tango.Core.Helpers;
using Tango.MachineStudio.Common.StudioApplication;
using Tango.MachineStudio.Common.Navigation;
using System.Reflection;
using System.Collections;
using Tango.Core;
using Tango.Logging;
using Tango.MachineStudio.Common.Modules;
using Tango.MachineStudio.Common;
using Tango.Settings;
using System.Windows;
using Tango.Integration.ExternalBridge;
using Tango.MachineStudio.Common.EventLogging;
using Tango.BL.Enumerations;
using Tango.Core.DI;
using Tango.BL.Entities;
using Tango.BL;
using Tango.MachineStudio.UI.ViewModels;
using Tango.MachineStudio.Common.Notifications;
using Tango.MachineStudio.UI.Views;
using Tango.Integration.Operation;
using Tango.MachineStudio.UI.Windows;
using Tango.BL.Builders;
namespace Tango.MachineStudio.UI.StudioApplication
{
///
/// Represents the default Machine Studio Application Manager.
///
///
///
public class DefaultStudioApplicationManager : ExtendedObject, IStudioApplicationManager
{
private INavigationManager _navigationManager;
private IStudioModuleLoader _moduleLoader;
private INotificationProvider _notification;
private List _openedWindows;
private List _notified_view_models;
private bool _isDialogShown;
///
/// Occurs when the application is ready.
///
public event EventHandler ApplicationReady;
///
/// Occurs when the connected machine session has been lost and an automatic reconnection with the last machine is required.
///
public event EventHandler ReconnectionRequired;
///
/// Initializes a new instance of the class.
///
/// The navigation manager.
public DefaultStudioApplicationManager(INavigationManager navigationManager, IStudioModuleLoader moduleLoader, INotificationProvider notification)
{
_moduleLoader = moduleLoader;
_navigationManager = navigationManager;
_notification = notification;
_openedWindows = new List();
_notified_view_models = new List();
Application.Current.MainWindow.ContentRendered += (_, __) =>
{
TangoIOC.Default.GetAllInstancesByBase().ToList().ForEach(x => x.OnApplicationStarted());
};
}
///
/// Gets a value indicating whether Machine Studio is shutting down.
///
public bool IsShuttingDown { get; private set; }
///
/// Occurs when the connected machine property has changed.
///
public event EventHandler ConnectedMachineChanged;
///
/// Gets or sets the machine.
///
public Machine Machine { get; private set; }
private IExternalBridgeClient _connectedMachine;
///
/// Gets or sets the currently connected machine if any.
///
public IExternalBridgeClient ConnectedMachine
{
get { return _connectedMachine; }
private set
{
if (_connectedMachine != value)
{
_connectedMachine = value;
RaisePropertyChangedAuto();
RaisePropertyChanged(nameof(IsMachineConnected));
RaisePropertyChanged(nameof(IsMachineConnectedViaTCP));
if (_connectedMachine != null)
{
_connectedMachine.StateChanged -= ConnectedMachine_StateChanged;
_connectedMachine.StateChanged += ConnectedMachine_StateChanged;
}
ConnectedMachineChanged?.Invoke(this, _connectedMachine);
}
}
}
///
/// Gets a value indicating whether the is valid and connected through TCP/IP.
///
public bool IsMachineConnectedViaTCP
{
get { return IsMachineConnected && ConnectedMachine is ExternalBridgeTcpClient; }
}
///
/// Handles the state changed event.
///
/// The sender.
/// The e.
private void ConnectedMachine_StateChanged(object sender, Transport.TransportComponentState e)
{
if (e == Transport.TransportComponentState.Disconnected || e == Transport.TransportComponentState.Failed)
{
ConnectedMachine = null;
if (e == Transport.TransportComponentState.Failed)
{
String failed_reason = (sender as IMachineOperator).FailedStateException.Message;
if (!_isDialogShown)
{
_isDialogShown = true;
ConnectionLostViewVM vm = new ConnectionLostViewVM()
{
Exception = failed_reason,
AutoReconnect = true,
};
InvokeUI(() =>
{
_notification.ShowModalDialog(vm, (x) =>
{
_isDialogShown = false;
ReconnectionRequired?.Invoke(this, new EventArgs());
}, () =>
{
_isDialogShown = false;
});
});
}
}
}
}
///
/// Gets a value indicating whether the is valid.
///
public bool IsMachineConnected
{
get { return ConnectedMachine != null; }
}
///
/// Gets the machine studio application version.
///
public Version Version
{
get
{
return AssemblyHelper.GetCurrentAssemblyVersion();
}
}
///
/// Shutdown the application.
///
public async void ShutDown()
{
if (IsShuttingDown) return;
IsShuttingDown = true;
try
{
Rect r = new Rect(
MainWindow.Instance.Left,
MainWindow.Instance.Top,
MainWindow.Instance.Width,
MainWindow.Instance.Height);
await Task.Factory.StartNew(async () =>
{
try
{
//Do Shutdown Procedures...
foreach (var vm in TangoIOC.Default.GetAllInstancesByBase())
{
try
{
var result = await vm.OnShutdownRequest();
if (!result)
{
IsShuttingDown = false;
return;
}
}
catch (Exception ex)
{
LogManager.Log(ex, "Error on shutdown request with " + vm.GetType().Name);
}
}
foreach (var vm in TangoIOC.Default.GetAllInstancesByBase())
{
vm.OnShuttingDown();
}
var settings = SettingsManager.Default.GetOrCreate();
settings.LastBounds = r;
settings.StudioModulesBounds.Clear();
foreach (var window in _openedWindows.OfType())
{
window.Invoke(() =>
{
var context = window.ModuleContext;
if (context != null)
{
settings.StudioModulesBounds.Add(new MachineStudioSettings.StudioModuleBounds()
{
Bounds = window.RestoreBounds,
State = window.WindowState,
Name = context.Module.Name,
});
}
});
}
var mainViewVM = TangoIOC.Default.GetInstance();
settings.LastMainModuleName = mainViewVM.CurrentModule != null ? mainViewVM.CurrentModule.Name : null;
try
{
SettingsManager.Default.Save();
}
catch (Exception ex)
{
LogManager.Log(ex, "Error saving settings.");
}
await _navigationManager.NavigateTo(NavigationView.ShutdownView);
Thread.Sleep(1500);
foreach (var window in _openedWindows)
{
ThreadsHelper.InvokeUI(() =>
{
window.Close();
});
}
try
{
if (ConnectedMachine != null)
{
ConnectedMachine.Disconnect().Wait();
}
}
catch (Exception ex)
{
LogManager.Log(ex, "Error disconnecting from machine.");
}
var eventLogger = TangoIOC.Default.GetInstance();
if (eventLogger != null)
{
//eventLogger.Log(EventTypes.APPLICATION_TERMINATED, "Application Terminated!");
eventLogger.FlushAll();
}
Thread.Sleep(1500);
Environment.Exit(0);
}
catch
{
Environment.Exit(0);
}
});
}
catch (Exception ex)
{
IsShuttingDown = false;
LogManager.Log(ex, "An error occurred while shutting down machine studio.");
}
}
///
/// Notify the application manager about an external opened window.
/// When application exists. All registered windows will be closed.
///
/// The window.
public void RegisterOpenedWindow(Window window)
{
_openedWindows.Add(window);
window.Closed += (x, y) => { _openedWindows.Remove(window); };
}
public bool IsModuleInNewWindow(IStudioModule module)
{
return _openedWindows.Exists(x => (x as ModuleWindow).ModuleContext.Module == module);
}
///
/// Gets the core libraries version.
///
public Version CoreVersion
{
get
{
return typeof(ExtendedObject).Assembly.GetName().Version;
}
}
///
/// Gets the build date.
///
public string BuildDate
{
get
{
return AssemblyHelper.GetCurrentAssemblyBuildDate().ToShortDateString();
}
}
///
/// Gets the change log.
///
public string ChangeLog
{
get
{
return EmbeddedResourceHelper.GetEmbeddedResourceText("Tango.MachineStudio.UI.ChangeLog.txt");
}
}
///
/// Raises the application ready event.
///
public void NotifyApplicationReady()
{
TangoIOC.Default.GetAllInstancesByBase().ToList().ForEach(x =>
{
if (!_notified_view_models.Contains(x))
{
x.OnApplicationReady();
_notified_view_models.Add(x);
}
});
ApplicationReady?.Invoke(this, new EventArgs());
}
///
/// Sets the connected machine.
///
/// The connected machine.
public void SetConnectedMachine(IExternalBridgeClient connectedMachine)
{
if (connectedMachine != null)
{
Machine = ObservablesStaticCollections.Instance.Machines.SingleOrDefault(x => x.SerialNumber == connectedMachine.SerialNumber);
if (Machine == null)
{
throw new NullReferenceException($"The specified machine '{connectedMachine.SerialNumber}' could not be found on the database.");
}
connectedMachine.SetMachine(Machine);
ConnectedMachine = connectedMachine;
var settings = SettingsManager.Default.GetOrCreate();
ConnectedMachine.JobUploadStrategy = settings.JobUploadStrategy;
}
else
{
Machine = null;
ConnectedMachine = null;
}
}
}
}