// #region Imports
import { tryGet } from '../Extensions/Extensions';
// #endregion
/**
 * A utility class for formatting dates using format strings.
 *
 * Supported format specifiers:
 * - `d`   : Day of the month (1-31) without leading zero.
 * - `dd`  : Day of the month (01-31) with leading zero.
 * - `ddd` : Abbreviated name of the day of the week (e.g., Mon, Tue).
 * - `dddd`: Full name of the day of the week (e.g., Monday, Tuesday).
 * - `h`   : Hour (1-12) in 12-hour format without leading zero.
 * - `hh`  : Hour (01-12) in 12-hour format with leading zero.
 * - `H`   : Hour (0-23) in 24-hour format without leading zero.
 * - `HH`  : Hour (00-23) in 24-hour format with leading zero.
 * - `m`   : Minute (0-59) without leading zero.
 * - `mm`  : Minute (00-59) with leading zero.
 * - `M`   : Month (1-12) without leading zero.
 * - `MM`  : Month (01-12) with leading zero.
 * - `MMM` : Abbreviated name of the month (e.g., Jan, Feb).
 * - `MMMM`: Full name of the month (e.g., January, February).
 * - `s`   : Second (0-59) without leading zero.
 * - `ss`  : Second (00-59) with leading zero.
 * - `t`   : First character of the AM/PM designator (e.g., A or P).
 * - `tt`  : Full AM/PM designator (e.g., AM or PM).
 * - `y`   : Year as the last two digits without leading zero (e.g., 9 for 2009).
 * - `yy`  : Year as the last two digits with leading zero (e.g., 09 for 2009).
 * - `yyy` : Year with a minimum of three digits (e.g., 009, 2009).
 * - `yyyy`: Year as a four-digit number (e.g., 2009).
 * - `:`   : Time separator (e.g., colon).
 * - `/`   : Date separator (e.g., slash).
 * - `-`   : Custom separator (e.g., hyphen).
 * - `.`   : Custom separator (e.g., dot).
 *
 * @public
 */
export class DateTimeFormatter {
    static _validSpecifiers = [
        'd', 'dd', 'ddd', 'dddd',
        'h', 'hh', 'H', 'HH',
        'm', 'mm',
        'M', 'MM', 'MMM', 'MMMM',
        's', 'ss',
        't', 'tt',
        'y', 'yy', 'yyy', 'yyyy',
        ':', '/', '-', '.'
    ];
    static _formatMapping = {
        'd': { day: 'numeric' },
        'dd': { day: '2-digit' },
        'ddd': { weekday: 'short' },
        'dddd': { weekday: 'long' },
        'h': {
            hour: 'numeric',
            hour12: true
        },
        'hh': {
            hour: '2-digit',
            hour12: true
        },
        'H': {
            hour: 'numeric',
            hour12: false
        },
        'HH': {
            hour: '2-digit',
            hour12: false
        },
        'm': { minute: 'numeric' },
        'mm': { minute: '2-digit' },
        'M': { month: 'numeric' },
        'MM': { month: '2-digit' },
        'MMM': { month: 'short' },
        'MMMM': { month: 'long' },
        's': { second: 'numeric' },
        'ss': { second: '2-digit' },
        't': {}, // AM/PM not directly supported
        'tt': { hour12: true },
        'y': { year: '2-digit' },
        'yy': { year: '2-digit' },
        'yyy': { year: 'numeric' },
        'yyyy': { year: 'numeric' },
        ':': {}, // Time separator
        '/': {}, // Date separator
        '-': {}, // Custom separator (hyphen)
        '.': {} // Custom separator (dot)
    };
    /**
     * Validates that a format string contains only valid datetime format specifiers.
     *
     * @param format The format string.
     * @returns A validated format string.
     * @throws Error if the format contains invalid specifiers.
     */
    static validateFormat(format) {
        const regex = new RegExp(`^(${this._validSpecifiers.join('|')}|[-:/. ])+$`);
        if (!regex.test(format)) {
            throw new Error(`Invalid format string: "${format}".`);
        }
        return format;
    }
    /**
     * Formats a date using a format string.
     *
     * @param date The date to format.
     * @param format The format string.
     * @param locale The locale for Intl formatting (default: 'en-US').
     * @returns The formatted date string.
     */
    static format(date, format, locale = 'en-US') {
        const segments = format.match(/d{1,4}|y{1,4}|M{1,4}|H{1,2}|h{1,2}|m{1,2}|s{1,2}|t{1,2}|[-:/. ]+/g);
        if (!segments) {
            throw new Error(`Unable to parse format string: "${format}".`);
        }
        return segments
            .map((segment) => {
            const intlOptions = tryGet(this._formatMapping, segment);
            if (intlOptions) {
                if ((/[-:/. ]+/).test(segment)) {
                    return segment; // Return separator as-is
                }
                const d = new Intl.DateTimeFormat(locale, intlOptions).format(date);
                console.log(segment, d);
                return d;
            }
            // Unknown format segment
            return segment;
        })
            .join('');
    }
}
//# sourceMappingURL=DateTimeFormatter.js.map