namespace AIStudio.Tools.PowerPoint;
///
/// One slide layout of a template.
///
/// The name the template gives the layout.
/// Where the layout is stored inside the file, which identifies it when the presentation is written.
/// The layout type as the file spells it, e.g., "title" or "secHead"; empty when the file states none.
/// The slots in reading order: from top to bottom, and from left to right within a row.
internal sealed record TemplateLayout(string Name, Uri PartUri, string LayoutType, IReadOnlyList Slots)
{
///
/// Finds the slot a placeholder of a slide based on this layout fills.
///
///
/// PowerPoint links the placeholders of a slide to those of its layout by their index, and a
/// placeholder without an index, such as the title, by its type. A slide often states the type
/// less precisely than its layout does, e.g., none at all for a body, so the index wins.
///
/// The placeholder type as the slide spells it; "obj" when it states none.
/// The placeholder index the slide states, if any.
/// The slot, or null when the placeholder fills none, e.g., because it is the footer.
public TemplateSlot? SlotOf(string placeholderType, uint? placeholderIndex)
{
if (placeholderIndex is { } index && this.Slots.FirstOrDefault(slot => slot.PlaceholderIndex == index) is { } slotByIndex)
return slotByIndex;
var typeGroup = TypeGroupOf(placeholderType);
return this.Slots.FirstOrDefault(slot => (slot.PlaceholderIndex is null || placeholderIndex is null) && TypeGroupOf(slot.PlaceholderType) == typeGroup);
}
///
/// The type a placeholder is matched by: a title is a title, whether it is centered or not.
///
private static string TypeGroupOf(string placeholderType) => placeholderType == "ctrTitle" ? "title" : placeholderType;
}