// © 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, const MicroPropsGenerator *parent,
                               UErrorCode &status)
        : rules(rules), parent(parent) {
    data.populate(locale, nsName, compactStyle, compactType, status);
    if (buildReference != nullptr) {
        // Safe code path
        precomputeAllModifiers(*buildReference, status);
        safe = TRUE;
    } else {
        // Unsafe code path
        safe = FALSE;
    }
}

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);
        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 as if it had magnitude 0
    int32_t magnitude;
    if (quantity.isZero()) {
        magnitude = 0;
        micros.rounder.apply(quantity, status);
    } else {
        // TODO: Revisit chooseMultiplierAndApply
        int32_t multiplier = micros.rounder.chooseMultiplierAndApply(quantity, data, status);
        magnitude = quantity.isZero() ? 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);
                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);
        static_cast<MutablePatternModifier*>(const_cast<Modifier*>(micros.modMiddle))
            ->setPatternInfo(&patternInfo);
    }

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

#endif /* #if !UCONFIG_NO_FORMATTING */
