const require_zone = require('../zone.js');
const require_util = require('../impl/util.js');

//#region ../../node_modules/.pnpm/luxon@3.5.0/node_modules/luxon/src/zones/IANAZone.js
let dtfCache = {};
function makeDTF(zone) {
	if (!dtfCache[zone]) dtfCache[zone] = new Intl.DateTimeFormat("en-US", {
		hour12: false,
		timeZone: zone,
		year: "numeric",
		month: "2-digit",
		day: "2-digit",
		hour: "2-digit",
		minute: "2-digit",
		second: "2-digit",
		era: "short"
	});
	return dtfCache[zone];
}
const typeToPos = {
	year: 0,
	month: 1,
	day: 2,
	era: 3,
	hour: 4,
	minute: 5,
	second: 6
};
function hackyOffset(dtf, date) {
	const formatted = dtf.format(date).replace(/\u200E/g, ""), [, fMonth, fDay, fYear, fadOrBc, fHour, fMinute, fSecond] = /(\d+)\/(\d+)\/(\d+) (AD|BC),? (\d+):(\d+):(\d+)/.exec(formatted);
	return [
		fYear,
		fMonth,
		fDay,
		fadOrBc,
		fHour,
		fMinute,
		fSecond
	];
}
function partsOffset(dtf, date) {
	const formatted = dtf.formatToParts(date);
	const filled = [];
	for (let i = 0; i < formatted.length; i++) {
		const { type, value } = formatted[i];
		const pos = typeToPos[type];
		if (type === "era") filled[pos] = value;
		else if (!require_util.isUndefined(pos)) filled[pos] = parseInt(value, 10);
	}
	return filled;
}
let ianaZoneCache = {};
/**
* A zone identified by an IANA identifier, like America/New_York
* @implements {Zone}
*/
var IANAZone = class IANAZone extends require_zone.default {
	/**
	* @param {string} name - Zone name
	* @return {IANAZone}
	*/
	static create(name) {
		if (!ianaZoneCache[name]) ianaZoneCache[name] = new IANAZone(name);
		return ianaZoneCache[name];
	}
	/**
	* Reset local caches. Should only be necessary in testing scenarios.
	* @return {void}
	*/
	static resetCache() {
		ianaZoneCache = {};
		dtfCache = {};
	}
	/**
	* Returns whether the provided string is a valid specifier. This only checks the string's format, not that the specifier identifies a known zone; see isValidZone for that.
	* @param {string} s - The string to check validity on
	* @example IANAZone.isValidSpecifier("America/New_York") //=> true
	* @example IANAZone.isValidSpecifier("Sport~~blorp") //=> false
	* @deprecated For backward compatibility, this forwards to isValidZone, better use `isValidZone()` directly instead.
	* @return {boolean}
	*/
	static isValidSpecifier(s) {
		return this.isValidZone(s);
	}
	/**
	* Returns whether the provided string identifies a real zone
	* @param {string} zone - The string to check
	* @example IANAZone.isValidZone("America/New_York") //=> true
	* @example IANAZone.isValidZone("Fantasia/Castle") //=> false
	* @example IANAZone.isValidZone("Sport~~blorp") //=> false
	* @return {boolean}
	*/
	static isValidZone(zone) {
		if (!zone) return false;
		try {
			new Intl.DateTimeFormat("en-US", { timeZone: zone }).format();
			return true;
		} catch (e) {
			return false;
		}
	}
	constructor(name) {
		super();
		/** @private **/
		this.zoneName = name;
		/** @private **/
		this.valid = IANAZone.isValidZone(name);
	}
	/**
	* The type of zone. `iana` for all instances of `IANAZone`.
	* @override
	* @type {string}
	*/
	get type() {
		return "iana";
	}
	/**
	* The name of this zone (i.e. the IANA zone name).
	* @override
	* @type {string}
	*/
	get name() {
		return this.zoneName;
	}
	/**
	* Returns whether the offset is known to be fixed for the whole year:
	* Always returns false for all IANA zones.
	* @override
	* @type {boolean}
	*/
	get isUniversal() {
		return false;
	}
	/**
	* Returns the offset's common name (such as EST) at the specified timestamp
	* @override
	* @param {number} ts - Epoch milliseconds for which to get the name
	* @param {Object} opts - Options to affect the format
	* @param {string} opts.format - What style of offset to return. Accepts 'long' or 'short'.
	* @param {string} opts.locale - What locale to return the offset name in.
	* @return {string}
	*/
	offsetName(ts, { format, locale }) {
		return require_util.parseZoneInfo(ts, format, locale, this.name);
	}
	/**
	* Returns the offset's value as a string
	* @override
	* @param {number} ts - Epoch milliseconds for which to get the offset
	* @param {string} format - What style of offset to return.
	*                          Accepts 'narrow', 'short', or 'techie'. Returning '+6', '+06:00', or '+0600' respectively
	* @return {string}
	*/
	formatOffset(ts, format) {
		return require_util.formatOffset(this.offset(ts), format);
	}
	/**
	* Return the offset in minutes for this zone at the specified timestamp.
	* @override
	* @param {number} ts - Epoch milliseconds for which to compute the offset
	* @return {number}
	*/
	offset(ts) {
		const date = new Date(ts);
		if (isNaN(date)) return NaN;
		const dtf = makeDTF(this.name);
		let [year, month, day, adOrBc, hour, minute, second] = dtf.formatToParts ? partsOffset(dtf, date) : hackyOffset(dtf, date);
		if (adOrBc === "BC") year = -Math.abs(year) + 1;
		const asUTC = require_util.objToLocalTS({
			year,
			month,
			day,
			hour: hour === 24 ? 0 : hour,
			minute,
			second,
			millisecond: 0
		});
		let asTS = +date;
		const over = asTS % 1e3;
		asTS -= over >= 0 ? over : 1e3 + over;
		return (asUTC - asTS) / (60 * 1e3);
	}
	/**
	* Return whether this Zone is equal to another zone
	* @override
	* @param {Zone} otherZone - the zone to compare
	* @return {boolean}
	*/
	equals(otherZone) {
		return otherZone.type === "iana" && otherZone.name === this.name;
	}
	/**
	* Return whether this Zone is valid.
	* @override
	* @type {boolean}
	*/
	get isValid() {
		return this.valid;
	}
};

//#endregion
exports.default = IANAZone;