/*
 * Copyright (C) 2015, International Business Machines
 * Corporation and others.  All Rights Reserved.
 *
 * file name: digitaffixesandpadding.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/plurrule.h"
#include "charstr.h"
#include "digitaffix.h"
#include "digitaffixesandpadding.h"
#include "digitlst.h"
#include "uassert.h"
#include "valueformatter.h"
#include "visibledigits.h"

U_NAMESPACE_BEGIN

UBool
DigitAffixesAndPadding::needsPluralRules() const {
    return (
            fPositivePrefix.hasMultipleVariants() ||
            fPositiveSuffix.hasMultipleVariants() ||
            fNegativePrefix.hasMultipleVariants() ||
            fNegativeSuffix.hasMultipleVariants());
}

UnicodeString &
DigitAffixesAndPadding::formatInt32(
        int32_t value,
        const ValueFormatter &formatter,
        FieldPositionHandler &handler,
        const PluralRules *optPluralRules,
        UnicodeString &appendTo,
        UErrorCode &status) const {
    if (U_FAILURE(status)) {
        return appendTo;
    }
    if (optPluralRules != NULL || fWidth > 0 || !formatter.isFastFormattable(value)) {
        VisibleDigitsWithExponent digits;
        formatter.toVisibleDigitsWithExponent(
                (int64_t) value, digits, status);
        return format(
                digits,
                formatter,
                handler,
                optPluralRules,
                appendTo,
                status);
    }
    UBool bPositive = value >= 0;
    const DigitAffix *prefix = bPositive ? &fPositivePrefix.getOtherVariant() : &fNegativePrefix.getOtherVariant();
    const DigitAffix *suffix = bPositive ? &fPositiveSuffix.getOtherVariant() : &fNegativeSuffix.getOtherVariant();
    if (value < 0) {
        value = -value;
    }
    prefix->format(handler, appendTo);
    formatter.formatInt32(value, handler, appendTo);
    return suffix->format(handler, appendTo);
}

static UnicodeString &
formatAffix(
        const DigitAffix *affix,
        FieldPositionHandler &handler,
        UnicodeString &appendTo) {
    if (affix) {
        affix->format(handler, appendTo);
    }
    return appendTo;
}

static int32_t
countAffixChar32(const DigitAffix *affix) {
    if (affix) {
        return affix->countChar32();
    }
    return 0;
}

UnicodeString &
DigitAffixesAndPadding::format(
        const VisibleDigitsWithExponent &digits,
        const ValueFormatter &formatter,
        FieldPositionHandler &handler,
        const PluralRules *optPluralRules,
        UnicodeString &appendTo,
        UErrorCode &status) const {
    if (U_FAILURE(status)) {
        return appendTo;
    }
    const DigitAffix *prefix = NULL;
    const DigitAffix *suffix = NULL;
    if (!digits.isNaN()) {
        UBool bPositive = !digits.isNegative();
        const PluralAffix *pluralPrefix = bPositive ? &fPositivePrefix : &fNegativePrefix;
        const PluralAffix *pluralSuffix = bPositive ? &fPositiveSuffix : &fNegativeSuffix;
        if (optPluralRules == NULL || digits.isInfinite()) {
            prefix = &pluralPrefix->getOtherVariant();
            suffix = &pluralSuffix->getOtherVariant();
        } else {
            UnicodeString count(optPluralRules->select(digits));
            prefix = &pluralPrefix->getByCategory(count);
            suffix = &pluralSuffix->getByCategory(count);
        }
    }
    if (fWidth <= 0) {
        formatAffix(prefix, handler, appendTo);
        formatter.format(digits, handler, appendTo);
        return formatAffix(suffix, handler, appendTo);
    }
    int32_t codePointCount = countAffixChar32(prefix) + formatter.countChar32(digits) + countAffixChar32(suffix);
    int32_t paddingCount = fWidth - codePointCount;
    switch (fPadPosition) {
    case kPadBeforePrefix:
        appendPadding(paddingCount, appendTo);
        formatAffix(prefix, handler, appendTo);
        formatter.format(digits, handler, appendTo);
        return formatAffix(suffix, handler, appendTo);
    case kPadAfterPrefix:
        formatAffix(prefix, handler, appendTo);
        appendPadding(paddingCount, appendTo);
        formatter.format(digits, handler, appendTo);
        return formatAffix(suffix, handler, appendTo);
    case kPadBeforeSuffix:
        formatAffix(prefix, handler, appendTo);
        formatter.format(digits, handler, appendTo);
        appendPadding(paddingCount, appendTo);
        return formatAffix(suffix, handler, appendTo);
    case kPadAfterSuffix:
        formatAffix(prefix, handler, appendTo);
        formatter.format(digits, handler, appendTo);
        formatAffix(suffix, handler, appendTo);
        return appendPadding(paddingCount, appendTo);
    default:
        U_ASSERT(FALSE);
        return appendTo;
    }
}

UnicodeString &
DigitAffixesAndPadding::format(
        DigitList &value,
        const ValueFormatter &formatter,
        FieldPositionHandler &handler,
        const PluralRules *optPluralRules,
        UnicodeString &appendTo,
        UErrorCode &status) const {
    VisibleDigitsWithExponent digits;
    formatter.toVisibleDigitsWithExponent(
            value, digits, status);
    if (U_FAILURE(status)) {
        return appendTo;
    }
    return format(
            digits, formatter, handler, optPluralRules, appendTo, status);
}

UnicodeString &
DigitAffixesAndPadding::appendPadding(int32_t paddingCount, UnicodeString &appendTo) const {
    for (int32_t i = 0; i < paddingCount; ++i) {
        appendTo.append(fPadChar);
    }
    return appendTo;
}


U_NAMESPACE_END
#endif /* #if !UCONFIG_NO_FORMATTING */
