/*
 * Copyright (C) 2015, International Business Machines
 * Corporation and others.  All Rights Reserved.
 *
 * file name: digitformatter.cpp
 */

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING
#if defined(STARBOARD)
#include "starboard/client_porting/poem/string_poem.h"
#endif  // defined(STARBOARD)

#include "unicode/dcfmtsym.h"
#include "unicode/unum.h"

#include "digitformatter.h"
#include "digitgrouping.h"
#include "digitinterval.h"
#include "digitlst.h"
#include "fphdlimp.h"
#include "smallintformatter.h"
#include "unistrappender.h"
#include "visibledigits.h"

U_NAMESPACE_BEGIN

DigitFormatter::DigitFormatter()
        : fGroupingSeparator(",", -1, US_INV), fDecimal(".", -1, US_INV),
          fNegativeSign("-", -1, US_INV), fPositiveSign("+", -1, US_INV),
          fIsStandardDigits(TRUE), fExponent("E", -1, US_INV) {
    for (int32_t i = 0; i < 10; ++i) {
        fLocalizedDigits[i] = (UChar32) (0x30 + i);
    }
    fInfinity.setTo(UnicodeString("Inf", -1, US_INV), UNUM_INTEGER_FIELD);
    fNan.setTo(UnicodeString("Nan", -1, US_INV), UNUM_INTEGER_FIELD);
}

DigitFormatter::DigitFormatter(const DecimalFormatSymbols &symbols) {
    setDecimalFormatSymbols(symbols);
}

void
DigitFormatter::setOtherDecimalFormatSymbols(
        const DecimalFormatSymbols &symbols) {
    fLocalizedDigits[0] = symbols.getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
    fLocalizedDigits[1] = symbols.getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol).char32At(0);
    fLocalizedDigits[2] = symbols.getConstSymbol(DecimalFormatSymbols::kTwoDigitSymbol).char32At(0);
    fLocalizedDigits[3] = symbols.getConstSymbol(DecimalFormatSymbols::kThreeDigitSymbol).char32At(0);
    fLocalizedDigits[4] = symbols.getConstSymbol(DecimalFormatSymbols::kFourDigitSymbol).char32At(0);
    fLocalizedDigits[5] = symbols.getConstSymbol(DecimalFormatSymbols::kFiveDigitSymbol).char32At(0);
    fLocalizedDigits[6] = symbols.getConstSymbol(DecimalFormatSymbols::kSixDigitSymbol).char32At(0);
    fLocalizedDigits[7] = symbols.getConstSymbol(DecimalFormatSymbols::kSevenDigitSymbol).char32At(0);
    fLocalizedDigits[8] = symbols.getConstSymbol(DecimalFormatSymbols::kEightDigitSymbol).char32At(0);
    fLocalizedDigits[9] = symbols.getConstSymbol(DecimalFormatSymbols::kNineDigitSymbol).char32At(0);
    fIsStandardDigits = isStandardDigits();
    fNegativeSign = symbols.getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
    fPositiveSign = symbols.getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
    fInfinity.setTo(symbols.getConstSymbol(DecimalFormatSymbols::kInfinitySymbol), UNUM_INTEGER_FIELD);
    fNan.setTo(symbols.getConstSymbol(DecimalFormatSymbols::kNaNSymbol), UNUM_INTEGER_FIELD);
    fExponent = symbols.getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
}

void
DigitFormatter::setDecimalFormatSymbolsForMonetary(
        const DecimalFormatSymbols &symbols) {
    setOtherDecimalFormatSymbols(symbols);
    fGroupingSeparator = symbols.getConstSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol);
    fDecimal = symbols.getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
}

void
DigitFormatter::setDecimalFormatSymbols(
        const DecimalFormatSymbols &symbols) {
    setOtherDecimalFormatSymbols(symbols);
    fGroupingSeparator = symbols.getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
    fDecimal = symbols.getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
}

static void appendField(
        int32_t fieldId,
        const UnicodeString &value,
        FieldPositionHandler &handler,
        UnicodeString &appendTo) {
    int32_t currentLength = appendTo.length();
    appendTo.append(value);
    handler.addAttribute(
            fieldId,
            currentLength,
            appendTo.length());
}

int32_t DigitFormatter::countChar32(
        const DigitGrouping &grouping,
        const DigitInterval &interval,
        const DigitFormatterOptions &options) const {
    int32_t result = interval.length();

    // We always emit '0' in lieu of no digits.
    if (result == 0) {
        result = 1;
    }
    if (options.fAlwaysShowDecimal || interval.getLeastSignificantInclusive() < 0) {
        result += fDecimal.countChar32();
    }
    result += grouping.getSeparatorCount(interval.getIntDigitCount()) * fGroupingSeparator.countChar32();
    return result;
}

int32_t
DigitFormatter::countChar32(
        const VisibleDigits &digits,
        const DigitGrouping &grouping,
        const DigitFormatterOptions &options) const {
    if (digits.isNaN()) {
        return countChar32ForNaN();
    }   
    if (digits.isInfinite()) {
        return countChar32ForInfinity();
    }   
    return countChar32(
            grouping,
            digits.getInterval(),
            options);
}

int32_t
DigitFormatter::countChar32(
        const VisibleDigitsWithExponent &digits,
        const SciFormatterOptions &options) const {
    if (digits.isNaN()) {
        return countChar32ForNaN();
    }
    if (digits.isInfinite()) {
        return countChar32ForInfinity();
    }
    const VisibleDigits *exponent = digits.getExponent();
    if (exponent == NULL) {
        DigitGrouping grouping;
        return countChar32(
                grouping,
                digits.getMantissa().getInterval(),
                options.fMantissa);
    }
    return countChar32(
            *exponent, digits.getMantissa().getInterval(), options);
}

int32_t
DigitFormatter::countChar32(
        const VisibleDigits &exponent,
        const DigitInterval &mantissaInterval,
        const SciFormatterOptions &options) const {
    DigitGrouping grouping;
    int32_t count = countChar32(
            grouping, mantissaInterval, options.fMantissa);
    count += fExponent.countChar32();
    count += countChar32ForExponent(
            exponent, options.fExponent);
    return count;
}

UnicodeString &DigitFormatter::format(
        const VisibleDigits &digits,
        const DigitGrouping &grouping,
        const DigitFormatterOptions &options,
        FieldPositionHandler &handler,
        UnicodeString &appendTo) const {
    if (digits.isNaN()) {
        return formatNaN(handler, appendTo);
    }
    if (digits.isInfinite()) {
        return formatInfinity(handler, appendTo);
    }

    const DigitInterval &interval = digits.getInterval();
    int32_t digitsLeftOfDecimal = interval.getMostSignificantExclusive();
    int32_t lastDigitPos = interval.getLeastSignificantInclusive();
    int32_t intBegin = appendTo.length();
    int32_t fracBegin;

    // Emit "0" instead of empty string.
    if (digitsLeftOfDecimal == 0 && lastDigitPos == 0) {
        appendTo.append(fLocalizedDigits[0]);
        handler.addAttribute(UNUM_INTEGER_FIELD, intBegin, appendTo.length());
        if (options.fAlwaysShowDecimal) {
            appendField(
                    UNUM_DECIMAL_SEPARATOR_FIELD,
                    fDecimal,
                    handler,
                    appendTo);
        }
        return appendTo;
    }
    {
        UnicodeStringAppender appender(appendTo);
        for (int32_t i = interval.getMostSignificantExclusive() - 1;
                i >= interval.getLeastSignificantInclusive(); --i) {
            if (i == -1) {
                appender.flush();
                appendField(
                        UNUM_DECIMAL_SEPARATOR_FIELD,
                        fDecimal,
                        handler,
                        appendTo);
                fracBegin = appendTo.length();
            }
            appender.append(fLocalizedDigits[digits.getDigitByExponent(i)]);
            if (grouping.isSeparatorAt(digitsLeftOfDecimal, i)) {
                appender.flush();
                appendField(
                        UNUM_GROUPING_SEPARATOR_FIELD,
                        fGroupingSeparator,
                        handler,
                        appendTo);
            }
            if (i == 0) {
                appender.flush();
                if (digitsLeftOfDecimal > 0) {
                    handler.addAttribute(UNUM_INTEGER_FIELD, intBegin, appendTo.length());
                }
            }
        }
        if (options.fAlwaysShowDecimal && lastDigitPos == 0) {
            appender.flush();
            appendField(
                    UNUM_DECIMAL_SEPARATOR_FIELD,
                    fDecimal,
                    handler,
                    appendTo);
        }
    }
    // lastDigitPos is never > 0 so we are guaranteed that kIntegerField
    // is already added.
    if (lastDigitPos < 0) {
        handler.addAttribute(UNUM_FRACTION_FIELD, fracBegin, appendTo.length());
    }
    return appendTo;
}

UnicodeString &
DigitFormatter::format(
        const VisibleDigitsWithExponent &digits,
        const SciFormatterOptions &options,
        FieldPositionHandler &handler,
        UnicodeString &appendTo) const {
    DigitGrouping grouping;
    format(
            digits.getMantissa(),
            grouping,
            options.fMantissa,
            handler,
            appendTo);
    const VisibleDigits *exponent = digits.getExponent();
    if (exponent == NULL) {
        return appendTo;
    }
    int32_t expBegin = appendTo.length();
    appendTo.append(fExponent);
    handler.addAttribute(
            UNUM_EXPONENT_SYMBOL_FIELD, expBegin, appendTo.length());
    return formatExponent(
            *exponent,
            options.fExponent,
            UNUM_EXPONENT_SIGN_FIELD,
            UNUM_EXPONENT_FIELD,
            handler,
            appendTo);
}

static int32_t formatInt(
        int32_t value, uint8_t *digits) {
    int32_t idx = 0;
    while (value > 0) {
        digits[idx++] = (uint8_t) (value % 10);
        value /= 10;
    }
    return idx;
}

UnicodeString &
DigitFormatter::formatDigits(
        const uint8_t *digits,
        int32_t count,
        const IntDigitCountRange &range,
        int32_t intField,
        FieldPositionHandler &handler,
        UnicodeString &appendTo) const {
    int32_t i = range.pin(count) - 1;
    int32_t begin = appendTo.length();

    // Always emit '0' as placeholder for empty string.
    if (i == -1) {
        appendTo.append(fLocalizedDigits[0]);
        handler.addAttribute(intField, begin, appendTo.length());
        return appendTo;
    }
    {
        UnicodeStringAppender appender(appendTo);
        for (; i >= count; --i) {
            appender.append(fLocalizedDigits[0]);
        }
        for (; i >= 0; --i) {
            appender.append(fLocalizedDigits[digits[i]]);
        }
    }
    handler.addAttribute(intField, begin, appendTo.length());
    return appendTo;
}

UnicodeString &
DigitFormatter::formatExponent(
        const VisibleDigits &digits,
        const DigitFormatterIntOptions &options,
        int32_t signField,
        int32_t intField,
        FieldPositionHandler &handler,
        UnicodeString &appendTo) const {
    UBool neg = digits.isNegative();
    if (neg || options.fAlwaysShowSign) {
        appendField(
                signField,
                neg ? fNegativeSign : fPositiveSign,
                handler,
                appendTo);
    }
    int32_t begin = appendTo.length();
    DigitGrouping grouping;
    DigitFormatterOptions expOptions;
    FieldPosition fpos(FieldPosition::DONT_CARE);
    FieldPositionOnlyHandler noHandler(fpos);
    format(
            digits,
            grouping,
            expOptions,
            noHandler,
            appendTo);
    handler.addAttribute(intField, begin, appendTo.length());
    return appendTo;
}

int32_t
DigitFormatter::countChar32ForExponent(
        const VisibleDigits &exponent,
        const DigitFormatterIntOptions &options) const {
    int32_t result = 0;
    UBool neg = exponent.isNegative();
    if (neg || options.fAlwaysShowSign) {
        result += neg ? fNegativeSign.countChar32() : fPositiveSign.countChar32();
    }
    DigitGrouping grouping;
    DigitFormatterOptions expOptions;
    result += countChar32(grouping, exponent.getInterval(), expOptions);
    return result;
}

UnicodeString &
DigitFormatter::formatPositiveInt32(
        int32_t positiveValue,
        const IntDigitCountRange &range,
        FieldPositionHandler &handler,
        UnicodeString &appendTo) const {
    // super fast path
    if (fIsStandardDigits && SmallIntFormatter::canFormat(positiveValue, range)) {
        int32_t begin = appendTo.length();
        SmallIntFormatter::format(positiveValue, range, appendTo);
        handler.addAttribute(UNUM_INTEGER_FIELD, begin, appendTo.length());
        return appendTo;
    }
    uint8_t digits[10];
    int32_t count = formatInt(positiveValue, digits);
    return formatDigits(
            digits,
            count,
            range,
            UNUM_INTEGER_FIELD,
            handler,
            appendTo);
}

UBool DigitFormatter::isStandardDigits() const {
    UChar32 cdigit = 0x30;
    for (int32_t i = 0; i < UPRV_LENGTHOF(fLocalizedDigits); ++i) {
        if (fLocalizedDigits[i] != cdigit) {
            return FALSE;
        }
        ++cdigit;
    }
    return TRUE;
}

UBool
DigitFormatter::equals(const DigitFormatter &rhs) const {
    UBool result = (fGroupingSeparator == rhs.fGroupingSeparator) &&
                   (fDecimal == rhs.fDecimal) &&
                   (fNegativeSign == rhs.fNegativeSign) &&
                   (fPositiveSign == rhs.fPositiveSign) &&
                   (fInfinity.equals(rhs.fInfinity)) &&
                   (fNan.equals(rhs.fNan)) &&
                   (fIsStandardDigits == rhs.fIsStandardDigits) &&
                   (fExponent == rhs.fExponent);

    if (!result) {
        return FALSE;
    }
    for (int32_t i = 0; i < UPRV_LENGTHOF(fLocalizedDigits); ++i) {
        if (fLocalizedDigits[i] != rhs.fLocalizedDigits[i]) {
            return FALSE;
        }
    }
    return TRUE;
}


U_NAMESPACE_END

#endif /* #if !UCONFIG_NO_FORMATTING */
