using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using static Vanara.PInvoke.BITS;
namespace Vanara.IO
{
/// Manages the set of jobs for the background copy service (BITS).
public class BackgroundCopyJobCollection : ICollection
{
internal BackgroundCopyJobCollection()
{
}
/// Gets the number of jobs currently managed by BITS.
public int Count
{
get
{
try
{
var ienum = BackgroundCopyManager.EnumJobs((BG_JOB_ENUM)JobListRights);
return (int)ienum.GetCount();
}
catch (COMException cex)
{
throw new BackgroundCopyException(cex);
}
}
}
/// Gets a value indicating whether the is read-only.
bool ICollection.IsReadOnly => false;
/// Gets the correct flag for enumerating jobs based on whether user has administrator rights.
private uint JobListRights => BackgroundCopyManager.IsCurrentUserAdministrator() ? 1u : 0u;
/// Gets the object with the specified job identifier.
/// Unique identifier of the job.
/// The referenced object if found, if not.
public BackgroundCopyJob this[Guid jobId]
{
get
{
var job = BackgroundCopyManager.GetJob(jobId);
return job is not null ? new BackgroundCopyJob(job) : throw new KeyNotFoundException();
}
}
/// Gets the first object with the specified display name.
/// The display name of the job.
/// The referenced object if found, if not.
public BackgroundCopyJob this[string displayName]
{
get
{
var ijobs = BackgroundCopyManager.EnumJobs((BG_JOB_ENUM)JobListRights);
IBackgroundCopyJob[] jobs;
while ((jobs = ijobs.Next(1)).Length == 1)
if (jobs[0].GetDisplayName() == displayName)
return new(jobs[0]);
return null;
}
}
/// Creates a new upload or download transfer job.
/// Name of the job.
/// Description of the job.
/// Type (upload or download) of the job.
/// The new .
public BackgroundCopyJob Add(string displayName, string description = "", BackgroundCopyJobType jobType = BackgroundCopyJobType.Download)
{
try
{
var job = new BackgroundCopyJob(BackgroundCopyManager.CreateJob(displayName, (BG_JOB_TYPE)jobType));
if (!string.IsNullOrEmpty(description))
job.Description = description;
return job;
}
catch (COMException cex)
{
BackgroundCopyManager.HandleCOMException(cex);
}
return null;
}
/// Removes all items from the .
public void Clear()
{
foreach (var i in this)
Remove(i);
}
/// Determines whether the contains a specific value.
/// The object to locate in the .
/// true if is found in the ; otherwise, false.
public bool Contains(Guid jobId)
{
try
{
var ijob = BackgroundCopyManager.GetJob(jobId);
return ijob is not null;
}
catch
{
return false;
}
}
/// Returns an enumerator that iterates through the collection.
/// A that can be used to iterate through the collection.
public IEnumerator GetEnumerator()
{
var ienum = BackgroundCopyManager.EnumJobs((BG_JOB_ENUM)JobListRights);
return new Enumerator(ienum);
}
/// Removes the first occurrence of a specific object from the . The object to
/// remove from the . true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original . item
public bool Remove(BackgroundCopyJob item)
{
if (item is null) throw new ArgumentNullException(nameof(item));
// TODO: Look at what needs to be done to really remove a job and all it's actions
try { item.Cancel(); return true; } catch { return false; }
}
/// Returns a that represents this instance.
/// A that represents this instance.
public override string ToString() => $"Jobs: {Count}";
/// Adds an item to the . The object to add to the .
void ICollection.Add(BackgroundCopyJob item)
{
}
/// Determines whether the contains a specific value.
/// The object to locate in the .
/// true if is found in the ; otherwise, false.
///
bool ICollection.Contains(BackgroundCopyJob item) => Contains(item.ID);
/// Copies the elements of the to an , starting at a particular index.
/// The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing. The zero-based index in at which copying begins.
void ICollection.CopyTo(BackgroundCopyJob[] array, int arrayIndex)
{
var ijobs = BackgroundCopyManager.EnumJobs((BG_JOB_ENUM)JobListRights);
var cnt = ijobs.GetCount();
Array.Copy(Array.ConvertAll(ijobs.Next(cnt), i => new BackgroundCopyJob(i)), 0, array, arrayIndex, cnt);
}
/// Returns an enumerator that iterates through a collection.
/// An object that can be used to iterate through the collection.
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
///
/// An implementation the interface that can iterate through the objects within the
/// collection.
///
private sealed class Enumerator : IEnumerator
{
private IBackgroundCopyJob icurrentjob;
private IEnumBackgroundCopyJobs ienum;
internal Enumerator(IEnumBackgroundCopyJobs enumjobs)
{
ienum = enumjobs;
ienum.Reset();
}
///
/// Gets the object in the collection to which the enumerator is pointing.
///
public BackgroundCopyJob Current => icurrentjob is not null ? new BackgroundCopyJob(icurrentjob) : throw new InvalidOperationException();
///
/// Gets the object in the collection to which the enumerator is pointing.
///
object IEnumerator.Current => Current;
/// Disposes of the Enumerator object.
public void Dispose()
{
ienum = null;
icurrentjob = null;
}
/// Moves the enumerator index to the next object in the collection.
///
public bool MoveNext()
{
try
{
icurrentjob = ienum.Next(1)?.FirstOrDefault();
return icurrentjob is not null;
}
catch { return false; }
}
/// Resets the enumerator index to the beginning of the collection.
public void Reset()
{
icurrentjob = null;
ienum.Reset();
}
}
}
}