using Microsoft.EntityFrameworkCore; using SharedLibraryCore.Database; using SharedLibraryCore.Database.Models; using SharedLibraryCore.Dtos; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace SharedLibraryCore.Services { public class MetaService { private static List>>> _metaActions = new List>>>(); /// /// adds or updates meta key and value to the database /// /// key of meta data /// value of the meta data /// client to save the meta for /// public async Task AddPersistentMeta(string metaKey, string metaValue, EFClient client) { using (var ctx = new DatabaseContext()) { var existingMeta = await ctx.EFMeta .Where(_meta => _meta.Key == metaKey) .Where(_meta => _meta.ClientId == client.ClientId) .FirstOrDefaultAsync(); if (existingMeta != null) { existingMeta.Value = metaValue; existingMeta.Updated = DateTime.UtcNow; } else { ctx.EFMeta.Add(new EFMeta() { ClientId = client.ClientId, Created = DateTime.UtcNow, Key = metaKey, Value = metaValue }); } await ctx.SaveChangesAsync(); } } /// /// retrieves meta data for given client and key /// /// key to retrieve value for /// client to retrieve meta for /// public async Task GetPersistentMeta(string metaKey, EFClient client) { using (var ctx = new DatabaseContext(disableTracking: true)) { return await ctx.EFMeta .Where(_meta => _meta.Key == metaKey) .Where(_meta => _meta.ClientId == client.ClientId) .FirstOrDefaultAsync(); } } /// /// aads a meta task to the runtime meta list /// /// public static void AddRuntimeMeta(Func>> metaAction) { _metaActions.Add(metaAction); } /// /// retrieves all the runtime meta information for given client idea /// /// id of the client /// number of meta items to retrieve /// offset from the first item /// public static async Task> GetRuntimeMeta(int clientId, int offset = 0, int count = int.MaxValue, DateTime? startAt = null) { var meta = new List(); foreach (var action in _metaActions) { var metaItems = await action(clientId, offset, count, startAt); meta.AddRange(metaItems); } if (count == 1) { var table = new List>(); var metaWithColumn = meta .Where(_meta => _meta.Column != null); var columnGrouping = metaWithColumn .GroupBy(_meta => _meta.Column); var metaToSort = meta.Except(metaWithColumn).ToList(); foreach (var metaItem in columnGrouping) { table.Add(new List(metaItem)); } while (metaToSort.Count > 0) { var sortingMeta = metaToSort.First(); int indexOfSmallestColumn() { int index = 0; int smallestColumnSize = int.MaxValue; for (int i = 0; i < table.Count; i++) { if (table[i].Count < smallestColumnSize) { smallestColumnSize = table[i].Count; index = i; } } return index; } int columnIndex = indexOfSmallestColumn(); sortingMeta.Column = columnIndex; sortingMeta.Order = columnGrouping .First(_group => _group.Key == columnIndex) .Count(); table[columnIndex].Add(sortingMeta); metaToSort.Remove(sortingMeta); } return meta; } return meta.OrderByDescending(_meta => _meta.When) .Take(count) .ToList(); } } }