import { DATETIME_FULL, DATETIME_FULL_WITH_SECONDS, DATETIME_HUGE, DATETIME_HUGE_WITH_SECONDS, DATETIME_MED, DATETIME_MED_WITH_SECONDS, DATETIME_SHORT, DATETIME_SHORT_WITH_SECONDS, DATE_FULL, DATE_HUGE, DATE_MED, DATE_SHORT, TIME_24_SIMPLE, TIME_24_WITH_LONG_OFFSET, TIME_24_WITH_SECONDS, TIME_24_WITH_SHORT_OFFSET, TIME_SIMPLE, TIME_WITH_LONG_OFFSET, TIME_WITH_SECONDS, TIME_WITH_SHORT_OFFSET } from "./formats.mjs";
import { padStart } from "./util.mjs";
import { eraForDateTime, meridiemForDateTime, monthForDateTime, weekdayForDateTime } from "./english.mjs";

//#region ../../node_modules/.pnpm/luxon@3.5.0/node_modules/luxon/src/impl/formatter.js
function stringifyTokens(splits, tokenToString) {
	let s = "";
	for (const token of splits) if (token.literal) s += token.val;
	else s += tokenToString(token.val);
	return s;
}
const macroTokenToFormatOpts = {
	D: DATE_SHORT,
	DD: DATE_MED,
	DDD: DATE_FULL,
	DDDD: DATE_HUGE,
	t: TIME_SIMPLE,
	tt: TIME_WITH_SECONDS,
	ttt: TIME_WITH_SHORT_OFFSET,
	tttt: TIME_WITH_LONG_OFFSET,
	T: TIME_24_SIMPLE,
	TT: TIME_24_WITH_SECONDS,
	TTT: TIME_24_WITH_SHORT_OFFSET,
	TTTT: TIME_24_WITH_LONG_OFFSET,
	f: DATETIME_SHORT,
	ff: DATETIME_MED,
	fff: DATETIME_FULL,
	ffff: DATETIME_HUGE,
	F: DATETIME_SHORT_WITH_SECONDS,
	FF: DATETIME_MED_WITH_SECONDS,
	FFF: DATETIME_FULL_WITH_SECONDS,
	FFFF: DATETIME_HUGE_WITH_SECONDS
};
/**
* @private
*/
var Formatter = class Formatter {
	static create(locale, opts = {}) {
		return new Formatter(locale, opts);
	}
	static parseFormat(fmt) {
		let current = null, currentFull = "", bracketed = false;
		const splits = [];
		for (let i = 0; i < fmt.length; i++) {
			const c = fmt.charAt(i);
			if (c === "'") {
				if (currentFull.length > 0) splits.push({
					literal: bracketed || /^\s+$/.test(currentFull),
					val: currentFull
				});
				current = null;
				currentFull = "";
				bracketed = !bracketed;
			} else if (bracketed) currentFull += c;
			else if (c === current) currentFull += c;
			else {
				if (currentFull.length > 0) splits.push({
					literal: /^\s+$/.test(currentFull),
					val: currentFull
				});
				currentFull = c;
				current = c;
			}
		}
		if (currentFull.length > 0) splits.push({
			literal: bracketed || /^\s+$/.test(currentFull),
			val: currentFull
		});
		return splits;
	}
	static macroTokenToFormatOpts(token) {
		return macroTokenToFormatOpts[token];
	}
	constructor(locale, formatOpts) {
		this.opts = formatOpts;
		this.loc = locale;
		this.systemLoc = null;
	}
	formatWithSystemDefault(dt, opts) {
		if (this.systemLoc === null) this.systemLoc = this.loc.redefaultToSystem();
		return this.systemLoc.dtFormatter(dt, {
			...this.opts,
			...opts
		}).format();
	}
	dtFormatter(dt, opts = {}) {
		return this.loc.dtFormatter(dt, {
			...this.opts,
			...opts
		});
	}
	formatDateTime(dt, opts) {
		return this.dtFormatter(dt, opts).format();
	}
	formatDateTimeParts(dt, opts) {
		return this.dtFormatter(dt, opts).formatToParts();
	}
	formatInterval(interval, opts) {
		return this.dtFormatter(interval.start, opts).dtf.formatRange(interval.start.toJSDate(), interval.end.toJSDate());
	}
	resolvedOptions(dt, opts) {
		return this.dtFormatter(dt, opts).resolvedOptions();
	}
	num(n, p = 0) {
		if (this.opts.forceSimple) return padStart(n, p);
		const opts = { ...this.opts };
		if (p > 0) opts.padTo = p;
		return this.loc.numberFormatter(opts).format(n);
	}
	formatDateTimeFromString(dt, fmt) {
		const knownEnglish = this.loc.listingMode() === "en", useDateTimeFormatter = this.loc.outputCalendar && this.loc.outputCalendar !== "gregory", string = (opts, extract) => this.loc.extract(dt, opts, extract), formatOffset = (opts) => {
			if (dt.isOffsetFixed && dt.offset === 0 && opts.allowZ) return "Z";
			return dt.isValid ? dt.zone.formatOffset(dt.ts, opts.format) : "";
		}, meridiem = () => knownEnglish ? meridiemForDateTime(dt) : string({
			hour: "numeric",
			hourCycle: "h12"
		}, "dayperiod"), month = (length, standalone) => knownEnglish ? monthForDateTime(dt, length) : string(standalone ? { month: length } : {
			month: length,
			day: "numeric"
		}, "month"), weekday = (length, standalone) => knownEnglish ? weekdayForDateTime(dt, length) : string(standalone ? { weekday: length } : {
			weekday: length,
			month: "long",
			day: "numeric"
		}, "weekday"), maybeMacro = (token) => {
			const formatOpts = Formatter.macroTokenToFormatOpts(token);
			if (formatOpts) return this.formatWithSystemDefault(dt, formatOpts);
			else return token;
		}, era = (length) => knownEnglish ? eraForDateTime(dt, length) : string({ era: length }, "era"), tokenToString = (token) => {
			switch (token) {
				case "S": return this.num(dt.millisecond);
				case "u":
				case "SSS": return this.num(dt.millisecond, 3);
				case "s": return this.num(dt.second);
				case "ss": return this.num(dt.second, 2);
				case "uu": return this.num(Math.floor(dt.millisecond / 10), 2);
				case "uuu": return this.num(Math.floor(dt.millisecond / 100));
				case "m": return this.num(dt.minute);
				case "mm": return this.num(dt.minute, 2);
				case "h": return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12);
				case "hh": return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12, 2);
				case "H": return this.num(dt.hour);
				case "HH": return this.num(dt.hour, 2);
				case "Z": return formatOffset({
					format: "narrow",
					allowZ: this.opts.allowZ
				});
				case "ZZ": return formatOffset({
					format: "short",
					allowZ: this.opts.allowZ
				});
				case "ZZZ": return formatOffset({
					format: "techie",
					allowZ: this.opts.allowZ
				});
				case "ZZZZ": return dt.zone.offsetName(dt.ts, {
					format: "short",
					locale: this.loc.locale
				});
				case "ZZZZZ": return dt.zone.offsetName(dt.ts, {
					format: "long",
					locale: this.loc.locale
				});
				case "z": return dt.zoneName;
				case "a": return meridiem();
				case "d": return useDateTimeFormatter ? string({ day: "numeric" }, "day") : this.num(dt.day);
				case "dd": return useDateTimeFormatter ? string({ day: "2-digit" }, "day") : this.num(dt.day, 2);
				case "c": return this.num(dt.weekday);
				case "ccc": return weekday("short", true);
				case "cccc": return weekday("long", true);
				case "ccccc": return weekday("narrow", true);
				case "E": return this.num(dt.weekday);
				case "EEE": return weekday("short", false);
				case "EEEE": return weekday("long", false);
				case "EEEEE": return weekday("narrow", false);
				case "L": return useDateTimeFormatter ? string({
					month: "numeric",
					day: "numeric"
				}, "month") : this.num(dt.month);
				case "LL": return useDateTimeFormatter ? string({
					month: "2-digit",
					day: "numeric"
				}, "month") : this.num(dt.month, 2);
				case "LLL": return month("short", true);
				case "LLLL": return month("long", true);
				case "LLLLL": return month("narrow", true);
				case "M": return useDateTimeFormatter ? string({ month: "numeric" }, "month") : this.num(dt.month);
				case "MM": return useDateTimeFormatter ? string({ month: "2-digit" }, "month") : this.num(dt.month, 2);
				case "MMM": return month("short", false);
				case "MMMM": return month("long", false);
				case "MMMMM": return month("narrow", false);
				case "y": return useDateTimeFormatter ? string({ year: "numeric" }, "year") : this.num(dt.year);
				case "yy": return useDateTimeFormatter ? string({ year: "2-digit" }, "year") : this.num(dt.year.toString().slice(-2), 2);
				case "yyyy": return useDateTimeFormatter ? string({ year: "numeric" }, "year") : this.num(dt.year, 4);
				case "yyyyyy": return useDateTimeFormatter ? string({ year: "numeric" }, "year") : this.num(dt.year, 6);
				case "G": return era("short");
				case "GG": return era("long");
				case "GGGGG": return era("narrow");
				case "kk": return this.num(dt.weekYear.toString().slice(-2), 2);
				case "kkkk": return this.num(dt.weekYear, 4);
				case "W": return this.num(dt.weekNumber);
				case "WW": return this.num(dt.weekNumber, 2);
				case "n": return this.num(dt.localWeekNumber);
				case "nn": return this.num(dt.localWeekNumber, 2);
				case "ii": return this.num(dt.localWeekYear.toString().slice(-2), 2);
				case "iiii": return this.num(dt.localWeekYear, 4);
				case "o": return this.num(dt.ordinal);
				case "ooo": return this.num(dt.ordinal, 3);
				case "q": return this.num(dt.quarter);
				case "qq": return this.num(dt.quarter, 2);
				case "X": return this.num(Math.floor(dt.ts / 1e3));
				case "x": return this.num(dt.ts);
				default: return maybeMacro(token);
			}
		};
		return stringifyTokens(Formatter.parseFormat(fmt), tokenToString);
	}
	formatDurationFromString(dur, fmt) {
		const tokenToField = (token) => {
			switch (token[0]) {
				case "S": return "millisecond";
				case "s": return "second";
				case "m": return "minute";
				case "h": return "hour";
				case "d": return "day";
				case "w": return "week";
				case "M": return "month";
				case "y": return "year";
				default: return null;
			}
		}, tokenToString = (lildur) => (token) => {
			const mapped = tokenToField(token);
			if (mapped) return this.num(lildur.get(mapped), token.length);
			else return token;
		}, tokens = Formatter.parseFormat(fmt), realTokens = tokens.reduce((found, { literal, val }) => literal ? found : found.concat(val), []);
		return stringifyTokens(tokens, tokenToString(dur.shiftTo(...realTokens.map(tokenToField).filter((t) => t))));
	}
};

//#endregion
export { Formatter as default };
//# sourceMappingURL=formatter.mjs.map