using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; using Wabbajack.Hashing.xxHash64; using Wabbajack.Paths; namespace Wabbajack.VFS; public class IndexRoot { public static IndexRoot Empty = new(); public IndexRoot(IReadOnlyList aFiles, IDictionary byFullPath, ILookup byHash, IDictionary byRoot, ILookup byName) { AllFiles = aFiles; ByFullPath = byFullPath; ByHash = byHash; ByRootPath = byRoot; ByName = byName; } public IndexRoot() { AllFiles = ImmutableList.Empty; ByFullPath = new Dictionary(); ByHash = EmptyLookup.Instance; ByRootPath = new Dictionary(); ByName = EmptyLookup.Instance; } public IReadOnlyList AllFiles { get; } public IDictionary ByFullPath { get; } public ILookup ByHash { get; } public ILookup ByName { get; set; } public IDictionary ByRootPath { get; } public async Task Integrate(IEnumerable files) { var allFiles = AllFiles.Concat(files) .OrderByDescending(f => f.LastModified) .GroupBy(f => f.FullPath) .Select(g => g.Last()) .ToList(); var byFullPath = Task.Run(() => allFiles.SelectMany(f => f.ThisAndAllChildren) .ToDictionary(f => f.FullPath)); var byHash = Task.Run(() => allFiles.SelectMany(f => f.ThisAndAllChildren) .Where(f => f.Hash != default) .ToLookup(f => f.Hash)); var byName = Task.Run(() => allFiles.SelectMany(f => f.ThisAndAllChildren) .ToLookup(f => f.Name)); var byRootPath = Task.Run(() => allFiles.ToDictionary(f => f.AbsoluteName)); var result = new IndexRoot(allFiles, await byFullPath, await byHash, await byRootPath, await byName); return result; } public VirtualFile FileForArchiveHashPath(HashRelativePath argArchiveHashPath) { var cur = ByHash[argArchiveHashPath.Hash].First(f => f.Parent == null); return argArchiveHashPath.Parts.Aggregate(cur, (current, itm) => ByName[itm].First(f => f.Parent == current)); } public static class EmptyLookup { public static ILookup Instance { get; } = Enumerable.Empty().ToLookup(x => default(TKey)); } }