using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.BL.Enumerations;
using Tango.BL.Helpers;
using Tango.Core.Commands;
using Tango.Core.DI;
using Tango.Core.IO;
using Tango.Core.Threading;
using Tango.CSV;
using Tango.FSE.Common;
using Tango.FSE.Common.HotFolder;
using Tango.FSE.Common.Navigation;
using Tango.FSE.Common.Notifications;
using Tango.FSE.Common.RemoteJobUpload;
using Tango.FSE.UI.Dialogs;
using Tango.FSE.UI.Panes;
using Tango.FSE.UI.Views;
using Tango.Integration.ExternalBridge;
using Tango.PPC.Shared.Statistics;
using Tango.SharedUI.Helpers;
using Tango.Transport;
using static Tango.BL.Helpers.SegmentsCsvHelper;
namespace Tango.FSE.UI.ViewModels
{
///
/// Represents the application main layout view model.
///
///
public class LayoutViewVM : FSEViewModel
{
private ActionTimer _transportOutActionTimer;
private ActionTimer _transportInActionTimer;
#region Properties
private bool _isConnectionPaneOpened;
///
/// Gets or sets a value indicating whether the machine connection pane is opened.
///
public bool IsConnectionPaneOpened
{
get { return _isConnectionPaneOpened; }
set { _isConnectionPaneOpened = value; RaisePropertyChangedAuto(); OnConnectionPaneToggleChanged(); }
}
private MachineConnectionPaneVM _connectionPaneVM;
///
/// Gets or sets the machine connection pane view model.
///
public MachineConnectionPaneVM ConnectionPaneVM
{
get { return _connectionPaneVM; }
set { _connectionPaneVM = value; RaisePropertyChangedAuto(); }
}
private ConnectedMachinePaneVM _connectedMachinePaneVM;
///
/// Gets or sets the connected machine pane view model.
///
public ConnectedMachinePaneVM ConnectedMachinePaneVM
{
get { return _connectedMachinePaneVM; }
set { _connectedMachinePaneVM = value; RaisePropertyChangedAuto(); }
}
private LogViewerPaneVM _logViewPaneVM;
///
/// Gets or sets the log viewer pane view model.
///
public LogViewerPaneVM LogViewerPaneVM
{
get { return _logViewPaneVM; }
set { _logViewPaneVM = value; RaisePropertyChangedAuto(); }
}
private bool _isMenuOpened;
///
/// Gets or sets a value indicating whether the main menu is opened.
///
public bool IsMenuOpened
{
get { return _isMenuOpened; }
set { _isMenuOpened = value; RaisePropertyChangedAuto(); }
}
private bool _isLogsOpened;
///
/// Gets or sets a value indicating whether the log viewer is opened.
///
public bool IsLogsOpened
{
get { return _isLogsOpened; }
set { _isLogsOpened = value; RaisePropertyChangedAuto(); }
}
private bool _transportOut;
///
/// Transport out on/off.
///
public bool TransportOut
{
get { return _transportOut; }
set { _transportOut = value; RaisePropertyChanged(nameof(TransportOut)); }
}
private bool _transportIn;
///
/// Transport in on/off.
///
public bool TransportIn
{
get { return _transportIn; }
set { _transportIn = value; RaisePropertyChanged(nameof(TransportIn)); }
}
[TangoInject]
public IHotFolderService HotFolderService { get; set; }
[TangoInject]
public IRemoteJobUploadProvider RemoteJobUploadProvider { get; set; }
#endregion
#region Commands
///
/// Toggles the connection pane visibility.
///
public RelayCommand ToggleConnectionPaneCommand { get; set; }
///
/// Logs outs the current user.
///
public RelayCommand LogoutCommand { get; set; }
///
/// Opens the bug report dialog.
///
public RelayCommand ReportIssueCommand { get; set; }
///
/// Navigates to the events view.
///
public RelayCommand NavigateToEventsCommand { get; set; }
///
/// Navigates to the home view.
///
public RelayCommand NavigateHomeCommand { get; set; }
///
/// Opens the hot folder configuration dialog.
///
public RelayCommand ConfigureHotFolderCommand { get; set; }
///
/// Opens the job upload dialog.
///
public RelayCommand UploadJobCommand { get; set; }
#endregion
#region Constructors
///
/// Initializes a new instance of the class.
///
public LayoutViewVM()
{
ToggleConnectionPaneCommand = new RelayCommand(() => IsConnectionPaneOpened = !IsConnectionPaneOpened);
ConnectionPaneVM = new MachineConnectionPaneVM();
ConnectionPaneVM.MachineSelected += ConnectionPaneVM_MachineSelected;
ConnectedMachinePaneVM = new ConnectedMachinePaneVM();
ConnectedMachinePaneVM.DisconnectedFromMachine += ConnectedMachinePaneVM_DisconnectedFromMachine;
LogViewerPaneVM = new LogViewerPaneVM();
LogoutCommand = new RelayCommand(Logout);
_transportOutActionTimer = new ActionTimer(TimeSpan.FromMilliseconds(50));
_transportInActionTimer = new ActionTimer(TimeSpan.FromMilliseconds(50));
ReportIssueCommand = new RelayCommand(OpenBugReportDialog);
NavigateToEventsCommand = new RelayCommand(NavigateToEvents);
NavigateHomeCommand = new RelayCommand(NavigateHome);
ConfigureHotFolderCommand = new RelayCommand(ConfigureHotFolder);
UploadJobCommand = new RelayCommand(UploadJob);
}
#endregion
#region Machine Operator Event Handlers
private void MachineProvider_MachineDisconnected(object sender, Common.Connection.MachineDisconnectedEventArgs e)
{
if (e.MachineOperator.Adapter != null)
{
e.MachineOperator.Adapter.PropertyChanged -= Adapter_PropertyChanged;
}
}
private void MachineProvider_MachineConnected(object sender, Common.Connection.MachineConnectedEventArgs e)
{
e.MachineOperator.Adapter.PropertyChanged -= Adapter_PropertyChanged;
e.MachineOperator.Adapter.PropertyChanged += Adapter_PropertyChanged;
}
private void Adapter_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(ITransportAdapter.TotalBytesSent))
{
TransportOut = true;
_transportOutActionTimer.ResetReplace(() => TransportOut = false);
}
else if (e.PropertyName == nameof(ITransportAdapter.TotalBytesReceived))
{
TransportIn = true;
_transportInActionTimer.ResetReplace(() => TransportIn = false);
}
}
#endregion
#region Connected Machine Pane Event Handlers
private async void ConnectedMachinePaneVM_DisconnectedFromMachine(object sender, EventArgs e)
{
IsConnectionPaneOpened = false;
try
{
await MachineProvider.DisconnectMachine();
}
catch (Exception ex)
{
LogManager.Log(ex, "Error disconnecting from machine.");
await NotificationProvider.ShowError("Error occurred while trying to disconnect from the machine.");
}
}
#endregion
#region Machine Connection Pane Event Handlers
private async void ConnectionPaneVM_MachineSelected(object sender, IExternalBridgeClient machine)
{
IsConnectionPaneOpened = false;
LogManager.Log($"Machine '{machine.SerialNumber}' selected for connection by user.");
try
{
if (await MachineProvider.ConnectToMachine(machine))
{
NotificationProvider.PushSnackbarItem(MessageType.Success, "Machine successfully connected", true, $"{MachineProvider.Machine.SerialNumber}, {MachineProvider.Machine.Name}", TimeSpan.FromSeconds(5));
}
}
catch (Exception ex)
{
await NotificationProvider.ShowError($"Error occurred while trying to connect to the specified machine.\n{ex.FlattenMessage()}");
LogManager.Log(ex, $"Error connecting to machine '{machine.SerialNumber}'.");
}
}
#endregion
#region Override Methods
public override void OnApplicationStarted()
{
MachineProvider.MachineDisconnected += MachineProvider_MachineDisconnected;
MachineProvider.MachineConnected += MachineProvider_MachineConnected;
}
public override void OnNavigatedTo()
{
base.OnNavigatedTo();
this.SetFocus(nameof(ToggleConnectionPaneCommand));
}
public override async Task OnApplicationLogout()
{
if (MachineProvider.IsConnected)
{
if (await NotificationProvider.ShowWarningQuestion("The current machine connection will be automatically closed.\nAre you sure you want to log out?"))
{
await MachineProvider.DisconnectMachine();
return true;
}
else
{
return false;
}
}
else
{
return true;
}
}
#endregion
#region Private Methods
private void OnConnectionPaneToggleChanged()
{
if (!MachineProvider.IsConnected)
{
if (IsConnectionPaneOpened)
{
try
{
ConnectionPaneVM.Start();
}
catch (Exception ex)
{
LogManager.Log(ex, "Error while trying to initialize machine scanning.");
NotificationProvider.ShowError($"Error occurred while trying to initialize machine scanning.\n{ex.FlattenMessage()}");
_isConnectionPaneOpened = false;
RaisePropertyChanged(nameof(IsConnectionPaneOpened));
}
}
else
{
try
{
ConnectionPaneVM.Stop();
}
catch (Exception ex)
{
LogManager.Log(ex, "Error while stopping machine scanning.");
}
}
}
}
private void Logout()
{
LogManager.Log("Logout command pressed by user.");
AuthenticationProvider.LogOut();
}
private void OpenBugReportDialog()
{
BugReporter.ShowBugReportDialog();
}
private void NavigateToEvents()
{
NavigationManager.NavigateTo(nameof(EventsView));
}
private void NavigateHome()
{
NavigationManager.NavigateTo(NavigationView.Home);
}
private async void ConfigureHotFolder()
{
await NotificationProvider.ShowDialog();
}
private async void UploadJob()
{
RequiredFiltersData data = null;
try
{
using (NotificationProvider.PushTaskItem("Preparing job upload requirements..."))
{
await Task.Delay(1500);
data = await StatisticsProvider.GetRequiredFiltersData();
}
}
catch (Exception ex)
{
await NotificationProvider.ShowError($"Error preparing job upload requirements.\n{ex.FlattenMessage()}");
return;
}
var lastSelectedRml = data.Rmls.FirstOrDefault(x => x.Guid == Settings.LastJobUploadThreadGuid);
if (lastSelectedRml == null) lastSelectedRml = data.Rmls.FirstOrDefault();
var vm = await NotificationProvider.ShowDialog(new JobUploadViewVM(MachineProvider) { Rmls = data.Rmls, SelectedRML = lastSelectedRml });
if (vm.DialogResult)
{
TemporaryFile tmpFile = TemporaryManager.CreateImaginaryFile(".csv");
try
{
Settings.LastJobUploadThreadGuid = vm.SelectedRML.Guid;
Settings.Save();
CsvDynamicWriter csv = new CsvDynamicWriter();
int cIndex = 0;
csv.Write(1, "Index", 0, cIndex++);
csv.Write(vm.SelectedRML.Name, "ThreadName", "", cIndex++);
csv.Write(vm.Length, "Length", 0, cIndex++);
csv.Write(ColorSpaces.Volume, "ColorSpace", ColorSpaces.Volume, cIndex++);
foreach (var liquidVolume in vm.Volumes)
{
if (liquidVolume.Volume > 0)
{
csv.Write(liquidVolume.Volume, liquidVolume.LiquidType.DisplayName, 0, cIndex);
}
}
csv.Save(tmpFile);
}
catch (Exception ex)
{
await NotificationProvider.ShowError($"Error creating job upload file.\n{ex.FlattenMessage()}");
tmpFile.Delete();
return;
}
SnackbarItem progress = null;
try
{
progress = NotificationProvider.PushProgressSnackbar("Job Upload", $"Uploading job '{vm.Name}'...");
await Task.Delay(1500);
await RemoteJobUploadProvider.UploadJob(tmpFile, PPC.Shared.RemoteJobUpload.RemoteJobUploadType.CSV, vm.Name);
progress.ProgressCompleted("Job uploaded successfully", TimeSpan.FromSeconds(2));
}
catch (Exception ex)
{
progress.ProgressFailed($"Error uploading job.\n{ex.Message}");
return;
}
}
}
#endregion
}
}