using AsyncEvent; using FileTime.Core.Providers; namespace FileTime.Core.Models { public class VirtualContainer : IContainer { private readonly List, IEnumerable>> _containerTransformators; private readonly List, IEnumerable>> _elementTransformators; public IContainer BaseContainer { get; } public bool IsPermanent { get; } public bool IsTransitive { get; } public string? VirtualContainerName { get; } public IReadOnlyList? Items { get; private set; } public IReadOnlyList? Containers { get; private set; } public IReadOnlyList? Elements { get; private set; } public string Name => BaseContainer.Name; public string? FullName => BaseContainer.FullName; public string? NativePath => BaseContainer.NativePath; public bool IsHidden => BaseContainer.IsHidden; public bool IsLoaded => BaseContainer.IsLoaded; public SupportsDelete CanDelete => BaseContainer.CanDelete; public bool CanRename => BaseContainer.CanRename; public IContentProvider Provider => BaseContainer.Provider; public IReadOnlyList Exceptions => BaseContainer.Exceptions; public bool SupportsDirectoryLevelSoftDelete => BaseContainer.SupportsDirectoryLevelSoftDelete; public AsyncEventHandler Refreshed { get; } public bool IsDestroyed => BaseContainer.IsDestroyed; private void RefreshAddBase(Func handler) { BaseContainer.Refreshed.Add(handler); } private void RefreshRemoveBase(Func handler) { BaseContainer.Refreshed.Add(handler); } public VirtualContainer( IContainer baseContainer, List, IEnumerable>> containerTransformators, List, IEnumerable>> elementTransformators, bool isPermanent = false, bool isTransitive = false, string? virtualContainerName = null) { Refreshed = new(RefreshAddBase, RefreshRemoveBase); BaseContainer = baseContainer; _containerTransformators = containerTransformators; _elementTransformators = elementTransformators; IsPermanent = isPermanent; IsTransitive = isTransitive; VirtualContainerName = virtualContainerName; } public async Task Init() { await InitItems(); } private async Task InitItems(CancellationToken token = default) { Containers = _containerTransformators.Aggregate((await BaseContainer.GetContainers(token))?.AsEnumerable(), (a, t) => t(a!))?.ToList()?.AsReadOnly(); Elements = _elementTransformators.Aggregate((await BaseContainer.GetElements(token))?.AsEnumerable(), (a, t) => t(a!))?.ToList()?.AsReadOnly(); Items = (Elements != null ? Containers?.Cast().Concat(Elements) : Containers?.Cast()) ?.ToList().AsReadOnly(); } public async Task GetByPath(string path, bool acceptDeepestMatch = false) => await BaseContainer.GetByPath(path, acceptDeepestMatch); public IContainer? GetParent() => BaseContainer.GetParent(); public async Task RefreshAsync(CancellationToken token = default) { await BaseContainer.RefreshAsync(token); await InitItems(token); } public IContainer GetRealContainer() => BaseContainer is VirtualContainer virtualContainer ? virtualContainer.GetRealContainer() : BaseContainer; public bool HasWithName(string name) => VirtualContainerName == name || (BaseContainer is VirtualContainer virtualContainer && virtualContainer.HasWithName(name)); public async Task ExceptWithName(string name) { if (BaseContainer is VirtualContainer virtualBaseContainer && virtualBaseContainer.VirtualContainerName == name) { var newContainer = new VirtualContainer( await virtualBaseContainer.ExceptWithName(name), _containerTransformators, _elementTransformators, IsPermanent, IsTransitive, VirtualContainerName); await newContainer.Init(); return newContainer; } else if (VirtualContainerName == name) { return BaseContainer; } return this; } public IContainer CloneVirtualChainFor(IContainer container, Func predicate) { var baseContainer = BaseContainer is VirtualContainer baseVirtualContainer ? baseVirtualContainer.CloneVirtualChainFor(container, predicate) : container; return predicate(this) ? new VirtualContainer( baseContainer, _containerTransformators, _elementTransformators, IsPermanent, IsTransitive, VirtualContainerName) : baseContainer; } public async Task CreateContainerAsync(string name) => await BaseContainer.CreateContainerAsync(name); public async Task CreateElementAsync(string name) => await BaseContainer.CreateElementAsync(name); public async Task IsExistsAsync(string name) => await BaseContainer.IsExistsAsync(name); public Task?> GetItems(CancellationToken token = default) { return Task.FromResult(Items); } public Task?> GetContainers(CancellationToken token = default) { return Task.FromResult(Containers); } public Task?> GetElements(CancellationToken token = default) { return Task.FromResult(Elements); } public async Task Delete(bool hardDelete = false) => await BaseContainer.Delete(); public async Task CloneAsync() { return new VirtualContainer( await BaseContainer.CloneAsync(), _containerTransformators, _elementTransformators, IsPermanent, IsTransitive, VirtualContainerName ); } public async Task Rename(string newName) => await BaseContainer.Rename(newName); public async Task CanOpenAsync() => await BaseContainer.CanOpenAsync(); public void Destroy() { BaseContainer.Destroy(); } public void Unload() { BaseContainer.Unload(); } } }