using FileTime.Core.Models; using FileTime.Core.Timeline; namespace FileTime.Core.Command { public class CopyCommand : ITransportationCommand { private Action? _copyOperation; private Func>? _createContainer; private TimeRunner? _timeRunner; public IList? Sources { get; } = new List(); public IContainer? Target { get; set; } public TransportMode? TransportMode { get; set; } = Command.TransportMode.Merge; public async Task 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(); _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 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 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 CanRun(PointInTime startPoint) { //TODO: implement return Task.FromResult(CanCommandRun.True); } } }