using Connected.Entities; using Connected.Entities.Storage; using Connected.Interop; using Connected.Middleware; using Connected.ServiceModel; using Connected.Services; namespace Connected.Common.Numbering; internal sealed class NumberingOps { public sealed class Calculate : ServiceFunction { public Calculate(IMiddlewareService middleware) { Middleware = middleware; } private IMiddlewareService Middleware { get; } protected override async Task OnInvoke() { foreach (var middleware in await Middleware.Query()) { if (await middleware.Invoke(Arguments) is string result && !string.IsNullOrEmpty(result)) return result; } return null; } } public sealed class NextValue : ServiceFunction { public NextValue(IStorageProvider storage, INumberingService numbering) { Storage = storage; Numbering = numbering; } private IStorageProvider Storage { get; } private INumberingService Numbering { get; } protected override async Task OnInvoke() { var result = await Prepare(); await Storage.Open().Update(result, Arguments, async () => { result = await Prepare(); return result; }, async (f) => { await Task.CompletedTask; return f; }); return result.Value; } private async Task Prepare() { var current = await Numbering.Select(Arguments.AsArguments()); if (current is null) { var id = await TryInsert(); if (id == 0) current = await Numbering.Select(Arguments.AsArguments()); else current = await Numbering.Select(id); } if (current is null) throw new NullReferenceException(nameof(INumbering)); var newValue = string.Empty; if (TypeConversion.TryConvert(current.Value, out long existingValue)) newValue = existingValue++.ToString(); else newValue = current.Value; return (Numbering)current with { Value = newValue }; } private async Task TryInsert() { try { return (await Storage.Open().Update(Arguments.AsEntity(State.New))).Id; } catch { return 0; } } } public sealed class SelectByEntity : ServiceFunction { public SelectByEntity(IStorageProvider storage) { Storage = storage; } private IStorageProvider Storage { get; } protected override async Task OnInvoke() { return await (from e in Storage.Open() where string.Equals(e.Entity, Arguments.Entity, StringComparison.OrdinalIgnoreCase) select e).AsEntity(); } } public sealed class Select : ServiceFunction, INumbering> { public Select(IStorageProvider storage) { Storage = storage; } private IStorageProvider Storage { get; } protected override async Task OnInvoke() { return await (from e in Storage.Open() where e.Id == Arguments.Id select e).AsEntity(); } } }