import Foundation

/// **What the running head and foot say** — "page footer/header", the card's fifth bullet, as four
/// toggles composed into two lines.
///
/// ### Why the pieces are composed here and not drawn here
///
/// Which pieces appear, in what order, and how a line reads when only some of them are switched on is a
/// *decision*, and decisions live in the pure layer where a test can hold them (`PrintDocumentBuilder`'s
/// own argument). Where the ink lands is `PrintDocumentView`'s.
///
/// ### The date and the page number arrive pre-formatted
///
/// Both are strings the caller supplies rather than a `Date` and an `Int` this type formats. That keeps
/// every rule below **locale-free and therefore testable**: "Page 3 of 7" and "9 Aug 2026 at 14:30" are
/// the caller's renderings of values the system formats differently in every region, and a rule that
/// baked them in would be a rule whose test only passed in one place.
///
/// ### Leading and trailing, not left and right
///
/// The two slots are named by reading order because that is what they are: the view places them at the
/// two ends of the measure, which a right-to-left interface swaps. Nothing here knows which end is
/// which.
public enum PrintRunningHead {

    /// A line of the running head or foot, as a pair of ends. Either may be empty; both empty means the
    /// line does not print at all, which is what `isEmpty` is for and what lets the view reclaim the
    /// space rather than leaving a band of blank paper.
    public struct Line: Sendable, Equatable {
        public var leading: String
        public var trailing: String

        public var isEmpty: Bool { leading.isEmpty && trailing.isEmpty }

        public init(leading: String = "", trailing: String = "") {
            self.leading = leading
            self.trailing = trailing
        }
    }

    /// The running head: the board's name at the leading end, the print's date at the trailing end.
    ///
    /// The board's name leads because it is what the reader is looking for when they pick the sheet up;
    /// the date trails because it answers a question they ask second. A board with no title contributes
    /// nothing rather than the word "Untitled" — the running head is context, and inventing context is
    /// worse than having none.
    public static func header(options: PrintOptions, boardTitle: String, dateText: String) -> Line {
        Line(
            leading: options.headerShowsBoardTitle ? boardTitle : "",
            trailing: options.headerShowsPrintDate ? dateText : ""
        )
    }

    /// The running foot: the user's own line at the leading end, the folio at the trailing end — where
    /// a book puts it.
    ///
    /// The custom line is read through `normalized`, so a toggle left on over an emptied field prints
    /// nothing rather than an indent of blank space (`PrintOptions.normalized`).
    public static func footer(options rawOptions: PrintOptions, pageText: String) -> Line {
        let options = rawOptions.normalized
        return Line(
            leading: options.footerShowsCustomLine ? options.footerCustomLine : "",
            trailing: options.footerShowsPageNumbers ? pageText : ""
        )
    }

    /// "Page 3 of 7" — the folio's wording, in one place because the view draws it and a summary line
    /// in the print panel describes it.
    public static func pageText(page: Int, of pageCount: Int) -> String {
        "Page \(page) of \(pageCount)"
    }
}
