namespace OpenNest.Data;
///
/// The customers, materials, grades and thicknesses an edit offers in its drop-downs: those
/// already used by library drawings, plus the materials and grades of a material catalog.
/// Names match by and keep the first spelling seen, so
/// pass the newest records first. Thicknesses come only from records in the edit's units.
/// The lists are suggestions; any typed value may still be saved.
///
public sealed class DrawingLibraryChoices
{
private readonly List _records;
private readonly List _catalog;
private DrawingLibraryChoices(List records, List catalog, Units units)
{
_records = records;
Units = units;
_catalog = catalog;
Customers = Distinct(records.Select(r => r.Customer));
Materials = Distinct(records.Select(r => r.MaterialName).Concat(catalog.Select(m => m.Name)));
}
public static DrawingLibraryChoices Empty { get; } = new(new(), new(), Units.Inches);
/// Library drawings, newest first; archived ones are skipped.
/// The edit's units; thicknesses in other units are not offered.
/// Materials and grades on file, for example the machine configurations'.
public static DrawingLibraryChoices From(IEnumerable records, Units units,
IEnumerable? catalog = null)
{
ArgumentNullException.ThrowIfNull(records);
return new DrawingLibraryChoices(records.Where(r => r != null && !r.Archived).ToList(),
catalog?.Where(m => m != null).ToList() ?? new(), units);
}
public Units Units { get; }
/// Customers, sorted.
public IReadOnlyList Customers { get; }
/// Material names, sorted.
public IReadOnlyList Materials { get; }
/// The grades used or on file for , sorted.
public IReadOnlyList GradesOf(string? material)
{
var key = SharedListNames.Key(material);
if (key.Length == 0)
return Array.Empty();
return Distinct(_records.Where(r => SharedListNames.Key(r.MaterialName) == key).Select(r => r.MaterialGrade)
.Concat(_catalog.Where(m => SharedListNames.Key(m.Name) == key).Select(m => m.Grade)));
}
///
/// The thicknesses library drawings of (and of
/// , when one is given) use, thinnest first.
///
public IReadOnlyList ThicknessesOf(string? material, string? grade)
{
var materialKey = SharedListNames.Key(material);
if (materialKey.Length == 0)
return Array.Empty();
var gradeKey = SharedListNames.Key(grade);
return _records
.Where(r => r.Units == Units && SharedListNames.Key(r.MaterialName) == materialKey
&& (gradeKey.Length == 0 || SharedListNames.Key(r.MaterialGrade) == gradeKey)
&& double.IsFinite(r.Thickness) && r.Thickness > 0)
.Select(r => DrawingLibraryRules.NormalizeThickness(r.Thickness))
.Distinct()
.OrderBy(t => t)
.ToList();
}
private static IReadOnlyList Distinct(IEnumerable names) =>
names
.Where(name => !string.IsNullOrWhiteSpace(name))
.Select(name => MaterialListRules.Spelling(name))
.GroupBy(SharedListNames.Key)
.Select(group => group.First())
.OrderBy(name => name, StringComparer.OrdinalIgnoreCase)
.ToList();
}