public class DrawTreeService
{
private readonly ConcurrentQueue<IEnumerable<string>> FileLists = new();
public readonly Tree MainTree = new Tree();
private readonly CancellationTokenSource CancellationTokenSource = new();
private CancellationToken CancellationToken => CancellationTokenSource.Token;
public DrawTreeService()
{
Task.Run(ProcessFileLists);
}
public void Cancel()
{
CancellationTokenSource.Cancel();
}
public void EnqueueList(IEnumerable<string> list)
{
FileLists.Enqueue(list);
}
public class Tree
{
public readonly Dictionary<string, Tree> Trees = new Dictionary<string, Tree>();
public readonly HashSet<string> Files = new HashSet<string>();
}
private async Task ProcessFileLists()
{
while (!CancellationToken.IsCancellationRequested)
{
if (!FileLists.TryDequeue(out var list))
{
await Task.Delay(100);
continue;
}
var isNewElements = DrawTree(MainTree, list);
if (isNewElements)
{
// TODO Дописываем вызов event-ов, заассоциированных с пересборкой дерева
foreach (var i in list)
{
Console.WriteLine(i);
}
}
}
}
private static bool DrawTree(Tree rootTree, IEnumerable<string> list)
{
var u = false;
foreach (var filename in list
.Where(x => !x.Contains('/'))
.Where(x => !rootTree.Files.Contains(x)))
{
rootTree.Files.Add(filename);
u = true;
}
var subfolders = list
.Where(x => x.Contains('/'))
.Select(filename =>
{
var array = filename.Split('/');
var prefix = array.First();
var subFile = array.Skip(1).Aggregate((a, b) => a + '/' + b);
return (prefix, filename: subFile);
})
.ToArray();
subfolders
.GroupBy(t => t.prefix)
.ToList()
.ForEach(t =>
{
var folder = t.Key;
if (!rootTree.Trees.ContainsKey(folder))
{
rootTree.Trees[folder] = new Tree();
u = true;
}
var u1 = DrawTree(rootTree.Trees[folder], t.Select(t1 => t1.filename).ToArray());
u |= u1;
});
return u;
}
}