namespace VideoBrowser.Core
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
///
/// Defines the .
///
public static class DownloadQueueHandler
{
#region Fields
private static bool _stop;
#endregion Fields
#region Properties
///
/// Gets the DownloadingCount.
///
private static int DownloadingCount => Queue.Count(o => IsDownloaderType(o) && o.CanPause());
///
/// Gets or sets a value indicating whether LimitDownloads.
///
public static bool LimitDownloads { get; set; }
///
/// Gets or sets the MaxDownloads.
///
public static int MaxDownloads { get; set; }
///
/// Gets or sets the Queue.
///
public static List Queue { get; } = new List();
#endregion Properties
#region Methods
///
/// The Add.
///
/// The operation.
public static void Add(Operation operation)
{
operation.Completed += Operation_Completed;
operation.Resumed += Operation_Resumed;
operation.StatusChanged += Operation_StatusChanged;
Queue.Add(operation);
}
///
/// The GetQueued.
///
/// The .
public static Operation[] GetQueued()
{
return Queue.Where(o => IsDownloaderType(o) && o.Status == OperationStatus.Queued).ToArray();
}
///
/// The GetWorking.
///
/// The .
public static Operation[] GetWorking()
{
return Queue.Where(o => IsDownloaderType(o) && o.Status == OperationStatus.Working).ToArray();
}
///
/// The Remove.
///
/// The operation.
public static void Remove(Operation operation)
{
operation.Completed -= Operation_Completed;
operation.Resumed -= Operation_Resumed;
operation.StatusChanged -= Operation_StatusChanged;
Queue.Remove(operation);
}
///
/// The StartWatching.
///
/// The maxDownloads.
public static void StartWatching(int maxDownloads)
{
MaxDownloads = maxDownloads;
MainLoop();
}
///
/// The Stop.
///
public static void Stop()
{
_stop = true;
}
///
/// The IsDownloaderType.
///
/// The operation.
/// The .
private static bool IsDownloaderType(Operation operation)
{
return operation is DownloadOperation;
}
///
/// The MainLoop.
///
private static async void MainLoop()
{
while (!_stop)
{
await Task.Delay(1000);
var queued = GetQueued();
// If downloads isn't limited, start all queued operations
if (!LimitDownloads)
{
if (queued.Length == 0)
{
continue;
}
foreach (var operation in queued)
{
if (operation.HasStarted)
{
operation.ResumeQuiet();
}
else
{
operation.Start();
}
}
}
else if (DownloadingCount < MaxDownloads)
{
// Number of operations to start
var count = Math.Min(MaxDownloads - DownloadingCount, queued.Length);
for (var i = 0; i < count; i++)
{
if (queued[i].HasStarted)
{
queued[i].ResumeQuiet();
}
else
{
queued[i].Start();
}
}
}
else if (DownloadingCount > MaxDownloads)
{
// Number of operations to pause
var count = DownloadingCount - MaxDownloads;
var working = GetWorking();
for (var i = DownloadingCount - 1; i > (MaxDownloads - 1); i--)
{
working[i].Queue();
}
}
}
}
///
/// The Operation_Completed.
///
/// The sender.
/// The e.
private static void Operation_Completed(object sender, OperationEventArgs e)
{
Remove((sender as Operation));
}
///
/// The Operation_Resumed.
///
/// The sender.
/// The e.
private static void Operation_Resumed(object sender, EventArgs e)
{
// User resumed operation, prioritize this operation over other queued
var operation = sender as Operation;
// Move operation to top of queue, since pausing happens from the bottom.
// I.E. this operation will only paused if absolutely necessary.
Queue.Remove(operation);
Queue.Insert(0, operation);
}
///
/// The Operation_StatusChanged.
///
/// The sender.
/// The e.
private static void Operation_StatusChanged(object sender, StatusChangedEventArgs e)
{
}
#endregion Methods
}
}