using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using InABox.Clients; namespace InABox.Core { public class MultiQuery { private readonly List _queries = new List(); public int Count => _queries.Count; public Dictionary Definitions() { Dictionary result = new Dictionary(); foreach (var query in _queries) result[query.Key] = query.Query; return result; } public IEnumerable> Results() { foreach (var query in _queries) if(query.Result != null) yield return new KeyValuePair(query.Key, query.Result); } public void Clear() { _queries.Clear(); } public void Add(IQueryDef query, object key) { if (key == null) throw new Exception("MultiQuery Key many not be null"); if (_queries.Any(x => Equals(x.Key, key))) throw new Exception("Key already exists"); _queries.Add(new InternalQueryDef(key, query)); } public void Query(Action? callback = null) { var tasks = new Dictionary>(); foreach (var query in _queries) { tasks[query.Key] = Task.Run(() => { return Client.Create(query.Query.Type) .Query(query.Query.Filter, query.Query.Columns, query.Query.SortOrder, query.Query.Range); }); } if (callback is null) { Task.WaitAll(tasks.Values.ToArray()); foreach(var query in _queries) { if(tasks.TryGetValue(query.Key, out var task)) { query.Result = task.Result; } } } else { Task.WhenAll(tasks.Values.ToArray()).ContinueWith(t => { foreach(var query in _queries) { if(tasks.TryGetValue(query.Key, out var task)) { query.Result = task.Result; } } callback.Invoke(this); }); } } public bool Contains(object key) { return _queries.Any(x => Equals(x.Key, key)); } public CoreTable Get(object key) { var query = _queries.FirstOrDefault(x => Equals(x.Key, key)); if (query == null) throw new Exception("Key does not exist"); if (query.Result == null) throw new Exception("No result available"); return query.Result; } public void Set(object key, CoreTable table) { var query = _queries.FirstOrDefault(x => Equals(x.Key, key)) ?? throw new Exception("Key does not exist"); query.Result = table; } private class InternalQueryDef { public object Key { get; set; } public IQueryDef Query { get; set; } public CoreTable? Result { get; set; } public InternalQueryDef(object key, IQueryDef query) { Key = key; Query = query; } } #region Simplified Generic Helpers public void Add(QueryDef query) where T : Entity, IRemotable, IPersistent, new() { Add(query, typeof(T)); } public void Add(Filter? filter = null, Columns? columns = null, SortOrder? sort = null, CoreRange? range = null) where T : Entity, IRemotable, IPersistent, new() { Add(new QueryDef(filter, columns, sort, range), typeof(T)); } public CoreTable Get() { return Get(typeof(T)); } public bool Contains() { return Contains(typeof(T)); } #endregion } }