using System.Collections.ObjectModel; using System.Windows; using System.Windows.Threading; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Messaging; using Livia.Models; using Livia.Models.Data; using Livia.Properties; using Livia.Utility; using Livia.Utility.DependencyInjection; using Livia.Views.Utility; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace Livia.ViewModels; public sealed class DataBlockTableViewModel : ObservableRecipient, IRecipient, IRecipient, IPagingControlRecipient { public int SequenceColumnNum { get => _sequenceColumnNum; private set => SetProperty(ref _sequenceColumnNum, value); } public ObservableCollection ServerJobList { get; } = []; public PagingControlViewModel DataBlockPagingViewModel { get; } public IServerHandler ServerHandler { get; } private int _sequenceColumnNum; private readonly IWarningSystem _warningSystem; private readonly ILogger _logger; private readonly IDataBlockLoader _dataBlockLoader; private SearchQueryCondition _currentSearch; private bool _isSearchResult; public DataBlockTableViewModel(IServerHandler serverHandler, IWarningSystem warningSystem, ILogger logger, IDataBlockLoader dataBlockLoader) { WeakReferenceMessenger.Default.Register(this); DataBlockPagingViewModel = ActivatorUtilities.CreateInstance(ServiceProviderFactory.ServiceProvider); DataBlockPagingViewModel.SetRecipient(this); ServerHandler = serverHandler; _warningSystem = warningSystem; _logger = logger; _dataBlockLoader = dataBlockLoader; //only if we are using this module if (!Settings.Default.AutoRefreshServerJobList) return; DispatcherTimer dispatcherTimer = new(); dispatcherTimer.Tick += Tick; dispatcherTimer.Interval = new TimeSpan(0, 0, 5); dispatcherTimer.Start(); Tick(null, null); } private void Tick(object? sender, EventArgs? e) { Task.Run(UpdateServerJobList); } public void SetSearchResult() { _isSearchResult = true; WeakReferenceMessenger.Default.Register(this); } private async Task SearchData(SearchQueryCondition condition) { SearchQueryJson json = new() { Conditions = condition, Limit = PagingControlViewModel.ItemPerPage, Offset = DataBlockPagingViewModel.Offset }; _currentSearch = condition; (List list, int count) = await ServerHandler.SearchData(json).ConfigureAwait(false); DataBlockPagingViewModel.SetItemNumber(count); int maxSequenceCount = list.Select(data => data.Sequence?.Count ?? 0).DefaultIfEmpty().Max(); SequenceColumnNum = (1 + maxSequenceCount) / 2; Application.Current.Dispatcher.Invoke(delegate { ServerJobList.Clear(); ServerJobList.AddRange(list); }); return true; } public async Task UpdateServerJobList() { //TODO::check for success here (List list, int count) = await ServerHandler.CheckServerJobList(PagingControlViewModel.ItemPerPage, DataBlockPagingViewModel.Offset).ConfigureAwait(false); //_logger.LogInformation("SelectedCount is {count}", count); DataBlockPagingViewModel.SetItemNumber(count); int maxSequenceCount = list.Select(data => data.Sequence?.Count ?? 0).DefaultIfEmpty().Max(); SequenceColumnNum = (1 + maxSequenceCount) / 2; Application.Current.Dispatcher.Invoke(delegate { ServerJobList.Clear(); ServerJobList.AddRange(list); }); await ServerHandler.UpdateDongleInfo().ConfigureAwait(false); return true; } public Task LoadData(ServerJobData dataContext) { return _dataBlockLoader.LoadServerData(dataContext); } public Task CancelData(ServerJobData dataContext) { return dataContext.Key == null ? Task.CompletedTask : ServerHandler.Cancel(dataContext.Key); } public async Task DownloadArchive(ServerJobData data, string savePath, CancellationToken cancellationToken) { _logger.LogInformation("Downloading archive to {path}", savePath); if (string.IsNullOrEmpty(data.Key)) { _warningSystem.ShowDialog(WarningWindowKind.Warning, true, "ProcessingError"); } (bool success, string messageIndex) = await ServerHandler.DownloadArchive(data.Key, savePath, cancellationToken); if (!success) { if (!cancellationToken.IsCancellationRequested) _warningSystem.ShowDialog(WarningWindowKind.Warning, true, messageIndex); } else { _warningSystem.ShowDialog(WarningWindowKind.Info, false, "DataProcessComplete"); } } public async Task DownloadSorted(ServerJobData data, string savePath, CancellationToken cancellationToken) { _logger.LogInformation("Downloading sorted to {path}", savePath); if (string.IsNullOrEmpty(data.Key)) { _warningSystem.ShowDialog(WarningWindowKind.Warning, true, "ProcessingError"); } (bool success, string messageIndex) = await ServerHandler.DownloadSorted(data.Key, savePath, cancellationToken); if (!success) { if (!cancellationToken.IsCancellationRequested) _warningSystem.ShowDialog(WarningWindowKind.Warning, true, messageIndex); } else { _warningSystem.ShowDialog(WarningWindowKind.Info, false, "DataProcessComplete"); } } public void Receive(LogoutMessage message) { Application.Current.Dispatcher.Invoke(delegate { ServerJobList.Clear(); }); DataBlockPagingViewModel.CurrentPage = 1; DataBlockPagingViewModel.SetItemNumber(0); } public void Receive(SearchQueryMessage message) { DataBlockPagingViewModel.CurrentPage = 1; Task.Run(() => SearchData(message.Value)); } public async Task Refresh() { return _isSearchResult ? await SearchData(_currentSearch).ConfigureAwait(false) : await UpdateServerJobList().ConfigureAwait(false); } public async Task DeleteData(ServerJobData data, CancellationToken cancellationToken) { _logger.LogInformation("Deleting data {id}", data.Id); (bool success, string messageIndex) = _isSearchResult ? await ServerHandler.DeleteData(data.Id, cancellationToken) : await ServerHandler.DeleteHistory(data.Key, cancellationToken); if (!success) { if (!cancellationToken.IsCancellationRequested) _warningSystem.ShowDialog(WarningWindowKind.Warning, true, messageIndex); } else { DataBlockPagingViewModel.RefreshCurrentPage(); _warningSystem.ShowDialog(WarningWindowKind.Info, false, messageIndex); } await Refresh(); } public async Task DeleteHistory(DataHistory data, CancellationToken cancellationToken) { _logger.LogInformation("Deleting data {id}", data.Key); (bool success, string messageIndex) = await ServerHandler.DeleteHistory(data.Key, cancellationToken); if (!success) { if (!cancellationToken.IsCancellationRequested) _warningSystem.ShowDialog(WarningWindowKind.Warning, true, messageIndex); } else { DataBlockPagingViewModel.RefreshCurrentPage(); _warningSystem.ShowDialog(WarningWindowKind.Info, false, messageIndex); } await Refresh(); } }