Files
FileTime/src/Core/FileTime.Core/Command/CopyCommand.cs
2022-01-31 23:13:39 +01:00

119 lines
4.8 KiB
C#

using FileTime.Core.Models;
using FileTime.Core.Timeline;
namespace FileTime.Core.Command
{
public class CopyCommand : ITransportationCommand
{
private Action<AbsolutePath, AbsolutePath>? _copyOperation;
private Func<IContainer, string, Task<IContainer>>? _createContainer;
private TimeRunner? _timeRunner;
public IList<AbsolutePath>? Sources { get; } = new List<AbsolutePath>();
public IContainer? Target { get; set; }
public TransportMode? TransportMode { get; set; } = Command.TransportMode.Merge;
public async Task<PointInTime> SimulateCommand(PointInTime startPoint)
{
if (Sources == null) throw new ArgumentException(nameof(Sources) + " can not be null");
if (Target == null) throw new ArgumentException(nameof(Target) + " can not be null");
if (TransportMode == null) throw new ArgumentException(nameof(TransportMode) + " can not be null");
var newDiffs = new List<Difference>();
_copyOperation = (_, to) =>
{
var target = to.GetParentAsAbsolutePath().Resolve();
newDiffs.Add(new Difference(
target is IElement
? DifferenceItemType.Element
: DifferenceItemType.Container,
DifferenceActionType.Create,
to
));
};
_createContainer = async (IContainer target, string name) =>
{
var newContainerDiff = new Difference(
DifferenceItemType.Container,
DifferenceActionType.Create,
AbsolutePath.FromParentAndChildName(target, name)
);
newDiffs.Add(newContainerDiff);
return (IContainer)(await newContainerDiff.AbsolutePath.Resolve())!;
};
await DoCopy(Sources, Target, TransportMode.Value);
return startPoint.WithDifferences(newDiffs);
}
public async Task Execute(Action<AbsolutePath, AbsolutePath> copy, TimeRunner timeRunner)
{
if (Sources == null) throw new ArgumentException(nameof(Sources) + " can not be null");
if (Target == null) throw new ArgumentException(nameof(Target) + " can not be null");
if (TransportMode == null) throw new ArgumentException(nameof(TransportMode) + " can not be null");
_copyOperation = copy;
_createContainer = async (IContainer target, string name) => await target.CreateContainer(name);
_timeRunner = timeRunner;
await DoCopy(Sources, Target, TransportMode.Value);
}
private async Task DoCopy(
IEnumerable<AbsolutePath> sources,
IContainer target,
TransportMode transportMode)
{
if (_copyOperation == null) throw new ArgumentException("No copy operation were given.");
if (_createContainer == null) throw new ArgumentException("No container creation function were given.");
foreach (var source in sources)
{
var item = await source.Resolve();
if (item is IContainer container)
{
var targetContainer = (await target.GetContainers())?.FirstOrDefault(d => d.Name == container.Name) ?? (await _createContainer?.Invoke(target, container.Name)!);
var childDirectories = (await container.GetContainers())!.Select(d => new AbsolutePath(d));
var childFiles = (await container.GetElements())!.Select(f => new AbsolutePath(f));
await DoCopy(childDirectories.Concat(childFiles), targetContainer, transportMode);
_timeRunner?.RefreshContainer.InvokeAsync(this, new AbsolutePath(container));
}
else if (item is IElement element)
{
var targetName = element.Name;
var targetNameExists = await target.IsExists(targetName);
if (transportMode == Command.TransportMode.Merge)
{
for (var i = 0; targetNameExists; i++)
{
targetName = element.Name + (i == 0 ? "_" : $"_{i}");
}
}
else if (transportMode == Command.TransportMode.Skip && targetNameExists)
{
continue;
}
_copyOperation?.Invoke(new AbsolutePath(element), AbsolutePath.FromParentAndChildName(target, targetName));
}
}
}
public Task<CanCommandRun> CanRun(PointInTime startPoint)
{
//TODO: implement
return Task.FromResult(CanCommandRun.True);
}
}
}