"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.format = format;
const calendarMath_js_1 = require("../utils/calendarMath.js");
const dateConversion_js_1 = require("../utils/dateConversion.js");
const serial_js_1 = require("../utils/serial.js");
const fallbackMonthNames = {
    tishrei: { en: "Tishrei", he: "תשרי" },
    cheshvan: { en: "Cheshvan", he: "חשוון" },
    kislev: { en: "Kislev", he: "כסלו" },
    tevet: { en: "Tevet", he: "טבת" },
    shevat: { en: "Shevat", he: "שבט" },
    adarI: { en: "Adar I", he: "אדר א׳" },
    adar: { en: "Adar", he: "אדר" },
    nisan: { en: "Nisan", he: "ניסן" },
    iyar: { en: "Iyar", he: "אייר" },
    sivan: { en: "Sivan", he: "סיוון" },
    tamuz: { en: "Tammuz", he: "תמוז" },
    av: { en: "Av", he: "אב" },
    elul: { en: "Elul", he: "אלול" },
};
const fallbackWeekdayNames = {
    long: {
        en: [
            "Sunday",
            "Monday",
            "Tuesday",
            "Wednesday",
            "Thursday",
            "Friday",
            "Saturday",
        ],
        he: [
            "יום ראשון",
            "יום שני",
            "יום שלישי",
            "יום רביעי",
            "יום חמישי",
            "יום שישי",
            "שבת",
        ],
    },
    narrow: {
        en: ["S", "M", "T", "W", "T", "F", "S"],
        he: ["א", "ב", "ג", "ד", "ה", "ו", "ש"],
    },
};
const getLocaleCode = (options) => {
    return options?.locale?.code ?? "he";
};
const getMonthCodeForDate = (date) => {
    const hebrew = (0, dateConversion_js_1.toHebrewDate)(date);
    return (0, calendarMath_js_1.getMonthCode)(hebrew.year, hebrew.monthIndex);
};
const formatMonthName = (date, localeCode) => {
    try {
        return new Intl.DateTimeFormat(localeCode, {
            month: "long",
            calendar: "hebrew",
        }).format(date);
    }
    catch {
        const code = getMonthCodeForDate(date);
        const isHebrew = localeCode.startsWith("he");
        return isHebrew ? fallbackMonthNames[code].he : fallbackMonthNames[code].en;
    }
};
const formatWeekdayName = (date, localeCode, width) => {
    try {
        return new Intl.DateTimeFormat(localeCode, {
            weekday: width,
            calendar: "hebrew",
        }).format(date);
    }
    catch {
        const index = date.getDay();
        const isHebrew = localeCode.startsWith("he");
        return isHebrew
            ? fallbackWeekdayNames[width].he[index]
            : fallbackWeekdayNames[width].en[index];
    }
};
const formatDateStyle = (date, localeCode, style) => {
    try {
        return new Intl.DateTimeFormat(localeCode, {
            dateStyle: style,
            calendar: "hebrew",
        }).format(date);
    }
    catch {
        const hebrew = (0, dateConversion_js_1.toHebrewDate)(date);
        const month = formatMonthName(date, localeCode);
        if (style === "full") {
            const weekday = formatWeekdayName(date, localeCode, "long");
            return `${weekday}, ${month} ${hebrew.day}, ${hebrew.year}`;
        }
        return `${month} ${hebrew.day}, ${hebrew.year}`;
    }
};
const formatNumber = (value) => {
    return value.toString();
};
const buildTimeFormat = (date, localeCode, formatStr) => {
    const hour12 = formatStr.includes("a");
    return new Intl.DateTimeFormat(localeCode, {
        hour: "numeric",
        minute: "numeric",
        hour12,
    }).format(date);
};
/** Hebrew calendar formatting override. */
function format(date, formatStr, options) {
    const extendedOptions = options;
    const localeCode = getLocaleCode(extendedOptions);
    const hebrew = (0, dateConversion_js_1.toHebrewDate)(date);
    const monthNumber = (0, serial_js_1.hebrewMonthNumber)(hebrew.monthIndex);
    switch (formatStr) {
        case "LLLL y":
        case "LLLL yyyy":
            return `${formatMonthName(date, localeCode)} ${formatNumber(hebrew.year)}`;
        case "LLLL":
            return formatMonthName(date, localeCode);
        case "PPP":
            return formatDateStyle(date, localeCode, "long");
        case "PPPP":
            return formatDateStyle(date, localeCode, "full");
        case "cccc":
            return formatWeekdayName(date, localeCode, "long");
        case "cccccc":
            return formatWeekdayName(date, localeCode, "narrow");
        case "yyyy":
        case "y":
            return formatNumber(hebrew.year);
        case "yyyy-MM":
            return `${formatNumber(hebrew.year)}-${formatNumber(monthNumber).padStart(2, "0")}`;
        case "yyyy-MM-dd":
            return `${formatNumber(hebrew.year)}-${formatNumber(monthNumber).padStart(2, "0")}-${formatNumber(hebrew.day).padStart(2, "0")}`;
        case "MM":
            return formatNumber(monthNumber).padStart(2, "0");
        case "M":
            return formatNumber(monthNumber);
        case "dd":
            return formatNumber(hebrew.day).padStart(2, "0");
        case "d":
            return formatNumber(hebrew.day);
        default:
            if (/[Hh]/.test(formatStr) && /m/.test(formatStr)) {
                return buildTimeFormat(date, localeCode, formatStr);
            }
            return `${formatNumber(hebrew.day)}/${formatNumber(monthNumber)}/${formatNumber(hebrew.year)}`;
    }
}
