/*
 * Copyright (C) 2020-2021 Apple Inc. All rights reserved.
 *
 * 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 "IntlListFormat.h"

#include "IntlObjectInlines.h"
#include "IteratorOperations.h"
#include "JSCInlines.h"
#include "ObjectConstructor.h"

// While UListFormatter APIs are draft in ICU 67, they are stable in ICU 68 with the same function signatures.
// So we can assume that these signatures of draft APIs are stable.
#if HAVE(ICU_U_LIST_FORMATTER)
#ifdef U_HIDE_DRAFT_API
#undef U_HIDE_DRAFT_API
#endif
#endif
#include <unicode/ulistformatter.h>
#if HAVE(ICU_U_LIST_FORMATTER)
#define U_HIDE_DRAFT_API 1
#endif

#if HAVE(ICU_U_LIST_FORMATTER)
#include <unicode/uformattedvalue.h>
#endif

namespace JSC {

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

// We do not use ICUDeleter<ulistfmt_close> because we do not want to include ulistformatter.h in IntlListFormat.h.
// ulistformatter.h needs to be included with #undef U_HIDE_DRAFT_API, and we would like to minimize this effect in IntlListFormat.cpp.
void UListFormatterDeleter::operator()(UListFormatter* formatter)
{
    if (formatter)
        ulistfmt_close(formatter);
}

IntlListFormat* IntlListFormat::create(VM& vm, Structure* structure)
{
    auto* object = new (NotNull, allocateCell<IntlListFormat>(vm)) IntlListFormat(vm, structure);
    object->finishCreation(vm);
    return object;
}

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

IntlListFormat::IntlListFormat(VM& vm, Structure* structure)
    : Base(vm, structure)
{
}

void IntlListFormat::finishCreation(VM& vm)
{
    Base::finishCreation(vm);
    ASSERT(inherits(vm, info()));
}

// https://tc39.es/proposal-intl-list-format/#sec-Intl.ListFormat
void IntlListFormat::initializeListFormat(JSGlobalObject* globalObject, JSValue locales, JSValue optionsValue)
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    auto requestedLocales = canonicalizeLocaleList(globalObject, locales);
    RETURN_IF_EXCEPTION(scope, void());

    JSObject* options = intlGetOptionsObject(globalObject, optionsValue);
    RETURN_IF_EXCEPTION(scope, void());

    ResolveLocaleOptions localeOptions;

    LocaleMatcher localeMatcher = intlOption<LocaleMatcher>(globalObject, options, vm.propertyNames->localeMatcher, { { "lookup"_s, LocaleMatcher::Lookup }, { "best fit"_s, LocaleMatcher::BestFit } }, "localeMatcher must be either \"lookup\" or \"best fit\""_s, LocaleMatcher::BestFit);
    RETURN_IF_EXCEPTION(scope, void());

    auto localeData = [](const String&, RelevantExtensionKey) -> Vector<String> {
        return { };
    };

    const auto& availableLocales = intlListFormatAvailableLocales();
    auto resolved = resolveLocale(globalObject, availableLocales, requestedLocales, localeMatcher, localeOptions, { }, localeData);

    m_locale = resolved.locale;
    if (m_locale.isEmpty()) {
        throwTypeError(globalObject, scope, "failed to initialize ListFormat due to invalid locale"_s);
        return;
    }

    m_type = intlOption<Type>(globalObject, options, vm.propertyNames->type, { { "conjunction"_s, Type::Conjunction }, { "disjunction"_s, Type::Disjunction }, { "unit"_s, Type::Unit } }, "type must be either \"conjunction\", \"disjunction\", or \"unit\""_s, Type::Conjunction);
    RETURN_IF_EXCEPTION(scope, void());

    m_style = intlOption<Style>(globalObject, options, vm.propertyNames->style, { { "long"_s, Style::Long }, { "short"_s, Style::Short }, { "narrow"_s, Style::Narrow } }, "style must be either \"long\", \"short\", or \"narrow\""_s, Style::Long);
    RETURN_IF_EXCEPTION(scope, void());

#if HAVE(ICU_U_LIST_FORMATTER)
    auto toUListFormatterType = [](Type type) {
        switch (type) {
        case Type::Conjunction:
            return ULISTFMT_TYPE_AND;
        case Type::Disjunction:
            return ULISTFMT_TYPE_OR;
        case Type::Unit:
            return ULISTFMT_TYPE_UNITS;
        }
        return ULISTFMT_TYPE_AND;
    };

    auto toUListFormatterWidth = [](Style style) {
        switch (style) {
        case Style::Long:
            return ULISTFMT_WIDTH_WIDE;
        case Style::Short:
            return ULISTFMT_WIDTH_SHORT;
        case Style::Narrow:
            return ULISTFMT_WIDTH_NARROW;
        }
        return ULISTFMT_WIDTH_WIDE;
    };

    UErrorCode status = U_ZERO_ERROR;
    m_listFormat = std::unique_ptr<UListFormatter, UListFormatterDeleter>(ulistfmt_openForType(m_locale.utf8().data(), toUListFormatterType(m_type), toUListFormatterWidth(m_style), &status));
    if (U_FAILURE(status)) {
        throwTypeError(globalObject, scope, "failed to initialize ListFormat"_s);
        return;
    }
#else
    throwTypeError(globalObject, scope, "Failed to initialize Intl.ListFormat since this feature is not supported in the linked ICU version"_s);
    return;
#endif
}

#if HAVE(ICU_U_LIST_FORMATTER)
static Vector<String, 4> stringListFromIterable(JSGlobalObject* globalObject, JSValue iterable)
{
    Vector<String, 4> result;

    if (iterable.isUndefined())
        return result;

    forEachInIterable(globalObject, iterable, [&](VM& vm, JSGlobalObject* globalObject, JSValue value) {
        auto scope = DECLARE_THROW_SCOPE(vm);
        if (!value.isString()) {
            throwTypeError(globalObject, scope, "Iterable passed to ListFormat includes non String"_s);
            return;
        }
        String item = value.toWTFString(globalObject);
        RETURN_IF_EXCEPTION(scope, void());
        result.append(item);
    });
    return result;
}

class ListFormatInput {
    WTF_MAKE_NONCOPYABLE(ListFormatInput);
public:
    ListFormatInput(Vector<String, 4>&& strings)
        : m_strings(WTFMove(strings))
    {
        m_stringPointers.reserveInitialCapacity(m_strings.size());
        m_stringLengths.reserveInitialCapacity(m_strings.size());
        for (auto& string : m_strings) {
            if (string.is8Bit()) {
                auto vector = makeUnique<Vector<UChar>>();
                vector->resize(string.length());
                StringImpl::copyCharacters(vector->data(), string.characters8(), string.length());
                m_retainedUpconvertedStrings.append(WTFMove(vector));
                m_stringPointers.append(m_retainedUpconvertedStrings.last()->data());
            } else
                m_stringPointers.append(string.characters16());
            m_stringLengths.append(string.length());
        }
    }

    int32_t size() const { return m_stringPointers.size(); }
    const UChar* const* stringPointers() const { return m_stringPointers.data(); }
    const int32_t* stringLengths() const { return m_stringLengths.data(); }

private:
    Vector<String, 4> m_strings;
    Vector<std::unique_ptr<Vector<UChar>>, 4> m_retainedUpconvertedStrings;
    Vector<const UChar*, 4> m_stringPointers;
    Vector<int32_t, 4> m_stringLengths;
};
#endif

// https://tc39.es/proposal-intl-list-format/#sec-Intl.ListFormat.prototype.format
JSValue IntlListFormat::format(JSGlobalObject* globalObject, JSValue list) const
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

#if HAVE(ICU_U_LIST_FORMATTER)
    auto stringList = stringListFromIterable(globalObject, list);
    RETURN_IF_EXCEPTION(scope, { });

    ListFormatInput input(WTFMove(stringList));

    Vector<UChar, 32> result;
    auto status = callBufferProducingFunction(ulistfmt_format, m_listFormat.get(), input.stringPointers(), input.stringLengths(), input.size(), result);
    if (U_FAILURE(status))
        return throwTypeError(globalObject, scope, "failed to format list of strings"_s);

    return jsString(vm, String(result));
#else
    UNUSED_PARAM(list);
    return throwTypeError(globalObject, scope, "failed to format list of strings"_s);
#endif
}

// https://tc39.es/proposal-intl-list-format/#sec-Intl.ListFormat.prototype.formatToParts
JSValue IntlListFormat::formatToParts(JSGlobalObject* globalObject, JSValue list) const
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

#if HAVE(ICU_U_LIST_FORMATTER)
    auto stringList = stringListFromIterable(globalObject, list);
    RETURN_IF_EXCEPTION(scope, { });

    ListFormatInput input(WTFMove(stringList));

    UErrorCode status = U_ZERO_ERROR;

    auto result = std::unique_ptr<UFormattedList, ICUDeleter<ulistfmt_closeResult>>(ulistfmt_openResult(&status));
    if (U_FAILURE(status))
        return throwTypeError(globalObject, scope, "failed to format list of strings"_s);

    ulistfmt_formatStringsToResult(m_listFormat.get(), input.stringPointers(), input.stringLengths(), input.size(), result.get(), &status);
    if (U_FAILURE(status))
        return throwTypeError(globalObject, scope, "failed to format list of strings"_s);

    // UFormattedValue is owned by UFormattedList. We do not need to close it.
    auto formattedValue = ulistfmt_resultAsValue(result.get(), &status);
    if (U_FAILURE(status))
        return throwTypeError(globalObject, scope, "failed to format list of strings"_s);

    JSArray* parts = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 0);
    if (!parts)
        return throwOutOfMemoryError(globalObject, scope);

    int32_t formattedStringLength = 0;
    const UChar* formattedStringPointer = ufmtval_getString(formattedValue, &formattedStringLength, &status);
    if (U_FAILURE(status))
        return throwTypeError(globalObject, scope, "failed to format list of strings"_s);
    String resultString(formattedStringPointer, formattedStringLength);

    auto iterator = std::unique_ptr<UConstrainedFieldPosition, ICUDeleter<ucfpos_close>>(ucfpos_open(&status));
    if (U_FAILURE(status))
        return throwTypeError(globalObject, scope, "failed to format list of strings"_s);

    ucfpos_constrainField(iterator.get(), UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, &status);
    if (U_FAILURE(status))
        return throwTypeError(globalObject, scope, "failed to format list of strings"_s);

    auto literalString = jsNontrivialString(vm, "literal"_s);
    auto elementString = jsNontrivialString(vm, "element"_s);

    auto createPart = [&] (JSString* type, JSString* value) {
        JSObject* part = constructEmptyObject(globalObject);
        part->putDirect(vm, vm.propertyNames->type, type);
        part->putDirect(vm, vm.propertyNames->value, value);
        return part;
    };

    int32_t resultLength = resultString.length();
    int32_t previousEndIndex = 0;
    while (true) {
        bool next = ufmtval_nextPosition(formattedValue, iterator.get(), &status);
        if (U_FAILURE(status))
            return throwTypeError(globalObject, scope, "failed to format list of strings"_s);
        if (!next)
            break;

        int32_t beginIndex = 0;
        int32_t endIndex = 0;
        ucfpos_getIndexes(iterator.get(), &beginIndex, &endIndex, &status);
        if (U_FAILURE(status))
            return throwTypeError(globalObject, scope, "failed to format list of strings"_s);

        if (previousEndIndex < beginIndex) {
            auto value = jsString(vm, resultString.substring(previousEndIndex, beginIndex - previousEndIndex));
            JSObject* part = createPart(literalString, value);
            parts->push(globalObject, part);
            RETURN_IF_EXCEPTION(scope, { });
        }
        previousEndIndex = endIndex;

        auto value = jsString(vm, resultString.substring(beginIndex, endIndex - beginIndex));
        JSObject* part = createPart(elementString, value);
        parts->push(globalObject, part);
        RETURN_IF_EXCEPTION(scope, { });
    }

    if (previousEndIndex < resultLength) {
        auto value = jsString(vm, resultString.substring(previousEndIndex, resultLength - previousEndIndex));
        JSObject* part = createPart(literalString, value);
        parts->push(globalObject, part);
        RETURN_IF_EXCEPTION(scope, { });
    }

    return parts;
#else
    UNUSED_PARAM(list);
    return throwTypeError(globalObject, scope, "failed to format list of strings"_s);
#endif
}

// https://tc39.es/proposal-intl-list-format/#sec-Intl.ListFormat.prototype.resolvedOptions
JSObject* IntlListFormat::resolvedOptions(JSGlobalObject* globalObject) const
{
    VM& vm = globalObject->vm();
    JSObject* options = constructEmptyObject(globalObject);
    options->putDirect(vm, vm.propertyNames->locale, jsString(vm, m_locale));
    options->putDirect(vm, vm.propertyNames->type, jsNontrivialString(vm, typeString(m_type)));
    options->putDirect(vm, vm.propertyNames->style, jsNontrivialString(vm, styleString(m_style)));
    return options;
}

ASCIILiteral IntlListFormat::styleString(Style style)
{
    switch (style) {
    case Style::Long:
        return "long"_s;
    case Style::Short:
        return "short"_s;
    case Style::Narrow:
        return "narrow"_s;
    }
    ASSERT_NOT_REACHED();
    return ASCIILiteral::null();
}

ASCIILiteral IntlListFormat::typeString(Type type)
{
    switch (type) {
    case Type::Conjunction:
        return "conjunction"_s;
    case Type::Disjunction:
        return "disjunction"_s;
    case Type::Unit:
        return "unit"_s;
    }
    ASSERT_NOT_REACHED();
    return ASCIILiteral::null();
}

} // namespace JSC
