// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
******************************************************************************
* Copyright (C) 2014-2016, International Business Machines
* Corporation and others.  All Rights Reserved.
******************************************************************************
* quantityformatter.cpp
*/

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

#if defined(STARBOARD)
#include "starboard/client_porting/poem/assert_poem.h"
#include "starboard/client_porting/poem/string_poem.h"
#endif  // defined(STARBOARD)
#include "unicode/simpleformatter.h"
#include "quantityformatter.h"
#include "uassert.h"
#include "unicode/unistr.h"
#include "unicode/decimfmt.h"
#include "cstring.h"
#include "unicode/plurrule.h"
#include "charstr.h"
#include "unicode/fmtable.h"
#include "unicode/fieldpos.h"
#include "standardplural.h"
#include "uassert.h"
#include "number_decimalquantity.h"
#include "number_utypes.h"
#include "formatted_string_builder.h"

U_NAMESPACE_BEGIN

QuantityFormatter::QuantityFormatter() {
    for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
        formatters[i] = NULL;
    }
}

QuantityFormatter::QuantityFormatter(const QuantityFormatter &other) {
    for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
        if (other.formatters[i] == NULL) {
            formatters[i] = NULL;
        } else {
            formatters[i] = new SimpleFormatter(*other.formatters[i]);
        }
    }
}

QuantityFormatter &QuantityFormatter::operator=(
        const QuantityFormatter& other) {
    if (this == &other) {
        return *this;
    }
    for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
        delete formatters[i];
        if (other.formatters[i] == NULL) {
            formatters[i] = NULL;
        } else {
            formatters[i] = new SimpleFormatter(*other.formatters[i]);
        }
    }
    return *this;
}

QuantityFormatter::~QuantityFormatter() {
    for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
        delete formatters[i];
    }
}

void QuantityFormatter::reset() {
    for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
        delete formatters[i];
        formatters[i] = NULL;
    }
}

UBool QuantityFormatter::addIfAbsent(
        const char *variant,
        const UnicodeString &rawPattern,
        UErrorCode &status) {
    int32_t pluralIndex = StandardPlural::indexFromString(variant, status);
    if (U_FAILURE(status)) {
        return FALSE;
    }
    if (formatters[pluralIndex] != NULL) {
        return TRUE;
    }
    SimpleFormatter *newFmt = new SimpleFormatter(rawPattern, 0, 1, status);
    if (newFmt == NULL) {
        status = U_MEMORY_ALLOCATION_ERROR;
        return FALSE;
    }
    if (U_FAILURE(status)) {
        delete newFmt;
        return FALSE;
    }
    formatters[pluralIndex] = newFmt;
    return TRUE;
}

UBool QuantityFormatter::isValid() const {
    return formatters[StandardPlural::OTHER] != NULL;
}

const SimpleFormatter *QuantityFormatter::getByVariant(
        const char *variant) const {
    U_ASSERT(isValid());
    int32_t pluralIndex = StandardPlural::indexOrOtherIndexFromString(variant);
    const SimpleFormatter *pattern = formatters[pluralIndex];
    if (pattern == NULL) {
        pattern = formatters[StandardPlural::OTHER];
    }
    return pattern;
}

UnicodeString &QuantityFormatter::format(
            const Formattable &number,
            const NumberFormat &fmt,
            const PluralRules &rules,
            UnicodeString &appendTo,
            FieldPosition &pos,
            UErrorCode &status) const {
    UnicodeString formattedNumber;
    StandardPlural::Form p = selectPlural(number, fmt, rules, formattedNumber, pos, status);
    if (U_FAILURE(status)) {
        return appendTo;
    }
    const SimpleFormatter *pattern = formatters[p];
    if (pattern == NULL) {
        pattern = formatters[StandardPlural::OTHER];
        if (pattern == NULL) {
            status = U_INVALID_STATE_ERROR;
            return appendTo;
        }
    }
    return format(*pattern, formattedNumber, appendTo, pos, status);
}

// The following methods live here so that class PluralRules does not depend on number formatting,
// and the SimpleFormatter does not depend on FieldPosition.

StandardPlural::Form QuantityFormatter::selectPlural(
            const Formattable &number,
            const NumberFormat &fmt,
            const PluralRules &rules,
            UnicodeString &formattedNumber,
            FieldPosition &pos,
            UErrorCode &status) {
    if (U_FAILURE(status)) {
        return StandardPlural::OTHER;
    }
    UnicodeString pluralKeyword;
    const DecimalFormat *decFmt = dynamic_cast<const DecimalFormat *>(&fmt);
    if (decFmt != NULL) {
        number::impl::DecimalQuantity dq;
        decFmt->formatToDecimalQuantity(number, dq, status);
        if (U_FAILURE(status)) {
            return StandardPlural::OTHER;
        }
        pluralKeyword = rules.select(dq);
        decFmt->format(number, formattedNumber, pos, status);
    } else {
        if (number.getType() == Formattable::kDouble) {
            pluralKeyword = rules.select(number.getDouble());
        } else if (number.getType() == Formattable::kLong) {
            pluralKeyword = rules.select(number.getLong());
        } else if (number.getType() == Formattable::kInt64) {
            pluralKeyword = rules.select((double) number.getInt64());
        } else {
            status = U_ILLEGAL_ARGUMENT_ERROR;
            return StandardPlural::OTHER;
        }
        fmt.format(number, formattedNumber, pos, status);
    }
    return StandardPlural::orOtherFromString(pluralKeyword);
}

void QuantityFormatter::formatAndSelect(
        double quantity,
        const NumberFormat& fmt,
        const PluralRules& rules,
        FormattedStringBuilder& output,
        StandardPlural::Form& pluralForm,
        UErrorCode& status) {
    UnicodeString pluralKeyword;
    const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(&fmt);
    if (df != nullptr) {
        number::impl::UFormattedNumberData fn;
        fn.quantity.setToDouble(quantity);
        const number::LocalizedNumberFormatter* lnf = df->toNumberFormatter(status);
        if (U_FAILURE(status)) {
            return;
        }
        lnf->formatImpl(&fn, status);
        if (U_FAILURE(status)) {
            return;
        }
        output = std::move(fn.getStringRef());
        pluralKeyword = rules.select(fn.quantity);
    } else {
        UnicodeString result;
        fmt.format(quantity, result, status);
        if (U_FAILURE(status)) {
            return;
        }
        // This code path is probably RBNF. Use the generic numeric field.
        output.append(result, kGeneralNumericField, status);
        if (U_FAILURE(status)) {
            return;
        }
        pluralKeyword = rules.select(quantity);
    }
    pluralForm = StandardPlural::orOtherFromString(pluralKeyword);
}

UnicodeString &QuantityFormatter::format(
            const SimpleFormatter &pattern,
            const UnicodeString &value,
            UnicodeString &appendTo,
            FieldPosition &pos,
            UErrorCode &status) {
    if (U_FAILURE(status)) {
        return appendTo;
    }
    const UnicodeString *param = &value;
    int32_t offset;
    pattern.formatAndAppend(&param, 1, appendTo, &offset, 1, status);
    if (pos.getBeginIndex() != 0 || pos.getEndIndex() != 0) {
        if (offset >= 0) {
            pos.setBeginIndex(pos.getBeginIndex() + offset);
            pos.setEndIndex(pos.getEndIndex() + offset);
        } else {
            pos.setBeginIndex(0);
            pos.setEndIndex(0);
        }
    }
    return appendTo;
}

U_NAMESPACE_END

#endif /* #if !UCONFIG_NO_FORMATTING */
