// |reftest| skip-if(!this.hasOwnProperty("Intl"))
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/

//-----------------------------------------------------------------------------
var BUGNUMBER = 1289882;
var summary = "Implement Intl.NumberFormat.prototype.formatToParts";

print(BUGNUMBER + ": " + summary);

//-----------------------------------------------------------------------------

assertEq("formatToParts" in Intl.NumberFormat(), true);

// NOTE: Some of these tests exercise standard behavior (e.g. that format and
//       formatToParts expose the same formatted string).  But much of this,
//       like the exact-formatted-string expectations, is technically
//       implementation-dependent.  This is necessary as a practical matter to
//       properly test the conversion from ICU's nested-field exposure to
//       ECMA-402's sequential-parts exposure.

var {
  Nan, Inf, Integer, Group, Decimal, Fraction,
  MinusSign, PlusSign, PercentSign, Currency, Literal,
} = NumberFormatParts;

//-----------------------------------------------------------------------------

// Test -0's partitioning now that it's not treated like +0.
// https://github.com/tc39/ecma402/pull/232

var deadSimpleFormatter = new Intl.NumberFormat("en-US");

assertParts(deadSimpleFormatter, -0,
            [MinusSign("-"), Integer("0")]);

// Test behavior of a currency with code formatting.
var usdCodeOptions =
  {
    style: "currency",
    currency: "USD",
    currencyDisplay: "code",
    minimumFractionDigits: 0,
    maximumFractionDigits: 0,
  };
var usDollarsCode = new Intl.NumberFormat("en-US", usdCodeOptions);

assertParts(usDollarsCode, 25,
            [Currency("USD"), Literal("\xA0"), Integer("25")]);

// ISO 4217 currency codes are formed from an ISO 3166-1 alpha-2 country code
// followed by a third letter.  ISO 3166 guarantees that no country code
// starting with "X" will ever be assigned.  Stepping carefully around a few
// 4217-designated special "currencies", XQQ will never have a representation.
// Thus, yes: this really is specified to work, as unrecognized or unsupported
// codes pass into the string unmodified.
var xqqCodeOptions =
  {
    style: "currency",
    currency: "XQQ",
    currencyDisplay: "code",
    minimumFractionDigits: 0,
    maximumFractionDigits: 0,
  };
var xqqMoneyCode = new Intl.NumberFormat("en-US", xqqCodeOptions);

assertParts(xqqMoneyCode, 25,
            [Currency("XQQ"), Literal("\xA0"), Integer("25")]);

// Test currencyDisplay: "name".
var usdNameOptions =
  {
    style: "currency",
    currency: "USD",
    currencyDisplay: "name",
    minimumFractionDigits: 0,
    maximumFractionDigits: 0,
  };
var usDollarsName = new Intl.NumberFormat("en-US", usdNameOptions);

assertParts(usDollarsName, 25,
            [Integer("25"), Literal(" "), Currency("US dollars")]);

var usdNameGroupingOptions =
  {
    style: "currency",
    currency: "USD",
    currencyDisplay: "name",
    minimumFractionDigits: 0,
    maximumFractionDigits: 0,
  };
var usDollarsNameGrouping =
  new Intl.NumberFormat("en-US", usdNameGroupingOptions);

assertParts(usDollarsNameGrouping, 12345678,
            [Integer("12"),
             Group(","),
             Integer("345"),
             Group(","),
             Integer("678"),
             Literal(" "),
             Currency("US dollars")]);

// But if the implementation doesn't recognize the currency, the provided code
// is used in place of a proper name, unmolested.
var xqqNameOptions =
  {
    style: "currency",
    currency: "XQQ",
    currencyDisplay: "name",
    minimumFractionDigits: 0,
    maximumFractionDigits: 0,
  };
var xqqMoneyName = new Intl.NumberFormat("en-US", xqqNameOptions);

assertParts(xqqMoneyName, 25,
            [Integer("25"), Literal(" "), Currency("XQQ")]);

// Test some currencies with fractional components.

var usdNameFractionOptions =
  {
    style: "currency",
    currency: "USD",
    currencyDisplay: "name",
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  };
var usdNameFractionFormatter =
  new Intl.NumberFormat("en-US", usdNameFractionOptions);

// The US national surplus (i.e. debt) as of October 18, 2016.  (Replicating
// data from a comment in builtin/Intl/NumberFormat.cpp.)
var usNationalSurplus = -19766580028249.41;

assertParts(usdNameFractionFormatter, usNationalSurplus,
            [MinusSign("-"),
             Integer("19"),
             Group(","),
             Integer("766"),
             Group(","),
             Integer("580"),
             Group(","),
             Integer("028"),
             Group(","),
             Integer("249"),
             Decimal("."),
             Fraction("41"),
             Literal(" "),
             Currency("US dollars")]);

// Percents in various forms.

var usPercentOptions =
  {
    style: "percent",
    minimumFractionDigits: 1,
    maximumFractionDigits: 1,
  };
var usPercentFormatter =
  new Intl.NumberFormat("en-US", usPercentOptions);

assertParts(usPercentFormatter, 0.375,
            [Integer("37"), Decimal("."), Fraction("5"), PercentSign("%")]);

assertParts(usPercentFormatter, -1284.375,
            [MinusSign("-"),
             Integer("128"),
             Group(","),
             Integer("437"),
             Decimal("."),
             Fraction("5"),
             PercentSign("%")]);

assertParts(usPercentFormatter, NaN,
            [Nan("NaN"), PercentSign("%")]);

assertParts(usPercentFormatter, Infinity,
            [Inf("∞"), PercentSign("%")]);

assertParts(usPercentFormatter, -Infinity,
            [MinusSign("-"), Inf("∞"), PercentSign("%")]);

var dePercentOptions =
  {
    style: "percent",
    minimumFractionDigits: 1,
    maximumFractionDigits: 1,
  };
var dePercentFormatter =
  new Intl.NumberFormat("de", dePercentOptions);

assertParts(dePercentFormatter, 0.375,
            [Integer("37"), Decimal(","), Fraction("5"), Literal("\xA0"), PercentSign("%")]);

assertParts(dePercentFormatter, -1284.375,
            [MinusSign("-"),
             Integer("128"),
             Group("."),
             Integer("437"),
             Decimal(","),
             Fraction("5"),
             Literal("\xA0"),
             PercentSign("%")]);

assertParts(dePercentFormatter, NaN,
            [Nan("NaN"), Literal("\xA0"), PercentSign("%")]);

assertParts(dePercentFormatter, Infinity,
            [Inf("∞"), Literal("\xA0"), PercentSign("%")]);

assertParts(dePercentFormatter, -Infinity,
            [MinusSign("-"), Inf("∞"), Literal("\xA0"), PercentSign("%")]);

var arPercentOptions =
  {
    style: "percent",
    minimumFractionDigits: 2,
  };
var arPercentFormatter =
  new Intl.NumberFormat("ar-IQ", arPercentOptions);

assertParts(arPercentFormatter, -135.32,
            [Literal("\u{061C}"),
             MinusSign("-"),
             Integer("١٣"),
             Group("٬"),
             Integer("٥٣٢"),
             Decimal("٫"),
             Fraction("٠٠"),
             PercentSign("٪"),
             Literal("\u{061C}")]);

// Decimals.

var usDecimalOptions =
  {
    style: "decimal",
    maximumFractionDigits: 7 // minimum defaults to 0
  };
var usDecimalFormatter =
  new Intl.NumberFormat("en-US", usDecimalOptions);

assertParts(usDecimalFormatter, 42,
            [Integer("42")]);

assertParts(usDecimalFormatter, 1337,
            [Integer("1"), Group(","), Integer("337")]);

assertParts(usDecimalFormatter, -6.25,
            [MinusSign("-"), Integer("6"), Decimal("."), Fraction("25")]);

assertParts(usDecimalFormatter, -1376.25,
            [MinusSign("-"),
             Integer("1"),
             Group(","),
             Integer("376"),
             Decimal("."),
             Fraction("25")]);

assertParts(usDecimalFormatter, 124816.8359375,
            [Integer("124"),
             Group(","),
             Integer("816"),
             Decimal("."),
             Fraction("8359375")]);

var usNoGroupingDecimalOptions =
  {
    style: "decimal",
    useGrouping: false,
    maximumFractionDigits: 7 // minimum defaults to 0
  };
var usNoGroupingDecimalFormatter =
  new Intl.NumberFormat("en-US", usNoGroupingDecimalOptions);

assertParts(usNoGroupingDecimalFormatter, 1337,
            [Integer("1337")]);

assertParts(usNoGroupingDecimalFormatter, -6.25,
            [MinusSign("-"), Integer("6"), Decimal("."), Fraction("25")]);

assertParts(usNoGroupingDecimalFormatter, -1376.25,
            [MinusSign("-"),
             Integer("1376"),
             Decimal("."),
             Fraction("25")]);

assertParts(usNoGroupingDecimalFormatter, 124816.8359375,
            [Integer("124816"),
             Decimal("."),
             Fraction("8359375")]);

var deDecimalOptions =
  {
    style: "decimal",
    maximumFractionDigits: 7 // minimum defaults to 0
  };
var deDecimalFormatter =
  new Intl.NumberFormat("de-DE", deDecimalOptions);

assertParts(deDecimalFormatter, 42,
            [Integer("42")]);

assertParts(deDecimalFormatter, 1337,
            [Integer("1"), Group("."), Integer("337")]);

assertParts(deDecimalFormatter, -6.25,
            [MinusSign("-"), Integer("6"), Decimal(","), Fraction("25")]);

assertParts(deDecimalFormatter, -1376.25,
            [MinusSign("-"),
             Integer("1"),
             Group("."),
             Integer("376"),
             Decimal(","),
             Fraction("25")]);

assertParts(deDecimalFormatter, 124816.8359375,
            [Integer("124"),
             Group("."),
             Integer("816"),
             Decimal(","),
             Fraction("8359375")]);

var deNoGroupingDecimalOptions =
  {
    style: "decimal",
    useGrouping: false,
    maximumFractionDigits: 7 // minimum defaults to 0
  };
var deNoGroupingDecimalFormatter =
  new Intl.NumberFormat("de-DE", deNoGroupingDecimalOptions);

assertParts(deNoGroupingDecimalFormatter, 1337,
            [Integer("1337")]);

assertParts(deNoGroupingDecimalFormatter, -6.25,
            [MinusSign("-"), Integer("6"), Decimal(","), Fraction("25")]);

assertParts(deNoGroupingDecimalFormatter, -1376.25,
            [MinusSign("-"),
             Integer("1376"),
             Decimal(","),
             Fraction("25")]);

assertParts(deNoGroupingDecimalFormatter, 124816.8359375,
            [Integer("124816"),
             Decimal(","),
             Fraction("8359375")]);

//-----------------------------------------------------------------------------

if (typeof reportCompare === "function")
    reportCompare(0, 0, 'ok');

print("Tests complete");
