namespace OpenNest.Data; /// /// Edits one listed library drawing's notes and nesting settings in place: the save is a /// metadata-only revision guarded by the revision it was listed with, so the package (and /// its hash) stays the same. A stale revision raises /// and changes nothing. /// public sealed class DrawingLibraryEditSession { private readonly IDrawingLibraryStore _library; public DrawingLibraryEditSession(IDrawingLibraryStore library, DrawingLibraryRecord listed, string savedBy) { _library = library ?? throw new ArgumentNullException(nameof(library)); Listed = listed ?? throw new ArgumentNullException(nameof(listed)); if (listed.Id == Guid.Empty || listed.Revision < 1) throw new ArgumentException("Choose a listed library drawing to edit.", nameof(listed)); if (listed.Archived) throw new ArgumentException("An archived library drawing cannot be edited. Restore it first.", nameof(listed)); SavedBy = savedBy ?? ""; } /// The record as it was listed; its revision guards the save. public DrawingLibraryRecord Listed { get; } public string SavedBy { get; } /// The record to save: the listed details with new notes and settings. public DrawingLibraryRecord Build(string notes, DrawingNestingSettings settings) => new() { Id = Listed.Id, Name = Listed.Name, Customer = Listed.Customer, MaterialName = Listed.MaterialName, MaterialGrade = Listed.MaterialGrade, Thickness = Listed.Thickness, Units = Listed.Units, CutType = Listed.CutType, Notes = notes ?? "", Settings = settings ?? throw new ArgumentNullException(nameof(settings)), SavedBy = SavedBy, }; /// The first rule the edit breaks, or null when it may be saved. public string? GetError(string notes, DrawingNestingSettings settings) => DrawingLibraryRules.GetMetadataError(Build(notes, settings)); /// True when saving would change nothing. public bool IsUnchanged(string notes, DrawingNestingSettings settings) => (notes ?? "") == Listed.Notes && Equals(settings, Listed.Settings); /// Saves the edit as the next revision; returns the stored record. public async Task SaveAsync(string notes, DrawingNestingSettings settings, CancellationToken cancellationToken = default) { var record = Build(notes, settings); var error = DrawingLibraryRules.GetMetadataError(record); if (error != null) throw new ArgumentException(error, nameof(settings)); var saved = await _library.UpdateMetadataAsync(Listed.Id, record, Listed.Revision, cancellationToken); if (!string.Equals(saved.PackageSha256, Listed.PackageSha256, StringComparison.OrdinalIgnoreCase) || !Equals(saved.Settings, record.Settings) || saved.Notes != record.Notes) throw new IOException("The nest server stored a different library drawing than was edited. Reload the library."); return saved; } }