/*
 * Copyright (C) 2015 Andy VanWagoner (thetalecrafter@gmail.com)
 * Copyright (C) 2015 Sukolsak Sakshuwong (sukolsak@gmail.com)
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "IntlObject.h"

#if ENABLE(INTL)

#include "Error.h"
#include "FunctionPrototype.h"
#include "IntlCollator.h"
#include "IntlCollatorConstructor.h"
#include "IntlCollatorPrototype.h"
#include "IntlDateTimeFormat.h"
#include "IntlDateTimeFormatConstructor.h"
#include "IntlDateTimeFormatPrototype.h"
#include "IntlNumberFormat.h"
#include "IntlNumberFormatConstructor.h"
#include "IntlNumberFormatPrototype.h"
#include "JSCInlines.h"
#include "JSCJSValueInlines.h"
#include "Lookup.h"
#include "ObjectPrototype.h"
#include <unicode/uloc.h>
#include <wtf/Assertions.h>

namespace JSC {

STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(IntlObject);

}

namespace JSC {

struct MatcherResult {
    String locale;
    String extension;
    size_t extensionIndex;
};

const ClassInfo IntlObject::s_info = { "Object", &Base::s_info, 0, CREATE_METHOD_TABLE(IntlObject) };

IntlObject::IntlObject(VM& vm, Structure* structure)
    : JSNonFinalObject(vm, structure)
{
}

IntlObject* IntlObject::create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
{
    IntlObject* object = new (NotNull, allocateCell<IntlObject>(vm.heap)) IntlObject(vm, structure);
    object->finishCreation(vm, globalObject);
    return object;
}

void IntlObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
{
    Base::finishCreation(vm);
    ASSERT(inherits(info()));

    // Set up Collator.
    IntlCollatorPrototype* collatorPrototype = IntlCollatorPrototype::create(vm, globalObject, IntlCollatorPrototype::createStructure(vm, globalObject, globalObject->objectPrototype()));
    Structure* collatorStructure = IntlCollator::createStructure(vm, globalObject, collatorPrototype);
    IntlCollatorConstructor* collatorConstructor = IntlCollatorConstructor::create(vm, IntlCollatorConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), collatorPrototype, collatorStructure);

    collatorPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, collatorConstructor, DontEnum);

    // Set up NumberFormat.
    IntlNumberFormatPrototype* numberFormatPrototype = IntlNumberFormatPrototype::create(vm, globalObject, IntlNumberFormatPrototype::createStructure(vm, globalObject, globalObject->objectPrototype()));
    Structure* numberFormatStructure = IntlNumberFormat::createStructure(vm, globalObject, numberFormatPrototype);
    IntlNumberFormatConstructor* numberFormatConstructor = IntlNumberFormatConstructor::create(vm, IntlNumberFormatConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), numberFormatPrototype, numberFormatStructure);

    numberFormatPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, numberFormatConstructor, DontEnum);

    // Set up DateTimeFormat.
    IntlDateTimeFormatPrototype* dateTimeFormatPrototype = IntlDateTimeFormatPrototype::create(vm, globalObject, IntlDateTimeFormatPrototype::createStructure(vm, globalObject, globalObject->objectPrototype()));
    Structure* dateTimeFormatStructure = IntlDateTimeFormat::createStructure(vm, globalObject, dateTimeFormatPrototype);
    IntlDateTimeFormatConstructor* dateTimeFormatConstructor = IntlDateTimeFormatConstructor::create(vm, IntlDateTimeFormatConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), dateTimeFormatPrototype, dateTimeFormatStructure);

    dateTimeFormatPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, dateTimeFormatConstructor, DontEnum);

    // 8.1 Properties of the Intl Object (ECMA-402 2.0)
    putDirectWithoutTransition(vm, vm.propertyNames->Collator, collatorConstructor, DontEnum);
    putDirectWithoutTransition(vm, vm.propertyNames->NumberFormat, numberFormatConstructor, DontEnum);
    putDirectWithoutTransition(vm, vm.propertyNames->DateTimeFormat, dateTimeFormatConstructor, DontEnum);
}

Structure* IntlObject::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
    return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
}

static String defaultLocale()
{
    // 6.2.4 DefaultLocale ()
    // FIXME: Implement this method.
    return ASCIILiteral("en");
}

bool intlBooleanOption(ExecState& state, JSValue options, PropertyName property, bool& usesFallback)
{
    // 9.2.9 GetOption (options, property, type, values, fallback)
    // For type="boolean". values is always undefined.

    // 1. Let opts be ToObject(options).
    JSObject* opts = options.toObject(&state);

    // 2. ReturnIfAbrupt(opts).
    if (state.hadException())
        return false;

    // 3. Let value be Get(opts, property).
    JSValue value = opts->get(&state, property);

    // 4. ReturnIfAbrupt(value).
    if (state.hadException())
        return false;

    // 5. If value is not undefined, then
    if (!value.isUndefined()) {
        // a. Assert: type is "boolean" or "string".
        // Function dedicated to "boolean".

        // b. If type is "boolean", then
        // i. Let value be ToBoolean(value).
        bool booleanValue = value.toBoolean(&state);

        // e. Return value.
        usesFallback = false;
        return booleanValue;
    }

    // 6. Else return fallback.
    // Because fallback can be undefined, we let the caller handle it instead.
    usesFallback = true;
    return false;
}

String intlStringOption(ExecState& state, JSValue options, PropertyName property, const HashSet<String>& values, const char* notFound, String fallback)
{
    // 9.2.9 GetOption (options, property, type, values, fallback)
    // For type="string".

    // 1. Let opts be ToObject(options).
    JSObject* opts = options.toObject(&state);

    // 2. ReturnIfAbrupt(opts).
    if (state.hadException())
        return String();

    // 3. Let value be Get(opts, property).
    JSValue value = opts->get(&state, property);

    // 4. ReturnIfAbrupt(value).
    if (state.hadException())
        return String();

    // 5. If value is not undefined, then
    if (!value.isUndefined()) {
        // a. Assert: type is "boolean" or "string".
        // Function dedicated to "string".

        // c. If type is "string", then
        // i. Let value be ToString(value).
        JSString* stringValue = value.toString(&state);

        // ii. ReturnIfAbrupt(value).
        if (state.hadException())
            return String();

        // d. If values is not undefined, then
        // i. If values does not contain an element equal to value, throw a RangeError exception.
        if (!values.isEmpty() && !values.contains(stringValue->value(&state))) {
            state.vm().throwException(&state, createRangeError(&state, String(notFound)));
            return String();
        }

        // e. Return value.
        return stringValue->value(&state);
    }

    // 6. Else return fallback.
    return fallback;
}

static String privateUseLangTag(const Vector<String>& parts, size_t startIndex)
{
    size_t numParts = parts.size();
    size_t currentIndex = startIndex;

    // Check for privateuse.
    // privateuse = "x" 1*("-" (2*8alphanum))
    StringBuilder privateuse;
    while (currentIndex < numParts) {
        const String& singleton = parts[currentIndex];
        unsigned singletonLength = singleton.length();
        bool isValid = (singletonLength == 1 && (singleton == "x" || singleton == "X"));
        if (!isValid)
            break;

        if (currentIndex != startIndex)
            privateuse.append('-');

        ++currentIndex;
        unsigned numExtParts = 0;
        privateuse.append('x');
        while (currentIndex < numParts) {
            const String& extPart = parts[currentIndex];
            unsigned extPartLength = extPart.length();

            bool isValid = (extPartLength >= 2 && extPartLength <= 8 && extPart.isAllSpecialCharacters<isASCIIAlphanumeric>());
            if (!isValid)
                break;

            ++currentIndex;
            ++numExtParts;
            privateuse.append('-');
            privateuse.append(extPart.convertToASCIILowercase());
        }

        // Requires at least one production.
        if (!numExtParts)
            return String();
    }

    // Leftovers makes it invalid.
    if (currentIndex < numParts)
        return String();

    return privateuse.toString();
}

static String canonicalLangTag(const Vector<String>& parts)
{
    ASSERT(!parts.isEmpty());

    // Follows the grammar at https://www.rfc-editor.org/rfc/bcp/bcp47.txt
    // langtag = language ["-" script] ["-" region] *("-" variant) *("-" extension) ["-" privateuse]

    size_t numParts = parts.size();
    // Check for language.
    // language = 2*3ALPHA ["-" extlang] / 4ALPHA / 5*8ALPHA
    size_t currentIndex = 0;
    const String& language = parts[currentIndex];
    unsigned languageLength = language.length();
    bool canHaveExtlang = languageLength >= 2 && languageLength <= 3;
    bool isValidLanguage = languageLength >= 2 && languageLength <= 8 && language.isAllSpecialCharacters<isASCIIAlpha>();
    if (!isValidLanguage)
        return String();

    ++currentIndex;
    StringBuilder canonical;
    canonical.append(language.convertToASCIILowercase());

    // Check for extlang.
    // extlang = 3ALPHA *2("-" 3ALPHA)
    if (canHaveExtlang) {
        for (unsigned times = 0; times < 3 && currentIndex < numParts; ++times) {
            const String& extlang = parts[currentIndex];
            unsigned extlangLength = extlang.length();
            if (extlangLength == 3 && extlang.isAllSpecialCharacters<isASCIIAlpha>()) {
                ++currentIndex;
                canonical.append('-');
                canonical.append(extlang.convertToASCIILowercase());
            } else
                break;
        }
    }

    // Check for script.
    // script = 4ALPHA
    if (currentIndex < numParts) {
        const String& script = parts[currentIndex];
        unsigned scriptLength = script.length();
        if (scriptLength == 4 && script.isAllSpecialCharacters<isASCIIAlpha>()) {
            ++currentIndex;
            canonical.append('-');
            canonical.append(toASCIIUpper(script[0]));
            canonical.append(script.substring(1, 3).convertToASCIILowercase());
        }
    }

    // Check for region.
    // region = 2ALPHA / 3DIGIT
    if (currentIndex < numParts) {
        const String& region = parts[currentIndex];
        unsigned regionLength = region.length();
        bool isValidRegion = (
            (regionLength == 2 && region.isAllSpecialCharacters<isASCIIAlpha>())
            || (regionLength == 3 && region.isAllSpecialCharacters<isASCIIDigit>())
        );
        if (isValidRegion) {
            ++currentIndex;
            canonical.append('-');
            canonical.append(region.upper());
        }
    }

    // Check for variant.
    // variant = 5*8alphanum / (DIGIT 3alphanum)
    HashSet<String> subtags;
    while (currentIndex < numParts) {
        const String& variant = parts[currentIndex];
        unsigned variantLength = variant.length();
        bool isValidVariant = (
            (variantLength >= 5 && variantLength <= 8 && variant.isAllSpecialCharacters<isASCIIAlphanumeric>())
            || (variantLength == 4 && isASCIIDigit(variant[0]) && variant.substring(1, 3).isAllSpecialCharacters<isASCIIAlphanumeric>())
        );
        if (!isValidVariant)
            break;

        // Cannot include duplicate subtags (case insensitive).
        String lowerVariant = variant.convertToASCIILowercase();
        if (!subtags.add(lowerVariant).isNewEntry)
            return String();

        ++currentIndex;

        // Reordering variant subtags is not required in the spec.
        canonical.append('-');
        canonical.append(lowerVariant);
    }

    // Check for extension.
    // extension = singleton 1*("-" (2*8alphanum))
    // singleton = alphanum except x or X
    subtags.clear();
    Vector<String> extensions;
    while (currentIndex < numParts) {
        const String& possibleSingleton = parts[currentIndex];
        unsigned singletonLength = possibleSingleton.length();
        bool isValidSingleton = (singletonLength == 1 && possibleSingleton != "x" && possibleSingleton != "X" && isASCIIAlphanumeric(possibleSingleton[0]));
        if (!isValidSingleton)
            break;

        // Cannot include duplicate singleton (case insensitive).
        String singleton = possibleSingleton.convertToASCIILowercase();
        if (!subtags.add(singleton).isNewEntry)
            return String();

        ++currentIndex;
        int numExtParts = 0;
        StringBuilder extension;
        extension.append(singleton);
        while (currentIndex < numParts) {
            const String& extPart = parts[currentIndex];
            unsigned extPartLength = extPart.length();

            bool isValid = (extPartLength >= 2 && extPartLength <= 8 && extPart.isAllSpecialCharacters<isASCIIAlphanumeric>());
            if (!isValid)
                break;

            ++currentIndex;
            ++numExtParts;
            extension.append('-');
            extension.append(extPart.convertToASCIILowercase());
        }

        // Requires at least one production.
        if (!numExtParts)
            return String();

        extensions.append(extension.toString());
    }

    // Add extensions to canonical sorted by singleton.
    std::sort(
        extensions.begin(),
        extensions.end(),
        [] (const String& a, const String& b) -> bool {
            return a[0] < b[0];
        }
    );
    size_t numExtenstions = extensions.size();
    for (size_t i = 0; i < numExtenstions; ++i) {
        canonical.append('-');
        canonical.append(extensions[i]);
    }

    // Check for privateuse.
    if (currentIndex < numParts) {
        String privateuse = privateUseLangTag(parts, currentIndex);
        if (privateuse.isNull())
            return String();
        canonical.append('-');
        canonical.append(privateuse);
    }

    // FIXME: Replace subtags with their preferred values.

    return canonical.toString();
}

static String grandfatheredLangTag(const String& locale)
{
    // grandfathered = irregular / regular
    // FIXME: convert to a compile time hash table if this is causing performance issues.
    HashMap<String, String> tagMap = {
        // Irregular.
        { ASCIILiteral("en-gb-oed"), ASCIILiteral("en-GB-oed") },
        { ASCIILiteral("i-ami"), ASCIILiteral("ami") },
        { ASCIILiteral("i-bnn"), ASCIILiteral("bnn") },
        { ASCIILiteral("i-default"), ASCIILiteral("i-default") },
        { ASCIILiteral("i-enochian"), ASCIILiteral("i-enochian") },
        { ASCIILiteral("i-hak"), ASCIILiteral("hak") },
        { ASCIILiteral("i-klingon"), ASCIILiteral("tlh") },
        { ASCIILiteral("i-lux"), ASCIILiteral("lb") },
        { ASCIILiteral("i-mingo"), ASCIILiteral("i-mingo") },
        { ASCIILiteral("i-navajo"), ASCIILiteral("nv") },
        { ASCIILiteral("i-pwn"), ASCIILiteral("pwn") },
        { ASCIILiteral("i-tao"), ASCIILiteral("tao") },
        { ASCIILiteral("i-tay"), ASCIILiteral("tay") },
        { ASCIILiteral("i-tsu"), ASCIILiteral("tsu") },
        { ASCIILiteral("sgn-be-fr"), ASCIILiteral("sfb") },
        { ASCIILiteral("sgn-be-nl"), ASCIILiteral("vgt") },
        { ASCIILiteral("sgn-ch-de"), ASCIILiteral("sgg") },
        // Regular.
        { ASCIILiteral("art-lojban"), ASCIILiteral("jbo") },
        { ASCIILiteral("cel-gaulish"), ASCIILiteral("cel-gaulish") },
        { ASCIILiteral("no-bok"), ASCIILiteral("nb") },
        { ASCIILiteral("no-nyn"), ASCIILiteral("nn") },
        { ASCIILiteral("zh-guoyu"), ASCIILiteral("cmn") },
        { ASCIILiteral("zh-hakka"), ASCIILiteral("hak") },
        { ASCIILiteral("zh-min"), ASCIILiteral("zh-min") },
        { ASCIILiteral("zh-min-nan"), ASCIILiteral("nan") },
        { ASCIILiteral("zh-xiang"), ASCIILiteral("hsn") }
    };

    return tagMap.get(locale.convertToASCIILowercase());
}

static String canonicalizeLanguageTag(const String& locale)
{
    // 6.2.2 IsStructurallyValidLanguageTag (locale)
    // 6.2.3 CanonicalizeLanguageTag (locale)
    // These are done one after another in CanonicalizeLocaleList, so they are combined here to reduce duplication.
    // https://www.rfc-editor.org/rfc/bcp/bcp47.txt

    // Language-Tag = langtag / privateuse / grandfathered
    String grandfather = grandfatheredLangTag(locale);
    if (!grandfather.isNull())
        return grandfather;

    // FIXME: Replace redundant tags [RFC4647].

    Vector<String> parts;
    locale.split('-', true, parts);
    if (!parts.isEmpty()) {
        String langtag = canonicalLangTag(parts);
        if (!langtag.isNull())
            return langtag;

        String privateuse = privateUseLangTag(parts, 0);
        if (!privateuse.isNull())
            return privateuse;
    }

    return String();
}

Vector<String> canonicalizeLocaleList(ExecState& state, JSValue locales)
{
    // 9.2.1 CanonicalizeLocaleList (locales)
    VM& vm = state.vm();
    JSGlobalObject* globalObject = state.callee()->globalObject();
    Vector<String> seen;

    // 1. If locales is undefined, then a. Return a new empty List.
    if (locales.isUndefined())
        return seen;

    // 2. Let seen be an empty List.
    // Done before to also return in step 1, if needed.

    // 3. If Type(locales) is String, then
    JSObject* localesObject;
    if (locales.isString()) {
        //  a. Let aLocales be CreateArrayFromList(«locales»).
        JSArray* localesArray = JSArray::tryCreateUninitialized(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 1);
        localesArray->initializeIndex(vm, 0, locales);
        // 4. Let O be ToObject(aLocales).
        localesObject = localesArray;
    } else {
        // 4. Let O be ToObject(aLocales).
        localesObject = locales.toObject(&state);
    }

    // 5. ReturnIfAbrupt(O).
    if (state.hadException())
        return Vector<String>();

    // 6. Let len be ToLength(Get(O, "length")).
    JSValue lengthProperty = localesObject->get(&state, vm.propertyNames->length);
    if (state.hadException())
        return Vector<String>();

    double length = lengthProperty.toLength(&state);
    if (state.hadException())
        return Vector<String>();

    // Keep track of locales that have been added to the list.
    HashSet<String> seenSet;

    // 7. Let k be 0.
    // 8. Repeat, while k < len
    for (double k = 0; k < length; ++k) {
        // a. Let Pk be ToString(k).
        // Not needed because hasProperty and get take an int for numeric key.

        // b. Let kPresent be HasProperty(O, Pk).
        bool kPresent = localesObject->hasProperty(&state, k);

        // c. ReturnIfAbrupt(kPresent).
        if (state.hadException())
            return Vector<String>();

        // d. If kPresent is true, then
        if (kPresent) {
            // i. Let kValue be Get(O, Pk).
            JSValue kValue = localesObject->get(&state, k);

            // ii. ReturnIfAbrupt(kValue).
            if (state.hadException())
                return Vector<String>();

            // iii. If Type(kValue) is not String or Object, throw a TypeError exception.
            if (!kValue.isString() && !kValue.isObject()) {
                throwTypeError(&state, ASCIILiteral("locale value must be a string or object"));
                return Vector<String>();
            }

            // iv. Let tag be ToString(kValue).
            JSString* tag = kValue.toString(&state);

            // v. ReturnIfAbrupt(tag).
            if (state.hadException())
                return Vector<String>();

            // vi. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception.
            // vii. Let canonicalizedTag be CanonicalizeLanguageTag(tag).
            String canonicalizedTag = canonicalizeLanguageTag(tag->value(&state));
            if (canonicalizedTag.isNull()) {
                state.vm().throwException(&state, createRangeError(&state, String::format("invalid language tag: %s", tag->value(&state).utf8().data())));
                return Vector<String>();
            }

            // viii. If canonicalizedTag is not an element of seen, append canonicalizedTag as the last element of seen.
            if (seenSet.add(canonicalizedTag).isNewEntry)
                seen.append(canonicalizedTag);
        }
        // e. Increase k by 1.
    }

    return seen;
}

static String bestAvailableLocale(const HashSet<String>& availableLocales, const String& locale)
{
    // 9.2.2 BestAvailableLocale (availableLocales, locale)
    // 1. Let candidate be locale.
    String candidate = locale;

    // 2. Repeat
    while (!candidate.isEmpty()) {
        // a. If availableLocales contains an element equal to candidate, then return candidate.
        if (availableLocales.contains(candidate))
            return candidate;

        // b. Let pos be the character index of the last occurrence of "-" (U+002D) within candidate. If that character does not occur, return undefined.
        size_t pos = candidate.reverseFind('-');
        if (pos == notFound)
            return String();

        // c. If pos ≥ 2 and the character "-" occurs at index pos-2 of candidate, then decrease pos by 2.
        if (pos >= 2 && candidate[pos - 2] == '-')
            pos -= 2;

        // d. Let candidate be the substring of candidate from position 0, inclusive, to position pos, exclusive.
        candidate = candidate.substring(0, pos);
    }

    return String();
}

static String removeUnicodeLocaleExtension(const String& locale)
{
    Vector<String> parts;
    locale.split('-', parts);
    StringBuilder builder;
    size_t partsSize = parts.size();
    if (partsSize > 0)
        builder.append(parts[0]);
    for (size_t p = 1; p < partsSize; ++p) {
        if (parts[p] == "u") {
            // Skip the u- and anything that follows until another singleton.
            // While the next part is part of the unicode extension, skip it.
            while (p + 1 < partsSize && parts[p + 1].length() > 1)
                ++p;
        } else {
            builder.append('-');
            builder.append(parts[p]);
        }
    }
    return builder.toString();
}

static MatcherResult lookupMatcher(const HashSet<String>& availableLocales, const Vector<String>& requestedLocales)
{
    // 9.2.3 LookupMatcher (availableLocales, requestedLocales) (ECMA-402 2.0)
    String locale;
    String noExtensionsLocale;
    String availableLocale;
    for (size_t i = 0; i < requestedLocales.size() && availableLocale.isNull(); ++i) {
        locale = requestedLocales[i];
        noExtensionsLocale = removeUnicodeLocaleExtension(locale);
        availableLocale = bestAvailableLocale(availableLocales, noExtensionsLocale);
    }

    MatcherResult result;
    if (!availableLocale.isNull()) {
        result.locale = availableLocale;
        if (locale != noExtensionsLocale) {
            // i. Let extension be the String value consisting of the first substring of locale that is a Unicode locale extension sequence.
            // ii. Let extensionIndex be the character position of the initial "-" extension sequence within locale.
            size_t extensionIndex = locale.find("-u-");
            RELEASE_ASSERT(extensionIndex != notFound);

            size_t extensionLength = locale.length() - extensionIndex;
            size_t end = extensionIndex + 3;
            while (end < locale.length()) {
                end = locale.find('-', end);
                if (end == notFound)
                    break;
                if (end + 2 < locale.length() && locale[end + 2] == '-') {
                    extensionLength = end - extensionIndex;
                    break;
                }
                end++;
            }
            result.extension = locale.substring(extensionIndex, extensionLength);
            result.extensionIndex = extensionIndex;
        }
    } else
        result.locale = defaultLocale();
    return result;
}

static MatcherResult bestFitMatcher(const HashSet<String>& availableLocales, const Vector<String>& requestedLocales)
{
    // 9.2.4 BestFitMatcher (availableLocales, requestedLocales) (ECMA-402 2.0)
    // FIXME: Implement something better than lookup.
    return lookupMatcher(availableLocales, requestedLocales);
}

HashMap<String, String> resolveLocale(const HashSet<String>& availableLocales, const Vector<String>& requestedLocales, const HashMap<String, String>& options, const Vector<String>& relevantExtensionKeys, Vector<String> (*localeData)(const String&, const String&))
{
    // 9.2.5 ResolveLocale (availableLocales, requestedLocales, options, relevantExtensionKeys, localeData) (ECMA-402 2.0)
    // 1. Let matcher be the value of options.[[localeMatcher]].
    const String& matcher = options.get(ASCIILiteral("localeMatcher"));

    // 2. If matcher is "lookup", then
    MatcherResult (*matcherOperation)(const HashSet<String>&, const Vector<String>&);
    if (matcher == "lookup") {
        // a. Let MatcherOperation be the abstract operation LookupMatcher.
        matcherOperation = lookupMatcher;
    } else { // 3. Else
        // a. Let MatcherOperation be the abstract operation BestFitMatcher.
        matcherOperation = bestFitMatcher;
    }

    // 4. Let r be MatcherOperation(availableLocales, requestedLocales).
    MatcherResult matcherResult = matcherOperation(availableLocales, requestedLocales);

    // 5. Let foundLocale be the value of r.[[locale]].
    String foundLocale = matcherResult.locale;

    // 6. If r has an [[extension]] field, then
    Vector<String> extensionSubtags;
    if (!matcherResult.extension.isNull()) {
        // a. Let extension be the value of r.[[extension]].
        // b. Let extensionIndex be the value of r.[[extensionIndex]].
        // c. Let extensionSubtags be Call(%StringProto_split%, extension, «"-"») .
        // d. Let extensionSubtagsLength be Get(CreateArrayFromList(extensionSubtags), "length").
        matcherResult.extension.split('-', extensionSubtags);
    }

    // 7. Let result be a new Record.
    HashMap<String, String> result;

    // 8. Set result.[[dataLocale]] to foundLocale.
    result.set(ASCIILiteral("dataLocale"), foundLocale);

    // 9. Let supportedExtension be "-u".
    String supportedExtension = ASCIILiteral("-u");

    // 10. Let k be 0.
    // 11. Let rExtensionKeys be ToObject(CreateArrayFromList(relevantExtensionKeys)).
    // 12. ReturnIfAbrupt(rExtensionKeys).
    // 13. Let len be ToLength(Get(rExtensionKeys, "length")).
    // 14. Repeat while k < len
    for (size_t k = 0; k < relevantExtensionKeys.size(); ++k) {
        // a. Let key be Get(rExtensionKeys, ToString(k)).
        // b. ReturnIfAbrupt(key).
        const String& key = relevantExtensionKeys[k];

        // c. Let foundLocaleData be Get(localeData, foundLocale).
        // d. ReturnIfAbrupt(foundLocaleData).
        // e. Let keyLocaleData be ToObject(Get(foundLocaleData, key)).
        // f. ReturnIfAbrupt(keyLocaleData).
        Vector<String> keyLocaleData = localeData(foundLocale, key);

        // g. Let value be ToString(Get(keyLocaleData, "0")).
        // h. ReturnIfAbrupt(value).
        ASSERT(!keyLocaleData.isEmpty());
        String value = keyLocaleData[0];

        // i. Let supportedExtensionAddition be "".
        String supportedExtensionAddition;

        // j. If extensionSubtags is not undefined, then
        if (!extensionSubtags.isEmpty()) {
            // i. Let keyPos be Call(%ArrayProto_indexOf%, extensionSubtags, «key») .
            size_t keyPos = extensionSubtags.find(key);
            // ii. If keyPos != -1, then
            if (keyPos != notFound) {
                // 1. If keyPos + 1 < extensionSubtagsLength and the length of the result of Get(extensionSubtags, ToString(keyPos +1)) is greater than 2, then
                if (keyPos + 1 < extensionSubtags.size() && extensionSubtags[keyPos + 1].length() > 2) {
                    const String& requestedValue = extensionSubtags[keyPos + 1];
                    if (keyLocaleData.contains(requestedValue)) {
                        value = requestedValue;
                        supportedExtensionAddition = "-" + key + '-' + value;
                    }
                } else if (keyLocaleData.contains(static_cast<String>(ASCIILiteral("true")))) {
                    // 2. Else, if the result of Call(%StringProto_includes%, keyLocaleData, «"true"») is true, then
                    value = ASCIILiteral("true");
                }
            }
        }

        // k. If options has a field [[<key>]], then
        HashMap<String, String>::const_iterator iterator = options.find(key);
        if (iterator != options.end()) {
            // i. Let optionsValue be the value of ToString(options.[[<key>]]).
            // ii. ReturnIfAbrupt(optionsValue).
            const String& optionsValue = iterator->value;
            // iii. If the result of Call(%StringProto_includes%, keyLocaleData, «optionsValue») is true, then
            if (!optionsValue.isNull() && keyLocaleData.contains(optionsValue)) {
                // 1. If optionsValue is not equal to value, then
                if (optionsValue != value) {
                    value = optionsValue;
                    supportedExtensionAddition = String();
                }
            }
        }

        // l. Set result.[[<key>]] to value.
        result.set(key, value);

        // m. Append supportedExtensionAddition to supportedExtension.
        supportedExtension.append(supportedExtensionAddition);

        // n. Increase k by 1.
    }

    // 15. If the number of elements in supportedExtension is greater than 2, then
    if (supportedExtension.length() > 2) {
        // a. Let preExtension be the substring of foundLocale from position 0, inclusive, to position extensionIndex, exclusive.
        // b. Let postExtension be the substring of foundLocale from position extensionIndex to the end of the string.
        // c. Let foundLocale be the concatenation of preExtension, supportedExtension, and postExtension.
        String preExtension = foundLocale.substring(0, matcherResult.extensionIndex);
        String postExtension = foundLocale.substring(matcherResult.extensionIndex);
        foundLocale = preExtension + supportedExtension + postExtension;
    }

    // 16. Set result.[[locale]] to foundLocale.
    result.set(ASCIILiteral("locale"), foundLocale);

    // 17. Return result.
    return result;
}

static JSArray* lookupSupportedLocales(ExecState& state, const HashSet<String>& availableLocales, const Vector<String>& requestedLocales)
{
    // 9.2.6 LookupSupportedLocales (availableLocales, requestedLocales)

    // 1. Let rLocales be CreateArrayFromList(requestedLocales).
    // Already an array.

    // 2. Let len be ToLength(Get(rLocales, "length")).
    size_t len = requestedLocales.size();

    // 3. Let subset be an empty List.
    VM& vm = state.vm();
    JSGlobalObject* globalObject = state.callee()->globalObject();
    JSArray* subset = JSArray::tryCreateUninitialized(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), 0);
    if (!subset) {
        throwOutOfMemoryError(&state);
        return nullptr;
    }

    // 4. Let k be 0.
    // 5. Repeat while k < len
    for (size_t k = 0; k < len; ++k) {
        // a. Let Pk be ToString(k).
        // b. Let locale be Get(rLocales, Pk).
        // c. ReturnIfAbrupt(locale).
        const String& locale = requestedLocales[k];

        // d. Let noExtensionsLocale be the String value that is locale with all Unicode locale extension sequences removed.
        String noExtensionsLocale = removeUnicodeLocaleExtension(locale);

        // e. Let availableLocale be BestAvailableLocale(availableLocales, noExtensionsLocale).
        String availableLocale = bestAvailableLocale(availableLocales, noExtensionsLocale);

        // f. If availableLocale is not undefined, then append locale to the end of subset.
        if (!availableLocale.isNull())
            subset->push(&state, jsString(&state, locale));

        // g. Increment k by 1.
    }

    // 6. Return subset.
    return subset;
}

static JSArray* bestFitSupportedLocales(ExecState& state, const HashSet<String>& availableLocales, const Vector<String>& requestedLocales)
{
    // 9.2.7 BestFitSupportedLocales (availableLocales, requestedLocales)
    // FIXME: Implement something better than lookup.
    return lookupSupportedLocales(state, availableLocales, requestedLocales);
}

JSValue supportedLocales(ExecState& state, const HashSet<String>& availableLocales, const Vector<String>& requestedLocales, JSValue options)
{
    // 9.2.8 SupportedLocales (availableLocales, requestedLocales, options)
    VM& vm = state.vm();
    String matcher;

    // 1. If options is not undefined, then
    if (!options.isUndefined()) {
        // a. Let matcher be GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit").
        const HashSet<String> matchers({ ASCIILiteral("lookup"), ASCIILiteral("best fit") });
        matcher = intlStringOption(state, options, vm.propertyNames->localeMatcher, matchers, "localeMatcher must be either \"lookup\" or \"best fit\"", ASCIILiteral("best fit"));
        // b. ReturnIfAbrupt(matcher).
        if (state.hadException())
            return jsUndefined();
    } else {
        // 2. Else, let matcher be "best fit".
        matcher = ASCIILiteral("best fit");
    }

    JSArray* supportedLocales;
    // 3. If matcher is "best fit",
    if (matcher == "best fit") {
        // a. Let MatcherOperation be the abstract operation BestFitSupportedLocales.
        // 5. Let supportedLocales be MatcherOperation(availableLocales, requestedLocales).
        supportedLocales = bestFitSupportedLocales(state, availableLocales, requestedLocales);
    } else {
        // 4. Else
        // a. Let MatcherOperation be the abstract operation LookupSupportedLocales.
        // 5. Let supportedLocales be MatcherOperation(availableLocales, requestedLocales).
        supportedLocales = lookupSupportedLocales(state, availableLocales, requestedLocales);
    }

    if (state.hadException())
        return jsUndefined();

    // 6. Let subset be CreateArrayFromList(supportedLocales).
    // Already an array.

    // 7. Let keys be subset.[[OwnPropertyKeys]]().
    PropertyNameArray keys(&state, PropertyNameMode::Strings);
    supportedLocales->getOwnPropertyNames(supportedLocales, &state, keys, EnumerationMode());

    PropertyDescriptor desc;
    desc.setConfigurable(false);
    desc.setWritable(false);

    // 8. Repeat for each element P of keys in List order,
    size_t len = keys.size();
    for (size_t i = 0; i < len; ++i) {
        // a. Let desc be PropertyDescriptor { [[Configurable]]: false, [[Writable]]: false }.
        // Created above for reuse.

        // b. Let status be DefinePropertyOrThrow(subset, P, desc).
        supportedLocales->defineOwnProperty(supportedLocales, &state, keys[i], desc, true);

        // c. Assert: status is not abrupt completion.
        if (state.hadException())
            return jsUndefined();
    }

    // 9. Return subset.
    return supportedLocales;
}

} // namespace JSC

#endif // ENABLE(INTL)
