import type { Decimal } from "@formatjs/bigdecimal";
import { type LocaleData } from "./core.js";
import { type LDMLPluralRule } from "./plural-rules.js";
export type NumberFormatNotation = "standard" | "scientific" | "engineering" | "compact";
export type RoundingPriorityType = "auto" | "morePrecision" | "lessPrecision";
export type NumberFormatRoundingType = "morePrecision" | "lessPrecision" | "significantDigits" | "fractionDigits";
export type RoundingModeType = "ceil" | "floor" | "expand" | "trunc" | "halfCeil" | "halfFloor" | "halfExpand" | "halfTrunc" | "halfEven";
export type UnsignedRoundingModeType = "infinity" | "zero" | "half-infinity" | "half-zero" | "half-even";
export type UseGroupingType = "min2" | "auto" | "always" | boolean;
export interface NumberFormatDigitOptions {
	minimumIntegerDigits?: number;
	minimumSignificantDigits?: number;
	maximumSignificantDigits?: number;
	minimumFractionDigits?: number;
	maximumFractionDigits?: number;
	roundingPriority?: RoundingPriorityType;
	roundingIncrement?: number;
	roundingMode?: RoundingModeType;
	trailingZeroDisplay?: TrailingZeroDisplay;
}
export interface NumberFormatDigitInternalSlots {
	minimumIntegerDigits: number;
	minimumSignificantDigits: number;
	maximumSignificantDigits: number;
	roundingType: NumberFormatRoundingType;
	minimumFractionDigits: number;
	maximumFractionDigits: number;
	notation: NumberFormatNotation;
	roundingIncrement: number;
	roundingMode: RoundingModeType;
	trailingZeroDisplay: TrailingZeroDisplay;
	roundingPriority: RoundingPriorityType;
}
export type RawNumberLocaleData = LocaleData<NumberFormatLocaleInternalData>;
export interface NumberFormatLocaleInternalData {
	units: UnitDataTable;
	currencies: Record<string, CurrencyData>;
	numbers: RawNumberData;
	nu: string[];
}
export interface UnitDataTable {
	simple: Record<string, UnitData>;
	compound: Record<string, CompoundUnitData>;
}
export interface UnitData {
	long: LDMLPluralRuleMap<string>;
	short: LDMLPluralRuleMap<string>;
	narrow: LDMLPluralRuleMap<string>;
	perUnit: Record<"narrow" | "short" | "long", string | undefined>;
}
export interface CompoundUnitData {
	long: string;
	short: string;
	narrow: string;
}
export interface CurrencyData {
	displayName: LDMLPluralRuleMap<string>;
	symbol: string;
	narrow: string;
}
export type DecimalFormatNum = "1000" | "10000" | "100000" | "1000000" | "10000000" | "100000000" | "1000000000" | "10000000000" | "100000000000" | "1000000000000" | "10000000000000" | "100000000000000";
export type NumberingSystem = string;
/**
* We only care about insertBetween bc we assume
* `currencyMatch` & `surroundingMatch` are all the same
*
* @export
* @interface CurrencySpacingData
*/
export interface CurrencySpacingData {
	beforeInsertBetween: string;
	afterInsertBetween: string;
}
export interface RawCurrencyData {
	currencySpacing: CurrencySpacingData;
	standard: string;
	accounting: string;
	short?: Record<DecimalFormatNum, LDMLPluralRuleMap<string>>;
	unitPattern: string;
}
export interface SymbolsData {
	decimal: string;
	group: string;
	list: string;
	percentSign: string;
	plusSign: string;
	minusSign: string;
	exponential: string;
	superscriptingExponent: string;
	perMille: string;
	infinity: string;
	nan: string;
	timeSeparator: string;
	approximatelySign: string;
	rangeSign: string;
	currencyGroup?: string;
	currencyDecimal?: string;
}
export interface RawNumberData {
	nu: string[];
	symbols: Record<NumberingSystem, SymbolsData>;
	decimal: Record<NumberingSystem, {
		standard: string;
		long: Record<DecimalFormatNum, LDMLPluralRuleMap<string>>;
		short: Record<DecimalFormatNum, LDMLPluralRuleMap<string>>;
	}>;
	percent: Record<NumberingSystem, string>;
	currency: Record<NumberingSystem, RawCurrencyData>;
}
export type LDMLPluralRuleMap<T> = Omit<Partial<Record<LDMLPluralRule, T>>, "other"> & {
	other: T;
};
export interface RawNumberFormatResult {
	formattedString: string;
	roundedNumber: Decimal;
	integerDigitsCount: number;
	roundingMagnitude: number;
}
export type NumberFormatOptionsLocaleMatcher = "lookup" | "best fit";
export type NumberFormatOptionsStyle = "decimal" | "percent" | "currency" | "unit";
export type NumberFormatOptionsCompactDisplay = "short" | "long";
export type NumberFormatOptionsCurrencyDisplay = "symbol" | "code" | "name" | "narrowSymbol";
export type NumberFormatOptionsCurrencySign = "standard" | "accounting";
export type NumberFormatOptionsNotation = NumberFormatNotation;
export type NumberFormatOptionsSignDisplay = "auto" | "always" | "never" | "exceptZero" | "negative";
export type NumberFormatOptionsUnitDisplay = "long" | "short" | "narrow";
export type TrailingZeroDisplay = "auto" | "stripIfInteger";
export interface NumberFormatInternal extends NumberFormatDigitInternalSlots {
	locale: string;
	dataLocale: string;
	style: NumberFormatOptionsStyle;
	currency?: string;
	currencyDisplay: NumberFormatOptionsCurrencyDisplay;
	unit?: string;
	unitDisplay: NumberFormatOptionsUnitDisplay;
	currencySign: NumberFormatOptionsCurrencySign;
	notation: NumberFormatOptionsNotation;
	compactDisplay: NumberFormatOptionsCompactDisplay;
	signDisplay: NumberFormatOptionsSignDisplay;
	useGrouping?: UseGroupingType;
	pl: Intl.PluralRules;
	boundFormat?: Intl.NumberFormat["format"];
	numberingSystem: string;
	dataLocaleData: NumberFormatLocaleInternalData;
	roundingMode: RoundingModeType;
}
export type NumberFormatOptions = Omit<Intl.NumberFormatOptions, "signDisplay" | "useGrouping"> & NumberFormatDigitOptions & {
	localeMatcher?: NumberFormatOptionsLocaleMatcher;
	style?: NumberFormatOptionsStyle;
	compactDisplay?: NumberFormatOptionsCompactDisplay;
	currencyDisplay?: NumberFormatOptionsCurrencyDisplay;
	currencySign?: NumberFormatOptionsCurrencySign;
	notation?: NumberFormatOptionsNotation;
	signDisplay?: NumberFormatOptionsSignDisplay;
	unit?: string;
	unitDisplay?: NumberFormatOptionsUnitDisplay;
	numberingSystem?: string;
	trailingZeroDisplay?: TrailingZeroDisplay;
	roundingPriority?: RoundingPriorityType;
	roundingIncrement?: number;
	roundingMode?: RoundingModeType;
	useGrouping?: UseGroupingType;
};
export type ResolvedNumberFormatOptions = Intl.ResolvedNumberFormatOptions & Pick<NumberFormatInternal, "currencySign" | "unit" | "unitDisplay" | "notation" | "compactDisplay" | "signDisplay">;
export type NumberFormatPartTypes = Intl.NumberFormatPartTypes | "exponentSeparator" | "exponentMinusSign" | "exponentInteger" | "compact" | "unit" | "literal" | "approximatelySign";
export interface NumberFormatPart {
	type: NumberFormatPartTypes;
	value: string;
	source?: string;
}
export interface NumberRangeToParts extends NumberFormatPart {
	result: string;
}
