using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using TwitchDownloaderWPF.TwitchTasks;
using TwitchDownloaderWPF.Properties;
using System.Diagnostics;
using System.IO;
using TwitchDownloaderWPF.Services;
namespace TwitchDownloaderWPF
{
///
/// Interaction logic for PageQueue.xaml
///
public partial class PageQueue : Page
{
public static readonly object taskLock = new object();
public static ObservableCollection taskList { get; } = new();
private static readonly BackgroundWorker taskManager = new BackgroundWorker();
public PageQueue()
{
InitializeComponent();
queueList.ItemsSource = taskList;
numVod.Value = Settings.Default.LimitVod;
numClip.Value = Settings.Default.LimitClip;
numChat.Value = Settings.Default.LimitChat;
numRender.Value = Settings.Default.LimitRender;
taskManager.DoWork += TaskManager_DoWork;
taskManager.RunWorkerAsync();
}
private static void TaskManager_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
int maxVod = Settings.Default.LimitVod;
int maxClip = Settings.Default.LimitClip;
int maxChat = Settings.Default.LimitChat;
int maxRender = Settings.Default.LimitRender;
int currentVod = 0;
int currentClip = 0;
int currentChat = 0;
int currentRender = 0;
lock (taskLock)
{
foreach (var task in taskList)
{
if (task.Status is not TwitchTaskStatus.Running)
continue;
switch (task)
{
case VodDownloadTask:
currentVod++;
break;
case ClipDownloadTask:
currentClip++;
break;
case ChatDownloadTask:
currentChat++;
break;
case ChatUpdateTask:
currentChat++;
break;
case ChatRenderTask:
currentRender++;
break;
}
}
foreach (var task in taskList)
{
if (!task.CanRun())
continue;
switch (task)
{
case VodDownloadTask when currentVod < maxVod:
currentVod++;
task.RunAsync();
break;
case ClipDownloadTask when currentClip < maxClip:
currentClip++;
task.RunAsync();
break;
case ChatDownloadTask when currentChat < maxChat:
currentChat++;
task.RunAsync();
break;
case ChatUpdateTask when currentChat < maxChat:
currentChat++;
task.RunAsync();
break;
case ChatRenderTask when currentRender < maxRender:
currentRender++;
task.RunAsync();
break;
}
}
}
Thread.Sleep(1000);
}
}
private void btnDonate_Click(object sender, RoutedEventArgs e)
{
Process.Start(new ProcessStartInfo("https://www.buymeacoffee.com/lay295") { UseShellExecute = true });
}
private void btnSettings_Click(object sender, RoutedEventArgs e)
{
var settings = new WindowSettings
{
Owner = Application.Current.MainWindow,
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
settings.ShowDialog();
btnDonate.Visibility = Settings.Default.HideDonation ? Visibility.Collapsed : Visibility.Visible;
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
btnDonate.Visibility = Settings.Default.HideDonation ? Visibility.Collapsed : Visibility.Visible;
}
private void numVod_ValueChanged(object sender, HandyControl.Data.FunctionEventArgs e)
{
if (this.IsInitialized)
{
Settings.Default.LimitVod = (int)numVod.Value;
Settings.Default.Save();
}
}
private void numClip_ValueChanged(object sender, HandyControl.Data.FunctionEventArgs e)
{
if (this.IsInitialized)
{
Settings.Default.LimitClip = (int)numClip.Value;
Settings.Default.Save();
}
}
private void numChat_ValueChanged(object sender, HandyControl.Data.FunctionEventArgs e)
{
if (this.IsInitialized)
{
Settings.Default.LimitChat = (int)numChat.Value;
Settings.Default.Save();
}
}
private void numRender_ValueChanged(object sender, HandyControl.Data.FunctionEventArgs e)
{
if (this.IsInitialized)
{
Settings.Default.LimitRender = (int)numRender.Value;
Settings.Default.Save();
}
}
private void btnUrlList_Click(object sender, RoutedEventArgs e)
{
var window = new WindowUrlList
{
Owner = Application.Current.MainWindow,
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
window.ShowDialog();
}
private void btnVods_Click(object sender, RoutedEventArgs e)
{
var window = new WindowMassDownload(DownloadType.Video)
{
Owner = Application.Current.MainWindow,
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
window.ShowDialog();
}
private void btnClips_Click(object sender, RoutedEventArgs e)
{
var window = new WindowMassDownload(DownloadType.Clip)
{
Owner = Application.Current.MainWindow,
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
window.ShowDialog();
}
private void BtnCancelTask_Click(object sender, RoutedEventArgs e)
{
if (sender is not Button { DataContext: TwitchTask task })
{
return;
}
CancelTask(task);
}
private void MenuItemCancelTask_Click(object sender, RoutedEventArgs e)
{
if (sender is not MenuItem { DataContext: TwitchTask task })
{
return;
}
CancelTask(task);
}
private static void CancelTask(TwitchTask task)
{
if (task.CanCancel)
{
task.Cancel();
}
}
private void BtnTaskError_Click(object sender, RoutedEventArgs e)
{
if (sender is not Button { DataContext: TwitchTask task })
{
return;
}
ShowTaskException(task);
}
private void MenuItemTaskError_Click(object sender, RoutedEventArgs e)
{
if (sender is not MenuItem { DataContext: TwitchTask task })
{
return;
}
ShowTaskException(task);
}
private static void ShowTaskException(TwitchTask task)
{
var taskException = task.Exception;
if (taskException is null)
{
return;
}
var errorMessage = taskException.Message;
if (Settings.Default.VerboseErrors)
{
errorMessage = taskException.ToString();
}
MessageBox.Show(Application.Current.MainWindow!, errorMessage, Translations.Strings.MessageBoxTitleError, MessageBoxButton.OK, MessageBoxImage.Error);
}
private void BtnRemoveTask_Click(object sender, RoutedEventArgs e)
{
if (sender is not Button { DataContext: TwitchTask task })
{
return;
}
RemoveTask(task);
}
private void MenuItemRemoveTask_Click(object sender, RoutedEventArgs e)
{
if (sender is not MenuItem { DataContext: TwitchTask task })
{
return;
}
RemoveTask(task);
}
private static void RemoveTask(TwitchTask task)
{
if (task.CanRun() || task.Status is TwitchTaskStatus.Running or TwitchTaskStatus.Waiting)
{
MessageBox.Show(Application.Current.MainWindow!, Translations.Strings.CancelTaskBeforeRemoving, Translations.Strings.TaskCouldNotBeRemoved, MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
lock (taskLock)
{
if (!taskList.Remove(task))
{
MessageBox.Show(Application.Current.MainWindow!, Translations.Strings.TaskCouldNotBeRemoved, Translations.Strings.UnknownErrorOccurred, MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
private void MenuItemOpenTaskFolder_Click(object sender, RoutedEventArgs e)
{
if (sender is not MenuItem { DataContext: TwitchTask task })
{
return;
}
FileService.OpenExplorerForFile(new FileInfo(task.OutputFile));
}
private void MenuItemCopyTaskPath_Click(object sender, RoutedEventArgs e)
{
if (sender is not MenuItem { DataContext: TwitchTask task })
{
return;
}
if (!ClipboardService.TrySetText(task.OutputFile, out var exception))
{
MessageBox.Show(Application.Current.MainWindow!, exception.ToString(), Translations.Strings.FailedToCopyToClipboard, MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void BtnRetryTask_Click(object sender, RoutedEventArgs e)
{
if (sender is not Button { DataContext: TwitchTask task })
{
return;
}
RetryTask(task);
}
private void MenuItemTaskRetry_Click(object sender, RoutedEventArgs e)
{
if (sender is not MenuItem { DataContext: TwitchTask task })
{
return;
}
RetryTask(task);
}
private static void RetryTask(TwitchTask task)
{
if (task.CanReinitialize)
{
task.Reinitialize();
}
}
private void BtnMoveTaskUp_Click(object sender, RoutedEventArgs e)
{
if (sender is not Button { DataContext: TwitchTask task })
{
return;
}
lock (taskLock)
{
var index = taskList.IndexOf(task);
if (index < 1)
return;
taskList.Move(index, index - 1);
}
}
private void BtnMoveTaskDown_Click(object sender, RoutedEventArgs e)
{
if (sender is not Button { DataContext: TwitchTask task })
{
return;
}
lock (taskLock)
{
var index = taskList.IndexOf(task);
if (index == -1 || index == taskList.Count - 1)
return;
taskList.Move(index, index + 1);
}
}
}
}