using Disco.Data.Repository; using Disco.Models.Repository; using Disco.Models.Services.Documents; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; namespace Disco.Services.Documents { public static class DocumentTemplatePackages { private static ConcurrentDictionary cache; static DocumentTemplatePackages() { using (var database = new DiscoDataContext()) { var packages = database.DiscoConfiguration.Documents.Packages; if (packages == null) { cache = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); } else { cache = new ConcurrentDictionary( packages.Select(p => new KeyValuePair(p.Id, p)), StringComparer.OrdinalIgnoreCase); } } } public static List GetPackages() => cache.Values.ToList(); public static DocumentTemplatePackage GetPackage(string Id) { DocumentTemplatePackage package; if (cache.TryGetValue(Id, out package)) return package; else return null; } public static IEnumerable AvailablePackages(DiscoDataContext Database, AttachmentTypes Scope) { var packages = cache.Values.Where(p => p.Scope == Scope).ToList(); if (packages.Count > 0) { var dbScope = Scope.ToString(); var validTemplateIds = Database.DocumentTemplates .Where(dt => dt.Scope == dbScope) .Select(dt => dt.Id).ToList(); return packages.Where(p => !p.IsHidden && p.DocumentTemplateIds != null && p.DocumentTemplateIds.Count > 0 && p.DocumentTemplateIds.Count(id => validTemplateIds.Contains(id)) > 0); } return Enumerable.Empty(); } public static List AvailablePackages(this Device device, DiscoDataContext Database, User TechnicianUser) { var packages = new List(); foreach (var package in AvailablePackages(Database, AttachmentTypes.Device)) { if (package.FilterExpressionMatches(device, Database, TechnicianUser, DateTime.Now, DocumentState.DefaultState())) { packages.Add(package); } } return packages; } public static List AvailablePackages(this Job job, DiscoDataContext Database, User TechnicianUser) { var packages = new List(); foreach (var package in AvailablePackages(Database, AttachmentTypes.Job)) { bool subTypeMatch = true; // default match if (package.JobSubTypes != null && package.JobSubTypes.Count > 0) { subTypeMatch = false; // enforce match foreach (var subType in job.JobSubTypes) { if (package.JobSubTypes.Contains($"{subType.JobTypeId}_{subType.Id}", StringComparer.OrdinalIgnoreCase)) { subTypeMatch = true; break; } } } if (subTypeMatch) { if (package.FilterExpressionMatches(job, Database, TechnicianUser, DateTime.Now, DocumentState.DefaultState())) { packages.Add(package); } } } return packages; } public static List AvailablePackages(this User user, DiscoDataContext Database, User TechnicianUser) { var packages = new List(); foreach (var package in AvailablePackages(Database, AttachmentTypes.User)) { if (package.FilterExpressionMatches(user, Database, TechnicianUser, DateTime.Now, DocumentState.DefaultState())) { packages.Add(package); } } return packages; } public static DocumentTemplatePackage CreatePackage(DocumentTemplatePackage Package) { if (string.IsNullOrWhiteSpace(Package.Id)) throw new ArgumentNullException(nameof(Package), "The Package Id is required"); if (cache.ContainsKey(Package.Id)) // Name Unique throw new ArgumentException("Another Package already exists with that Id", nameof(Package)); if (string.IsNullOrWhiteSpace(Package.Description)) throw new ArgumentNullException(nameof(Package), "The Package Description is required"); if (cache.TryAdd(Package.Id, Package)) { PersistCache(); return Package; } else throw new Exception("Unable to add the Package to the Cache, check the Package Id and try again"); } public static DocumentTemplatePackage UpdatePackage(DocumentTemplatePackage Package) { DocumentTemplatePackage existingPackage; if (string.IsNullOrWhiteSpace(Package.Id)) throw new ArgumentNullException(nameof(Package), "The Package Id is required"); if (!cache.TryGetValue(Package.Id, out existingPackage)) // Name Unique throw new ArgumentException("The Package Id does not exist", nameof(Package)); if (string.IsNullOrWhiteSpace(Package.Description)) throw new ArgumentNullException(nameof(Package), "The Package Description is required"); if (cache.TryUpdate(Package.Id, Package, existingPackage)) { PersistCache(); return Package; } else throw new Exception("Unable to update the Package in the Cache, there were concurrent updates to the same package"); } public static void RemovePackage(string Id) { DocumentTemplatePackage existingPackage; if (cache.TryRemove(Id, out existingPackage)) { PersistCache(); } } private static void PersistCache() { var packages = cache.Values.ToList(); if (packages.Count == 0) packages = null; using (var database = new DiscoDataContext()) { database.DiscoConfiguration.Documents.Packages = packages; database.SaveChanges(); } } } }