import { CanonicalizeLocaleList, FormatNumeric, FormatNumericRange, FormatNumericRangeToParts, FormatNumericToParts, InitializeNumberFormat, OrdinaryHasInstance, SupportedLocales, ToIntlMathematicalValue, createMemoizedPluralRules, defineProperty, invariant } from "@formatjs/ecma402-abstract";
import { currencyDigitsData } from "./currency-digits.generated.js";
import { numberingSystemNames } from "./numbering-systems.generated.js";
import getInternalSlots from "./get_internal_slots.js";
import "./types.js";
const RESOLVED_OPTIONS_KEYS = [
	"locale",
	"numberingSystem",
	"style",
	"currency",
	"currencyDisplay",
	"currencySign",
	"unit",
	"unitDisplay",
	"minimumIntegerDigits",
	"minimumFractionDigits",
	"maximumFractionDigits",
	"minimumSignificantDigits",
	"maximumSignificantDigits",
	"useGrouping",
	"notation",
	"compactDisplay",
	"signDisplay"
];
/**
* https://tc39.es/ecma402/#sec-intl-numberformat-constructor
*/
export const NumberFormat = function(locales, options) {
	// Cannot use `new.target` bc of IE11 & TS transpiles it to something else
	if (!this || !OrdinaryHasInstance(NumberFormat, this)) {
		return new NumberFormat(locales, options);
	}
	InitializeNumberFormat(this, locales, options, {
		getInternalSlots,
		localeData: NumberFormat.localeData,
		availableLocales: NumberFormat.availableLocales,
		getDefaultLocale: NumberFormat.getDefaultLocale,
		currencyDigitsData,
		numberingSystemNames
	});
	const internalSlots = getInternalSlots(this);
	const dataLocale = internalSlots.dataLocale;
	const dataLocaleData = NumberFormat.localeData[dataLocale];
	invariant(dataLocaleData !== undefined, `Cannot load locale-dependent data for ${dataLocale}.`);
	internalSlots.pl = createMemoizedPluralRules(dataLocale, {
		minimumFractionDigits: internalSlots.minimumFractionDigits,
		maximumFractionDigits: internalSlots.maximumFractionDigits,
		minimumIntegerDigits: internalSlots.minimumIntegerDigits,
		minimumSignificantDigits: internalSlots.minimumSignificantDigits,
		maximumSignificantDigits: internalSlots.maximumSignificantDigits
	});
	return this;
};
function formatToParts(x) {
	return FormatNumericToParts(this, ToIntlMathematicalValue(x), { getInternalSlots });
}
function formatRange(start, end) {
	return FormatNumericRange(this, ToIntlMathematicalValue(start), ToIntlMathematicalValue(end), { getInternalSlots });
}
function formatRangeToParts(start, end) {
	return FormatNumericRangeToParts(this, ToIntlMathematicalValue(start), ToIntlMathematicalValue(end), { getInternalSlots });
}
try {
	Object.defineProperty(formatToParts, "name", {
		value: "formatToParts",
		enumerable: false,
		writable: false,
		configurable: true
	});
} catch {}
defineProperty(NumberFormat.prototype, "formatToParts", { value: formatToParts });
defineProperty(NumberFormat.prototype, "formatRange", { value: formatRange });
defineProperty(NumberFormat.prototype, "formatRangeToParts", { value: formatRangeToParts });
defineProperty(NumberFormat.prototype, "resolvedOptions", { value: function resolvedOptions() {
	if (typeof this !== "object" || !OrdinaryHasInstance(NumberFormat, this)) {
		throw TypeError("Method Intl.NumberFormat.prototype.resolvedOptions called on incompatible receiver");
	}
	const internalSlots = getInternalSlots(this);
	const ro = {};
	for (const key of RESOLVED_OPTIONS_KEYS) {
		const value = internalSlots[key];
		if (value !== undefined) {
			ro[key] = value;
		}
	}
	if (internalSlots.roundingType === "morePrecision") {
		ro.roundingPriority = "morePrecision";
	} else if (internalSlots.roundingType === "lessPrecision") {
		ro.roundingPriority = "lessPrecision";
	} else {
		ro.roundingPriority = "auto";
	}
	return ro;
} });
const formatDescriptor = {
	enumerable: false,
	configurable: true,
	get() {
		if (typeof this !== "object" || !OrdinaryHasInstance(NumberFormat, this)) {
			throw TypeError("Intl.NumberFormat format property accessor called on incompatible receiver");
		}
		const internalSlots = getInternalSlots(this);
		let boundFormat = internalSlots.boundFormat;
		if (boundFormat === undefined) {
			// https://tc39.es/proposal-unified-intl-numberformat/section11/numberformat_diff_out.html#sec-number-format-functions
			boundFormat = (value) => FormatNumeric(internalSlots, ToIntlMathematicalValue(value));
			try {
				// https://github.com/tc39/test262/blob/master/test/intl402/NumberFormat/prototype/format/format-function-name.js
				Object.defineProperty(boundFormat, "name", {
					configurable: true,
					enumerable: false,
					writable: false,
					value: ""
				});
			} catch {}
			internalSlots.boundFormat = boundFormat;
		}
		return boundFormat;
	}
};
try {
	// https://github.com/tc39/test262/blob/master/test/intl402/NumberFormat/prototype/format/name.js
	Object.defineProperty(formatDescriptor.get, "name", {
		configurable: true,
		enumerable: false,
		writable: false,
		value: "get format"
	});
} catch {}
Object.defineProperty(NumberFormat.prototype, "format", formatDescriptor);
// Static properties
defineProperty(NumberFormat, "supportedLocalesOf", { value: function supportedLocalesOf(locales, options) {
	return SupportedLocales(NumberFormat.availableLocales, CanonicalizeLocaleList(locales), options);
} });
NumberFormat.__addLocaleData = function __addLocaleData(...data) {
	for (const { data: d, locale } of data) {
		const minimizedLocale = new Intl.Locale(locale).minimize().toString();
		NumberFormat.localeData[locale] = NumberFormat.localeData[minimizedLocale] = d;
		NumberFormat.availableLocales.add(minimizedLocale);
		NumberFormat.availableLocales.add(locale);
		if (!NumberFormat.__defaultLocale) {
			NumberFormat.__defaultLocale = minimizedLocale;
		}
	}
};
NumberFormat.__addUnitData = function __addUnitData(locale, unitsData) {
	const { [locale]: existingData } = NumberFormat.localeData;
	if (!existingData) {
		throw new Error(`Locale data for "${locale}" has not been loaded in NumberFormat. 
Please __addLocaleData before adding additional unit data`);
	}
	for (const unit in unitsData.simple) {
		existingData.units.simple[unit] = unitsData.simple[unit];
	}
	for (const unit in unitsData.compound) {
		existingData.units.compound[unit] = unitsData.compound[unit];
	}
};
NumberFormat.__defaultLocale = "";
NumberFormat.localeData = {};
NumberFormat.availableLocales = new Set();
NumberFormat.getDefaultLocale = () => {
	return NumberFormat.__defaultLocale;
};
NumberFormat.polyfilled = true;
try {
	// IE11 does not have Symbol
	if (typeof Symbol !== "undefined") {
		Object.defineProperty(NumberFormat.prototype, Symbol.toStringTag, {
			configurable: true,
			enumerable: false,
			writable: false,
			value: "Intl.NumberFormat"
		});
	}
	// https://github.com/tc39/test262/blob/master/test/intl402/NumberFormat/length.js
	Object.defineProperty(NumberFormat.prototype.constructor, "length", {
		configurable: true,
		enumerable: false,
		writable: false,
		value: 0
	});
	// https://github.com/tc39/test262/blob/master/test/intl402/NumberFormat/supportedLocalesOf/length.js
	Object.defineProperty(NumberFormat.supportedLocalesOf, "length", {
		configurable: true,
		enumerable: false,
		writable: false,
		value: 1
	});
	Object.defineProperty(NumberFormat, "prototype", {
		configurable: false,
		enumerable: false,
		writable: false,
		value: NumberFormat.prototype
	});
} catch {}
