// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

#include "unicode/ustring.h"
#include "unicode/ures.h"
#include "cstring.h"
#include "charstr.h"
#include "resource.h"
#include "number_compact.h"
#include "number_microprops.h"
#include "uresimp.h"

using namespace icu;
using namespace icu::number;
using namespace icu::number::impl;

namespace {

// A dummy object used when a "0" compact decimal entry is encountered. This is necessary
// in order to prevent falling back to root. Object equality ("==") is intended.
const UChar *USE_FALLBACK = u"<USE FALLBACK>";

/** Produces a string like "NumberElements/latn/patternsShort/decimalFormat". */
void getResourceBundleKey(const char *nsName, CompactStyle compactStyle, CompactType compactType,
                                 CharString &sb, UErrorCode &status) {
    sb.clear();
    sb.append("NumberElements/", status);
    sb.append(nsName, status);
    sb.append(compactStyle == CompactStyle::UNUM_SHORT ? "/patternsShort" : "/patternsLong", status);
    sb.append(compactType == CompactType::TYPE_DECIMAL ? "/decimalFormat" : "/currencyFormat", status);
}

int32_t getIndex(int32_t magnitude, StandardPlural::Form plural) {
    return magnitude * StandardPlural::COUNT + plural;
}

int32_t countZeros(const UChar *patternString, int32_t patternLength) {
    // NOTE: This strategy for computing the number of zeros is a hack for efficiency.
    // It could break if there are any 0s that aren't part of the main pattern.
    int32_t numZeros = 0;
    for (int32_t i = 0; i < patternLength; i++) {
        if (patternString[i] == u'0') {
            numZeros++;
        } else if (numZeros > 0) {
            break; // zeros should always be contiguous
        }
    }
    return numZeros;
}

} // namespace

// NOTE: patterns and multipliers both get zero-initialized.
CompactData::CompactData() : patterns(), multipliers(), largestMagnitude(0), isEmpty(TRUE) {
}

void CompactData::populate(const Locale &locale, const char *nsName, CompactStyle compactStyle,
                           CompactType compactType, UErrorCode &status) {
    CompactDataSink sink(*this);
    LocalUResourceBundlePointer rb(ures_open(nullptr, locale.getName(), &status));
    if (U_FAILURE(status)) { return; }

    bool nsIsLatn = strcmp(nsName, "latn") == 0;
    bool compactIsShort = compactStyle == CompactStyle::UNUM_SHORT;

    // Fall back to latn numbering system and/or short compact style.
    CharString resourceKey;
    getResourceBundleKey(nsName, compactStyle, compactType, resourceKey, status);
    UErrorCode localStatus = U_ZERO_ERROR;
    ures_getAllItemsWithFallback(rb.getAlias(), resourceKey.data(), sink, localStatus);
    if (isEmpty && !nsIsLatn) {
        getResourceBundleKey("latn", compactStyle, compactType, resourceKey, status);
        localStatus = U_ZERO_ERROR;
        ures_getAllItemsWithFallback(rb.getAlias(), resourceKey.data(), sink, localStatus);
    }
    if (isEmpty && !compactIsShort) {
        getResourceBundleKey(nsName, CompactStyle::UNUM_SHORT, compactType, resourceKey, status);
        localStatus = U_ZERO_ERROR;
        ures_getAllItemsWithFallback(rb.getAlias(), resourceKey.data(), sink, localStatus);
    }
    if (isEmpty && !nsIsLatn && !compactIsShort) {
        getResourceBundleKey("latn", CompactStyle::UNUM_SHORT, compactType, resourceKey, status);
        localStatus = U_ZERO_ERROR;
        ures_getAllItemsWithFallback(rb.getAlias(), resourceKey.data(), sink, localStatus);
    }

    // The last fallback should be guaranteed to return data.
    if (isEmpty) {
        status = U_INTERNAL_PROGRAM_ERROR;
    }
}

int32_t CompactData::getMultiplier(int32_t magnitude) const {
    if (magnitude < 0) {
        return 0;
    }
    if (magnitude > largestMagnitude) {
        magnitude = largestMagnitude;
    }
    return multipliers[magnitude];
}

const UChar *CompactData::getPattern(int32_t magnitude, StandardPlural::Form plural) const {
    if (magnitude < 0) {
        return nullptr;
    }
    if (magnitude > largestMagnitude) {
        magnitude = largestMagnitude;
    }
    const UChar *patternString = patterns[getIndex(magnitude, plural)];
    if (patternString == nullptr && plural != StandardPlural::OTHER) {
        // Fall back to "other" plural variant
        patternString = patterns[getIndex(magnitude, StandardPlural::OTHER)];
    }
    if (patternString == USE_FALLBACK) { // == is intended
        // Return null if USE_FALLBACK is present
        patternString = nullptr;
    }
    return patternString;
}

void CompactData::getUniquePatterns(UVector &output, UErrorCode &status) const {
    U_ASSERT(output.isEmpty());
    // NOTE: In C++, this is done more manually with a UVector.
    // In Java, we can take advantage of JDK HashSet.
    for (auto pattern : patterns) {
        if (pattern == nullptr || pattern == USE_FALLBACK) {
            continue;
        }

        // Insert pattern into the UVector if the UVector does not already contain the pattern.
        // Search the UVector from the end since identical patterns are likely to be adjacent.
        for (int32_t i = output.size() - 1; i >= 0; i--) {
            if (u_strcmp(pattern, static_cast<const UChar *>(output[i])) == 0) {
                goto continue_outer;
            }
        }

        // The string was not found; add it to the UVector.
        // ANDY: This requires a const_cast.  Why?
        output.addElement(const_cast<UChar *>(pattern), status);

        continue_outer:
        continue;
    }
}

void CompactData::CompactDataSink::put(const char *key, ResourceValue &value, UBool /*noFallback*/,
                                       UErrorCode &status) {
    // traverse into the table of powers of ten
    ResourceTable powersOfTenTable = value.getTable(status);
    if (U_FAILURE(status)) { return; }
    for (int i3 = 0; powersOfTenTable.getKeyAndValue(i3, key, value); ++i3) {

        // Assumes that the keys are always of the form "10000" where the magnitude is the
        // length of the key minus one.  We expect magnitudes to be less than MAX_DIGITS.
        auto magnitude = static_cast<int8_t> (strlen(key) - 1);
        int8_t multiplier = data.multipliers[magnitude];
        U_ASSERT(magnitude < COMPACT_MAX_DIGITS);

        // Iterate over the plural variants ("one", "other", etc)
        ResourceTable pluralVariantsTable = value.getTable(status);
        if (U_FAILURE(status)) { return; }
        for (int i4 = 0; pluralVariantsTable.getKeyAndValue(i4, key, value); ++i4) {

            // Skip this magnitude/plural if we already have it from a child locale.
            // Note: This also skips USE_FALLBACK entries.
            StandardPlural::Form plural = StandardPlural::fromString(key, status);
            if (U_FAILURE(status)) { return; }
            if (data.patterns[getIndex(magnitude, plural)] != nullptr) {
                continue;
            }

            // The value "0" means that we need to use the default pattern and not fall back
            // to parent locales. Example locale where this is relevant: 'it'.
            int32_t patternLength;
            const UChar *patternString = value.getString(patternLength, status);
            if (U_FAILURE(status)) { return; }
            if (u_strcmp(patternString, u"0") == 0) {
                patternString = USE_FALLBACK;
                patternLength = 0;
            }

            // Save the pattern string. We will parse it lazily.
            data.patterns[getIndex(magnitude, plural)] = patternString;

            // If necessary, compute the multiplier: the difference between the magnitude
            // and the number of zeros in the pattern.
            if (multiplier == 0) {
                int32_t numZeros = countZeros(patternString, patternLength);
                if (numZeros > 0) { // numZeros==0 in certain cases, like Somali "Kun"
                    multiplier = static_cast<int8_t> (numZeros - magnitude - 1);
                }
            }
        }

        // Save the multiplier.
        if (data.multipliers[magnitude] == 0) {
            data.multipliers[magnitude] = multiplier;
            if (magnitude > data.largestMagnitude) {
                data.largestMagnitude = magnitude;
            }
            data.isEmpty = false;
        } else {
            U_ASSERT(data.multipliers[magnitude] == multiplier);
        }
    }
}

///////////////////////////////////////////////////////////
/// END OF CompactData.java; BEGIN CompactNotation.java ///
///////////////////////////////////////////////////////////

CompactHandler::CompactHandler(
        CompactStyle compactStyle,
        const Locale &locale,
        const char *nsName,
        CompactType compactType,
        const PluralRules *rules,
        MutablePatternModifier *buildReference,
        bool safe,
        const MicroPropsGenerator *parent,
        UErrorCode &status)
        : rules(rules), parent(parent), safe(safe) {
    data.populate(locale, nsName, compactStyle, compactType, status);
    if (safe) {
        // Safe code path
        precomputeAllModifiers(*buildReference, status);
    } else {
        // Unsafe code path
        // Store the MutablePatternModifier reference.
        unsafePatternModifier = buildReference;
    }
}

CompactHandler::~CompactHandler() {
    for (int32_t i = 0; i < precomputedModsLength; i++) {
        delete precomputedMods[i].mod;
    }
}

void CompactHandler::precomputeAllModifiers(MutablePatternModifier &buildReference, UErrorCode &status) {
    if (U_FAILURE(status)) { return; }

    // Initial capacity of 12 for 0K, 00K, 000K, ...M, ...B, and ...T
    UVector allPatterns(12, status);
    if (U_FAILURE(status)) { return; }
    data.getUniquePatterns(allPatterns, status);
    if (U_FAILURE(status)) { return; }

    // C++ only: ensure that precomputedMods has room.
    precomputedModsLength = allPatterns.size();
    if (precomputedMods.getCapacity() < precomputedModsLength) {
        precomputedMods.resize(allPatterns.size(), status);
        if (U_FAILURE(status)) { return; }
    }

    for (int32_t i = 0; i < precomputedModsLength; i++) {
        auto patternString = static_cast<const UChar *>(allPatterns[i]);
        UnicodeString hello(patternString);
        CompactModInfo &info = precomputedMods[i];
        ParsedPatternInfo patternInfo;
        PatternParser::parseToPatternInfo(UnicodeString(patternString), patternInfo, status);
        if (U_FAILURE(status)) { return; }
        buildReference.setPatternInfo(&patternInfo, UNUM_COMPACT_FIELD);
        info.mod = buildReference.createImmutable(status);
        if (U_FAILURE(status)) { return; }
        info.patternString = patternString;
    }
}

void CompactHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micros,
                                     UErrorCode &status) const {
    parent->processQuantity(quantity, micros, status);
    if (U_FAILURE(status)) { return; }

    // Treat zero, NaN, and infinity as if they had magnitude 0
    int32_t magnitude;
    if (quantity.isZeroish()) {
        magnitude = 0;
        micros.rounder.apply(quantity, status);
    } else {
        // TODO: Revisit chooseMultiplierAndApply
        int32_t multiplier = micros.rounder.chooseMultiplierAndApply(quantity, data, status);
        magnitude = quantity.isZeroish() ? 0 : quantity.getMagnitude();
        magnitude -= multiplier;
    }

    StandardPlural::Form plural = utils::getStandardPlural(rules, quantity);
    const UChar *patternString = data.getPattern(magnitude, plural);
    if (patternString == nullptr) {
        // Use the default (non-compact) modifier.
        // No need to take any action.
    } else if (safe) {
        // Safe code path.
        // Java uses a hash set here for O(1) lookup.  C++ uses a linear search.
        // TODO: Benchmark this and maybe change to a binary search or hash table.
        int32_t i = 0;
        for (; i < precomputedModsLength; i++) {
            const CompactModInfo &info = precomputedMods[i];
            if (u_strcmp(patternString, info.patternString) == 0) {
                info.mod->applyToMicros(micros, quantity, status);
                break;
            }
        }
        // It should be guaranteed that we found the entry.
        U_ASSERT(i < precomputedModsLength);
    } else {
        // Unsafe code path.
        // Overwrite the PatternInfo in the existing modMiddle.
        // C++ Note: Use unsafePatternInfo for proper lifecycle.
        ParsedPatternInfo &patternInfo = const_cast<CompactHandler *>(this)->unsafePatternInfo;
        PatternParser::parseToPatternInfo(UnicodeString(patternString), patternInfo, status);
        unsafePatternModifier->setPatternInfo(&unsafePatternInfo, UNUM_COMPACT_FIELD);
        unsafePatternModifier->setNumberProperties(quantity.signum(), StandardPlural::Form::COUNT);
        micros.modMiddle = unsafePatternModifier;
    }

    // We already performed rounding. Do not perform it again.
    micros.rounder = RoundingImpl::passThrough();
}

#endif /* #if !UCONFIG_NO_FORMATTING */
