aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/SideChains/Colourful/Implementation/Conversion/Lab
ModeNameSize
-rw-r--r--LabToXYZConverter.cs2345logstatsplain
-rw-r--r--XYZToLabConverter.cs2736logstatsplain
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using Tango.Core;
using Tango.Core.Commands;
using Tango.Core.Helpers;
using Tango.FSE.Common;
using Tango.FSE.Common.Connection;
using Tango.FSE.Common.Dialogs;
using Tango.FSE.Common.FileSystem;
using Tango.FSE.Common.Logging;
using Tango.FSE.Common.Navigation;
using Tango.FSE.PPCConsole.Contracts;
using Tango.FSE.PPCConsole.Navigation;
using Tango.Logging;
using Tango.PPC.Shared.Logs;
using Tango.SharedUI.Components;
using static Tango.SharedUI.Controls.NavigationControl;

namespace Tango.FSE.PPCConsole.ViewModels
{
    public class LogsViewVM : FSEViewModel<ILogsView>, INavigationViewModel
    {
        private bool _loaded;
        private PeekLogsNavigationObject _peekNavigationObject;

        private List<RemoteLogFileModel<LogItemBase>> _logFiles;
        /// <summary>
        /// Gets or sets the remote log files.
        /// </summary>
        public List<RemoteLogFileModel<LogItemBase>> LogFiles
        {
            get { return _logFiles; }
            set { _logFiles = value; RaisePropertyChangedAuto(); }
        }

        private RemoteLogFileModel<LogItemBase> _selectedLogFile;
        /// <summary>
        /// Gets or sets the selected remote log file.
        /// </summary>
        public RemoteLogFileModel<LogItemBase> SelectedLogFile
        {
            get { return _selectedLogFile; }
            set { _selectedLogFile = value; RaisePropertyChangedAuto(); OnSelectedLogFileChanged(); InvalidateRelayCommands(); }
        }

        private ObservableCollection<LogItemBase> _applicationLogs;
        /// <summary>
        /// Gets or sets the application logs.
        /// </summary>
        public ObservableCollection<LogItemBase> ApplicationLogs
        {
            get { return _applicationLogs; }
            set { _applicationLogs = value; RaisePropertyChangedAuto(); }
        }

        /// <summary>
        /// Gets or sets the application logs view.
        /// </summary>
        public ICollectionView ApplicationLogsView { get; set; }

        /// <summary>
        /// Gets or sets the selected application logs categories.
        /// </summary>
        public SelectedObjectCollection<LogCategory> SelectedApplicationLogsCategories { get; set; }

        private String _applicationLogsFilter;
        /// <summary>
        /// Gets or sets the application logs filter.
        /// </summary>
        public String ApplicationLogsFilter
        {
            get { return _applicationLogsFilter; }
            set { _applicationLogsFilter = value; RaisePropertyChangedAuto(); ApplicationLogsView.Refresh(); }
        }

        /// <summary>
        /// Opens the detailed application log dialog.
        /// </summary>
        public RelayCommand<LogItemBase> OpenApplicationLogItemCommand { get; set; }

        /// <summary>
        /// Exports the selected log file to local disk.
        /// </summary>
        public RelayCommand ExportLogFileCommand { get; set; }

        /// <summary>
        /// Exports all the downloaded log files to disk.
        /// </summary>
        public RelayCommand ExportAllDownloadedLogFilesCommand { get; set; }

        /// <summary>
        /// Downloads all the available log files.
        /// </summary>
        public RelayCommand DownloadAllLogFilesCommand { get; set; }

        /// <summary>
        /// Re-downloads the selected log file.
        /// </summary>
        public RelayCommand ReDownloadSelectedLogFileCommand { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="LogsViewVM"/> class.
        /// </summary>
        public LogsViewVM()
        {
            ApplicationLogs = new ObservableCollection<LogItemBase>();
            InitCollectionView();

            SelectedApplicationLogsCategories = new SelectedObjectCollection<LogCategory>(new ObservableCollection<LogCategory>()
            {
                LogCategory.Info,
                LogCategory.Warning,
                LogCategory.Error,
                LogCategory.Critical,
                LogCategory.Debug,
            }, new ObservableCollection<LogCategory>()
            {
                LogCategory.Info,
                LogCategory.Warning,
                LogCategory.Error,
                LogCategory.Critical,
                LogCategory.Debug,
            });

            SelectedApplicationLogsCategories.SynchedSource.CollectionChanged += (_, __) => ApplicationLogsView.Refresh();

            OpenApplicationLogItemCommand = new RelayCommand<LogItemBase>(OpenApplicationLogItem);

            ExportLogFileCommand = new RelayCommand(ExportSelectedLogFile, () => SelectedLogFile != null);
            ExportAllDownloadedLogFilesCommand = new RelayCommand(ExportAllDownloadedLogFiles);
            DownloadAllLogFilesCommand = new RelayCommand(DownloadAllLogFiles);
            ReDownloadSelectedLogFileCommand = new RelayCommand(ReDownloadSelectedLogFile, () => SelectedLogFile != null);

            RegisterForMessage<PeekLogsNavigationObject>(HandlePeekLogsNavigationObject);
        }

        private void InitCollectionView()
        {
            ApplicationLogsView = CollectionViewSource.GetDefaultView(ApplicationLogs);
            ApplicationLogsView.Filter = FilterApplicationLogs;
        }

        public override void OnApplicationStarted()
        {
            base.OnApplicationStarted();
            MachineProvider.MachineConnected += MachineProvider_MachineConnected;
        }

        private async void MachineProvider_MachineConnected(object sender, MachineConnectedEventArgs e)
        {
            _loaded = false;

            if (MachineProvider.IsPPCAvailable && IsVisible)
            {
                await LoadLogFiles();
            }
        }

        public async override void OnNavigatedTo()
        {
            base.OnNavigatedTo();

            if (!_loaded && MachineProvider.IsPPCAvailable)
            {
                await LoadLogFiles();
            }

            if (MachineProvider.IsPPCAvailable)
            {
                if (_peekNavigationObject != null)
                {
                    PeekApplicationLogs(_peekNavigationObject);
                }
            }
        }

        private async Task LoadLogFiles()
        {
            if (!MachineProvider.ConnectionType.IsRemote() || !IsFree) return;

            try
            {
                IsFree = false;
                var logFiles = await LoggingProvider.GetApplicationLogFiles();
                LogFiles = logFiles.Select(x =>
                {

                    var model = new RemoteLogFileModel<LogItemBase>(new ApplicationLogFileParser());
                    model.RemoteLogFile = x;
                    model.DownloadCompleted += OnRemoteLogFileDownloadCompleted;
                    return model;

                }).ToList();
                SelectedLogFile = LogFiles.FirstOrDefault();
                _loaded = true;
            }
            catch (Exception ex)
            {
                LogManager.Log(ex, "Error loading log files.");
                NotificationProvider.PushErrorReportingSnackbar(ex, "PPC Module Error", "Could not initialize the remote PPC logs history.");
            }
            finally
            {
                IsFree = true;
            }
        }

        private void OnRemoteLogFileDownloadCompleted(object sender, EventArgs e)
        {
            if (SelectedLogFile == sender)
            {
                OnSelectedLogFileChanged();
            }
        }

        private void OnSelectedLogFileChanged()
        {
            if (SelectedLogFile == null) return;

            InvokeUI(() =>
            {
                ApplicationLogs = new ObservableCollection<LogItemBase>(SelectedLogFile.LogItems);
                InitCollectionView();
            });
        }

        private async void OpenApplicationLogItem(LogItemBase logItem)
        {
            await NotificationProvider.ShowDialog(new ApplicationLogItemViewVM() { LogItem = logItem });
        }

        private bool FilterApplicationLogs(object obj)
        {
            var log = obj as LogItemBase;
            return SelectedApplicationLogsCategories.SynchedSource.Contains(log.Category) && (String.IsNullOrWhiteSpace(ApplicationLogsFilter) || log.Message.ToLower().Contains(ApplicationLogsFilter.ToLower()));
        }

        private async void ExportSelectedLogFile()
        {
            if (SelectedLogFile != null && SelectedLogFile.Status == RemoteLogFileStatus.Downloaded)
            {
                var result = await StorageProvider.SaveFile("Export Log File", "Application Log Files|*.log", SelectedLogFile.RemoteLogFile.Name, ".log");
                if (result)
                {
                    using (NotificationProvider.PushTaskItem("Exporting log file..."))
                    {
                        try
                        {
                            File.Copy(SelectedLogFile.TemporaryFile, result.SelectedItem, true);
                            await NotificationProvider.ShowSuccess("Log file exported successfully.");
                        }
                        catch (Exception ex)
                        {
                            LogManager.Log(ex, "Error exporting application log file.");
                            await NotificationProvider.ShowError($"Could not export the log file.\n{ex.FlattenMessage()}");
                        }
                    }
                }
            }
            else
            {
                await NotificationProvider.ShowError("Please download the selected log file before trying to export.");
            }
        }

        private async void ExportAllDownloadedLogFiles()
        {
            var toExport = LogFiles.Where(x => x.Status == RemoteLogFileStatus.Downloaded).ToList();

            if (toExport.Count == 0)
            {
                await NotificationProvider.ShowError("Please download log files before trying to export.");
                return;
            }

            var result = await StorageProvider.SelectFolder("Export Log Files");
            if (result)
            {
                var count = toExport.Count;

                using (var task = NotificationProvider.PushTaskItem("Exporting log files..."))
                {
                    foreach (var logFile in toExport.ToList())
                    {
                        try
                        {
                            await Task.Delay(500);
                            File.Copy(logFile.TemporaryFile, Path.Combine(result.SelectedItem, logFile.RemoteLogFile.Name), true);
                            toExport.Remove(logFile);
                            task.UpdateProgress("Exporting log files...", count - toExport.Count, count, false);
                        }
                        catch (Exception ex)
                        {
                            LogManager.Log(ex, $"Error exporting application log file '{logFile.RemoteLogFile.Name}'.");
                            await NotificationProvider.ShowError($"Could not export '{logFile.RemoteLogFile.Name}'.\n{ex.FlattenMessage()}");
                        }
                    }
                }

                await NotificationProvider.ShowSuccess($"Successfully exported {count - toExport.Count} out of {count} log files.");
            }
        }

        private async void DownloadAllLogFiles()
        {
            var toDownload = LogFiles.Where(x => x.Status == RemoteLogFileStatus.None || x.Status == RemoteLogFileStatus.Failed).ToList();

            if (toDownload.Count == 0)
            {
                await NotificationProvider.ShowInfo("All log files have been downloaded.");
                return;
            }

            var totalSize = FileHelper.GetFriendlyFileSize(toDownload.Select(x => x.RemoteLogFile.Length).Sum());

            if (await NotificationProvider.ShowWarningQuestion($"Are you sure you wish to download the entire history of log files?\nTotal size: {totalSize}", "DOWNLOAD", "CANCEL"))
            {
                foreach (var logFile in toDownload)
                {
                    logFile.DownloadLogFile();
                }
            }
        }

        private void ReDownloadSelectedLogFile()
        {
            if (SelectedLogFile != null)
            {
                SelectedLogFile.Status = RemoteLogFileStatus.None;
                SelectedLogFile.DownloadLogFile();
            }
        }

        private void HandlePeekLogsNavigationObject(PeekLogsNavigationObject obj)
        {
            if (!IsVisible)
            {
                _peekNavigationObject = obj;
            }
            else
            {
                PeekApplicationLogs(obj);
            }
        }

        private async void PeekApplicationLogs(PeekLogsNavigationObject obj)
        {
            _peekNavigationObject = null;

            var closestLogFile = LogFiles.Where(x => x.RemoteLogFile.DateCreated < obj.Time).OrderBy(x => x.RemoteLogFile.DateCreated).LastOrDefault();

            if (closestLogFile != null)
            {
                if (closestLogFile.RemoteLogFile.DateModified > obj.Time)
                {
                    using (NotificationProvider.PushTaskItem("Peeking application log items..."))
                    {
                        SelectedLogFile = closestLogFile;

                        //Found proper log file..
                        if (closestLogFile.Status != RemoteLogFileStatus.Downloaded)
                        {
                            bool completed = false;
                            closestLogFile.DownloadCompleted += async (_, __) =>
                            {
                                if (!completed)
                                {
                                    using (NotificationProvider.PushTaskItem("Peeking application log items..."))
                                    {
                                        completed = true;

                                        var localTime = obj.Time.ToLocalTime();
                                        var log = closestLogFile.LogItems.Where(x => x.TimeStamp < localTime).OrderBy(x => x.TimeStamp).LastOrDefault();

                                        if (log != null)
                                        {
                                            await Task.Delay(2000);
                                            InvokeUI(() =>
                                            {
                                                View.ScrollToLogFile(SelectedLogFile);
                                                View.ScrollToLog(log);
                                            });
                                        }
                                    }
                                }

                            };
                            closestLogFile.DownloadLogFile();
                        }
                        else
                        {
                            var localTime = obj.Time.ToLocalTime();
                            var log = closestLogFile.LogItems.Where(x => x.TimeStamp < localTime).OrderBy(x => x.TimeStamp).LastOrDefault();

                            if (log != null)
                            {
                                await Task.Delay(2000);
                                View.ScrollToLogFile(SelectedLogFile);
                                View.ScrollToLog(log);
                            }
                        } 
                    }
                }
                else
                {
                    await NotificationProvider.ShowError("Could not correlate any log file.");
                }
            }
            else
            {
                await NotificationProvider.ShowError("A matching log file was found, but could not correlate any log item.\nIf this is an active log file, please to reload it and try again.");
            }
        }
    }
}