// © 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 <cstdlib>

#include "unicode/simpleformatter.h"
#include "unicode/ures.h"
#include "ureslocs.h"
#include "charstr.h"
#include "uresimp.h"
#include "measunit_impl.h"
#include "number_longnames.h"
#include "number_microprops.h"
#include <algorithm>
#include "cstring.h"
#include "util.h"

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

namespace {

/**
 * Display Name (this format has no placeholder).
 *
 * Used as an index into the LongNameHandler::simpleFormats array. Units
 * resources cover the normal set of PluralRules keys, as well as `dnam` and
 * `per` forms.
 */
constexpr int32_t DNAM_INDEX = StandardPlural::Form::COUNT;
/**
 * "per" form (e.g. "{0} per day" is day's "per" form).
 *
 * Used as an index into the LongNameHandler::simpleFormats array. Units
 * resources cover the normal set of PluralRules keys, as well as `dnam` and
 * `per` forms.
 */
constexpr int32_t PER_INDEX = StandardPlural::Form::COUNT + 1;
/**
 * Gender of the word, in languages with grammatical gender.
 */
constexpr int32_t GENDER_INDEX = StandardPlural::Form::COUNT + 2;
// Number of keys in the array populated by PluralTableSink.
constexpr int32_t ARRAY_LENGTH = StandardPlural::Form::COUNT + 3;

// TODO(icu-units#28): load this list from resources, after creating a "&set"
// function for use in ldml2icu rules.
const int32_t GENDER_COUNT = 7;
const char *gGenders[GENDER_COUNT] = {"animate",   "common", "feminine", "inanimate",
                                      "masculine", "neuter", "personal"};

// Converts a UnicodeString to a const char*, either pointing to a string in
// gGenders, or pointing to an empty string if an appropriate string was not
// found.
const char *getGenderString(UnicodeString uGender, UErrorCode status) {
    if (uGender.length() == 0) {
        return "";
    }
    CharString gender;
    gender.appendInvariantChars(uGender, status);
    if (U_FAILURE(status)) {
        return "";
    }
    int32_t first = 0;
    int32_t last = GENDER_COUNT;
    while (first < last) {
        int32_t mid = (first + last) / 2;
        int32_t cmp = uprv_strcmp(gender.data(), gGenders[mid]);
        if (cmp == 0) {
            return gGenders[mid];
        } else if (cmp > 0) {
            first = mid + 1;
        } else if (cmp < 0) {
            last = mid;
        }
    }
    // We don't return an error in case our gGenders list is incomplete in
    // production.
    //
    // TODO(icu-units#28): a unit test checking all locales' genders are covered
    // by gGenders? Else load a complete list of genders found in
    // grammaticalFeatures in an initOnce.
    return "";
}

// Returns the array index that corresponds to the given pluralKeyword.
static int32_t getIndex(const char* pluralKeyword, UErrorCode& status) {
    // pluralKeyword can also be "dnam", "per", or "gender"
    switch (*pluralKeyword) {
    case 'd':
        if (uprv_strcmp(pluralKeyword + 1, "nam") == 0) {
            return DNAM_INDEX;
        }
        break;
    case 'g':
        if (uprv_strcmp(pluralKeyword + 1, "ender") == 0) {
            return GENDER_INDEX;
        }
        break;
    case 'p':
        if (uprv_strcmp(pluralKeyword + 1, "er") == 0) {
            return PER_INDEX;
        }
        break;
    default:
        break;
    }
    StandardPlural::Form plural = StandardPlural::fromString(pluralKeyword, status);
    return plural;
}

// Selects a string out of the `strings` array which corresponds to the
// specified plural form, with fallback to the OTHER form.
//
// The `strings` array must have ARRAY_LENGTH items: one corresponding to each
// of the plural forms, plus a display name ("dnam") and a "per" form.
static UnicodeString getWithPlural(
        const UnicodeString* strings,
        StandardPlural::Form plural,
        UErrorCode& status) {
    UnicodeString result = strings[plural];
    if (result.isBogus()) {
        result = strings[StandardPlural::Form::OTHER];
    }
    if (result.isBogus()) {
        // There should always be data in the "other" plural variant.
        status = U_INTERNAL_PROGRAM_ERROR;
    }
    return result;
}

enum PlaceholderPosition { PH_EMPTY, PH_NONE, PH_BEGINNING, PH_MIDDLE, PH_END };

/**
 * Returns three outputs extracted from pattern.
 *
 * @param coreUnit is extracted as per Extract(...) in the spec:
 *   https://unicode.org/reports/tr35/tr35-general.html#compound-units
 * @param PlaceholderPosition indicates where in the string the placeholder was
 *   found.
 * @param joinerChar Iff the placeholder was at the beginning or end, joinerChar
 *   contains the space character (if any) that separated the placeholder from
 *   the rest of the pattern. Otherwise, joinerChar is set to NUL. Only one
 *   space character is considered.
 */
void extractCorePattern(const UnicodeString &pattern,
                        UnicodeString &coreUnit,
                        PlaceholderPosition &placeholderPosition,
                        UChar &joinerChar) {
    joinerChar = 0;
    int32_t len = pattern.length();
    if (pattern.startsWith(u"{0}", 3)) {
        placeholderPosition = PH_BEGINNING;
        if (u_isJavaSpaceChar(pattern[3])) {
            joinerChar = pattern[3];
            coreUnit.setTo(pattern, 4, len - 4);
        } else {
            coreUnit.setTo(pattern, 3, len - 3);
        }
    } else if (pattern.endsWith(u"{0}", 3)) {
        placeholderPosition = PH_END;
        if (u_isJavaSpaceChar(pattern[len - 4])) {
            coreUnit.setTo(pattern, 0, len - 4);
            joinerChar = pattern[len - 4];
        } else {
            coreUnit.setTo(pattern, 0, len - 3);
        }
    } else if (pattern.indexOf(u"{0}", 3, 1, len - 2) == -1) {
        placeholderPosition = PH_NONE;
        coreUnit = pattern;
    } else {
        placeholderPosition = PH_MIDDLE;
        coreUnit = pattern;
    }
}

//////////////////////////
/// BEGIN DATA LOADING ///
//////////////////////////

// Gets the gender of a built-in unit: unit must be a built-in. Returns an empty
// string both in case of unknown gender and in case of unknown unit.
UnicodeString
getGenderForBuiltin(const Locale &locale, const MeasureUnit &builtinUnit, UErrorCode &status) {
    LocalUResourceBundlePointer unitsBundle(ures_open(U_ICUDATA_UNIT, locale.getName(), &status));
    if (U_FAILURE(status)) { return {}; }

    // Map duration-year-person, duration-week-person, etc. to duration-year, duration-week, ...
    // TODO(ICU-20400): Get duration-*-person data properly with aliases.
    StringPiece subtypeForResource;
    int32_t subtypeLen = static_cast<int32_t>(uprv_strlen(builtinUnit.getSubtype()));
    if (subtypeLen > 7 && uprv_strcmp(builtinUnit.getSubtype() + subtypeLen - 7, "-person") == 0) {
        subtypeForResource = {builtinUnit.getSubtype(), subtypeLen - 7};
    } else {
        subtypeForResource = builtinUnit.getSubtype();
    }

    CharString key;
    key.append("units/", status);
    key.append(builtinUnit.getType(), status);
    key.append("/", status);
    key.append(subtypeForResource, status);
    key.append("/gender", status);

    UErrorCode localStatus = status;
    int32_t resultLen = 0;
    const UChar *result =
        ures_getStringByKeyWithFallback(unitsBundle.getAlias(), key.data(), &resultLen, &localStatus);
    if (U_SUCCESS(localStatus)) {
        status = localStatus;
        return UnicodeString(true, result, resultLen);
    } else {
        // TODO(icu-units#28): "$unitRes/gender" does not exist. Do we want to
        // check whether the parent "$unitRes" exists? Then we could return
        // U_MISSING_RESOURCE_ERROR for incorrect usage (e.g. builtinUnit not
        // being a builtin).
        return {};
    }
}

// Loads data from a resource tree with paths matching
// $key/$pluralForm/$gender/$case, with lateral inheritance for missing cases
// and genders.
//
// An InflectedPluralSink is configured to load data for a specific gender and
// case. It loads all plural forms, because selection between plural forms is
// dependent upon the value being formatted.
//
// See data/unit/de.txt and data/unit/fr.txt for examples - take a look at
// units/compound/power2: German has case, French has differences for gender,
// but no case.
//
// TODO(icu-units#138): Conceptually similar to PluralTableSink, however the
// tree structures are different. After homogenizing the structures, we may be
// able to unify the two classes.
//
// TODO: Spec violation: expects presence of "count" - does not fallback to an
// absent "count"! If this fallback were added, getCompoundValue could be
// superseded?
class InflectedPluralSink : public ResourceSink {
  public:
    // Accepts `char*` rather than StringPiece because
    // ResourceTable::findValue(...) requires a null-terminated `char*`.
    //
    // NOTE: outArray MUST have a length of at least ARRAY_LENGTH. No bounds
    // checking is performed.
    explicit InflectedPluralSink(const char *gender, const char *caseVariant, UnicodeString *outArray)
        : gender(gender), caseVariant(caseVariant), outArray(outArray) {
        // Initialize the array to bogus strings.
        for (int32_t i = 0; i < ARRAY_LENGTH; i++) {
            outArray[i].setToBogus();
        }
    }

    // See ResourceSink::put().
    void put(const char *key, ResourceValue &value, UBool /*noFallback*/, UErrorCode &status) U_OVERRIDE {
        int32_t pluralIndex = getIndex(key, status);
        if (U_FAILURE(status)) { return; }
        if (!outArray[pluralIndex].isBogus()) {
            // We already have a pattern
            return;
        }
        ResourceTable genderTable = value.getTable(status);
        ResourceTable caseTable; // This instance has to outlive `value`
        if (loadForPluralForm(genderTable, caseTable, value, status)) {
            outArray[pluralIndex] = value.getUnicodeString(status);
        }
    }

  private:
    // Tries to load data for the configured gender from `genderTable`. Returns
    // true if found, returning the data in `value`. The returned data will be
    // for the configured gender if found, falling back to "neuter" and
    // no-gender if not. The caseTable parameter holds the intermediate
    // ResourceTable for the sake of lifetime management.
    bool loadForPluralForm(const ResourceTable &genderTable,
                           ResourceTable &caseTable,
                           ResourceValue &value,
                           UErrorCode &status) {
        if (uprv_strcmp(gender, "") != 0) {
            if (loadForGender(genderTable, gender, caseTable, value, status)) {
                return true;
            }
            if (uprv_strcmp(gender, "neuter") != 0 &&
                loadForGender(genderTable, "neuter", caseTable, value, status)) {
                return true;
            }
        }
        if (loadForGender(genderTable, "_", caseTable, value, status)) {
            return true;
        }
        return false;
    }

    // Tries to load data for the given gender from `genderTable`. Returns true
    // if found, returning the data in `value`. The returned data will be for
    // the configured case if found, falling back to "nominative" and no-case if
    // not.
    bool loadForGender(const ResourceTable &genderTable,
                       const char *genderVal,
                       ResourceTable &caseTable,
                       ResourceValue &value,
                       UErrorCode &status) {
        if (!genderTable.findValue(genderVal, value)) {
            return false;
        }
        caseTable = value.getTable(status);
        if (uprv_strcmp(caseVariant, "") != 0) {
            if (loadForCase(caseTable, caseVariant, value)) {
                return true;
            }
            if (uprv_strcmp(caseVariant, "nominative") != 0 &&
                loadForCase(caseTable, "nominative", value)) {
                return true;
            }
        }
        if (loadForCase(caseTable, "_", value)) {
            return true;
        }
        return false;
    }

    // Tries to load data for the given case from `caseTable`. Returns true if
    // found, returning the data in `value`.
    bool loadForCase(const ResourceTable &caseTable, const char *caseValue, ResourceValue &value) {
        if (!caseTable.findValue(caseValue, value)) {
            return false;
        }
        return true;
    }

    const char *gender;
    const char *caseVariant;
    UnicodeString *outArray;
};

// Fetches localised formatting patterns for the given subKey. See documentation
// for InflectedPluralSink for details.
//
// Data is loaded for the appropriate unit width, with missing data filled in
// from unitsShort.
void getInflectedMeasureData(StringPiece subKey,
                             const Locale &locale,
                             const UNumberUnitWidth &width,
                             const char *gender,
                             const char *caseVariant,
                             UnicodeString *outArray,
                             UErrorCode &status) {
    InflectedPluralSink sink(gender, caseVariant, outArray);
    LocalUResourceBundlePointer unitsBundle(ures_open(U_ICUDATA_UNIT, locale.getName(), &status));
    if (U_FAILURE(status)) { return; }

    CharString key;
    key.append("units", status);
    if (width == UNUM_UNIT_WIDTH_NARROW) {
        key.append("Narrow", status);
    } else if (width == UNUM_UNIT_WIDTH_SHORT) {
        key.append("Short", status);
    }
    key.append("/", status);
    key.append(subKey, status);

    UErrorCode localStatus = status;
    ures_getAllChildrenWithFallback(unitsBundle.getAlias(), key.data(), sink, localStatus);
    if (width == UNUM_UNIT_WIDTH_SHORT) {
        status = localStatus;
        return;
    }
}

class PluralTableSink : public ResourceSink {
  public:
    // NOTE: outArray MUST have a length of at least ARRAY_LENGTH. No bounds
    // checking is performed.
    explicit PluralTableSink(UnicodeString *outArray) : outArray(outArray) {
        // Initialize the array to bogus strings.
        for (int32_t i = 0; i < ARRAY_LENGTH; i++) {
            outArray[i].setToBogus();
        }
    }

    void put(const char *key, ResourceValue &value, UBool /*noFallback*/, UErrorCode &status) U_OVERRIDE {
        if (uprv_strcmp(key, "case") == 0) {
            return;
        }
        int32_t index = getIndex(key, status);
        if (U_FAILURE(status)) { return; }
        if (!outArray[index].isBogus()) {
            return;
        }
        outArray[index] = value.getUnicodeString(status);
        if (U_FAILURE(status)) { return; }
    }

  private:
    UnicodeString *outArray;
};

/**
 * Populates outArray with `locale`-specific values for `unit` through use of
 * PluralTableSink. Only the set of basic units are supported!
 *
 * Reading from resources *unitsNarrow* and *unitsShort* (for width
 * UNUM_UNIT_WIDTH_NARROW), or just *unitsShort* (for width
 * UNUM_UNIT_WIDTH_SHORT). For other widths, it reads just "units".
 *
 * @param unit must be a built-in unit, i.e. must have a type and subtype,
 *     listed in gTypes and gSubTypes in measunit.cpp.
 * @param unitDisplayCase the empty string and "nominative" are treated the
 *     same. For other cases, strings for the requested case are used if found.
 *     (For any missing case-specific data, we fall back to nominative.)
 * @param outArray must be of fixed length ARRAY_LENGTH.
 */
void getMeasureData(const Locale &locale,
                    const MeasureUnit &unit,
                    const UNumberUnitWidth &width,
                    const char *unitDisplayCase,
                    UnicodeString *outArray,
                    UErrorCode &status) {
    PluralTableSink sink(outArray);
    LocalUResourceBundlePointer unitsBundle(ures_open(U_ICUDATA_UNIT, locale.getName(), &status));
    if (U_FAILURE(status)) { return; }

    CharString subKey;
    subKey.append("/", status);
    subKey.append(unit.getType(), status);
    subKey.append("/", status);

    // Check if unitSubType is an alias or not.
    LocalUResourceBundlePointer aliasBundle(ures_open(U_ICUDATA_ALIAS, "metadata", &status));

    UErrorCode aliasStatus = status;
    StackUResourceBundle aliasFillIn;
    CharString aliasKey;
    aliasKey.append("alias/unit/", aliasStatus);
    aliasKey.append(unit.getSubtype(), aliasStatus);
    aliasKey.append("/replacement", aliasStatus);
    ures_getByKeyWithFallback(aliasBundle.getAlias(), aliasKey.data(), aliasFillIn.getAlias(),
                              &aliasStatus);
    CharString unitSubType;
    if (!U_FAILURE(aliasStatus)) {
        // This means the subType is an alias. Then, replace unitSubType with the replacement.
        auto replacement = ures_getUnicodeString(aliasFillIn.getAlias(), &status);
        unitSubType.appendInvariantChars(replacement, status);
    } else {
        unitSubType.append(unit.getSubtype(), status);
    }

    // Map duration-year-person, duration-week-person, etc. to duration-year, duration-week, ...
    // TODO(ICU-20400): Get duration-*-person data properly with aliases.
    int32_t subtypeLen = static_cast<int32_t>(uprv_strlen(unitSubType.data()));
    if (subtypeLen > 7 && uprv_strcmp(unitSubType.data() + subtypeLen - 7, "-person") == 0) {
        subKey.append({unitSubType.data(), subtypeLen - 7}, status);
    } else {
        subKey.append({unitSubType.data(), subtypeLen}, status);
    }

    if (width != UNUM_UNIT_WIDTH_FULL_NAME) {
        UErrorCode localStatus = status;
        CharString genderKey;
        genderKey.append("units", localStatus);
        genderKey.append(subKey, localStatus);
        genderKey.append("/gender", localStatus);
        StackUResourceBundle fillIn;
        ures_getByKeyWithFallback(unitsBundle.getAlias(), genderKey.data(), fillIn.getAlias(),
                                  &localStatus);
        outArray[GENDER_INDEX] = ures_getUnicodeString(fillIn.getAlias(), &localStatus);
    }

    CharString key;
    key.append("units", status);
    if (width == UNUM_UNIT_WIDTH_NARROW) {
        key.append("Narrow", status);
    } else if (width == UNUM_UNIT_WIDTH_SHORT) {
        key.append("Short", status);
    }
    key.append(subKey, status);

    // Grab desired case first, if available. Then grab no-case data to fill in
    // the gaps.
    if (width == UNUM_UNIT_WIDTH_FULL_NAME && unitDisplayCase[0] != 0) {
        CharString caseKey;
        caseKey.append(key, status);
        caseKey.append("/case/", status);
        caseKey.append(unitDisplayCase, status);

        UErrorCode localStatus = U_ZERO_ERROR;
        // TODO(icu-units#138): our fallback logic is not spec-compliant:
        // lateral fallback should happen before locale fallback. Switch to
        // getInflectedMeasureData after homogenizing data format? Find a unit
        // test case that demonstrates the incorrect fallback logic (via
        // regional variant of an inflected language?)
        ures_getAllChildrenWithFallback(unitsBundle.getAlias(), caseKey.data(), sink, localStatus);
    }

    // TODO(icu-units#138): our fallback logic is not spec-compliant: we
    // check the given case, then go straight to the no-case data. The spec
    // states we should first look for case="nominative". As part of #138,
    // either get the spec changed, or add unit tests that warn us if
    // case="nominative" data differs from no-case data?
    UErrorCode localStatus = U_ZERO_ERROR;
    ures_getAllChildrenWithFallback(unitsBundle.getAlias(), key.data(), sink, localStatus);
    if (width == UNUM_UNIT_WIDTH_SHORT) {
        if (U_FAILURE(localStatus)) {
            status = localStatus;
        }
        return;
    }
}

// NOTE: outArray MUST have a length of at least ARRAY_LENGTH.
void getCurrencyLongNameData(const Locale &locale, const CurrencyUnit &currency, UnicodeString *outArray,
                             UErrorCode &status) {
    // In ICU4J, this method gets a CurrencyData from CurrencyData.provider.
    // TODO(ICU4J): Implement this without going through CurrencyData, like in ICU4C?
    PluralTableSink sink(outArray);
    LocalUResourceBundlePointer unitsBundle(ures_open(U_ICUDATA_CURR, locale.getName(), &status));
    if (U_FAILURE(status)) { return; }
    ures_getAllChildrenWithFallback(unitsBundle.getAlias(), "CurrencyUnitPatterns", sink, status);
    if (U_FAILURE(status)) { return; }
    for (int32_t i = 0; i < StandardPlural::Form::COUNT; i++) {
        UnicodeString &pattern = outArray[i];
        if (pattern.isBogus()) {
            continue;
        }
        int32_t longNameLen = 0;
        const char16_t *longName = ucurr_getPluralName(
                currency.getISOCurrency(),
                locale.getName(),
                nullptr /* isChoiceFormat */,
                StandardPlural::getKeyword(static_cast<StandardPlural::Form>(i)),
                &longNameLen,
                &status);
        // Example pattern from data: "{0} {1}"
        // Example output after find-and-replace: "{0} US dollars"
        pattern.findAndReplace(UnicodeString(u"{1}"), UnicodeString(longName, longNameLen));
    }
}

UnicodeString getCompoundValue(StringPiece compoundKey,
                               const Locale &locale,
                               const UNumberUnitWidth &width,
                               UErrorCode &status) {
    LocalUResourceBundlePointer unitsBundle(ures_open(U_ICUDATA_UNIT, locale.getName(), &status));
    if (U_FAILURE(status)) { return {}; }
    CharString key;
    key.append("units", status);
    if (width == UNUM_UNIT_WIDTH_NARROW) {
        key.append("Narrow", status);
    } else if (width == UNUM_UNIT_WIDTH_SHORT) {
        key.append("Short", status);
    }
    key.append("/compound/", status);
    key.append(compoundKey, status);

    UErrorCode localStatus = status;
    int32_t len = 0;
    const UChar *ptr =
        ures_getStringByKeyWithFallback(unitsBundle.getAlias(), key.data(), &len, &localStatus);
    if (U_FAILURE(localStatus) && width != UNUM_UNIT_WIDTH_SHORT) {
        // Fall back to short, which contains more compound data
        key.clear();
        key.append("unitsShort/compound/", status);
        key.append(compoundKey, status);
        ptr = ures_getStringByKeyWithFallback(unitsBundle.getAlias(), key.data(), &len, &status);
    } else {
        status = localStatus;
    }
    if (U_FAILURE(status)) {
        return {};
    }
    return UnicodeString(ptr, len);
}

/**
 * Loads and applies deriveComponent rules from CLDR's grammaticalFeatures.xml.
 *
 * Consider a deriveComponent rule that looks like this:
 *
 *     <deriveComponent feature="case" structure="per" value0="compound" value1="nominative"/>
 *
 * Instantiating an instance as follows:
 *
 *     DerivedComponents d(loc, "case", "per");
 *
 * Applying the rule in the XML element above, `d.value0("foo")` will be "foo",
 * and `d.value1("foo")` will be "nominative".
 *
 * The values returned by value0(...) and value1(...) are valid only while the
 * instance exists. In case of any kind of failure, value0(...) and value1(...)
 * will return "".
 */
class DerivedComponents {
  public:
    /**
     * Constructor.
     *
     * The feature and structure parameters must be null-terminated. The string
     * referenced by compoundValue must exist for longer than the
     * DerivedComponents instance.
     */
    DerivedComponents(const Locale &locale, const char *feature, const char *structure) {
        StackUResourceBundle derivationsBundle, stackBundle;
        ures_openDirectFillIn(derivationsBundle.getAlias(), NULL, "grammaticalFeatures", &status);
        ures_getByKey(derivationsBundle.getAlias(), "grammaticalData", derivationsBundle.getAlias(),
                      &status);
        ures_getByKey(derivationsBundle.getAlias(), "derivations", derivationsBundle.getAlias(),
                      &status);
        if (U_FAILURE(status)) {
            return;
        }
        UErrorCode localStatus = U_ZERO_ERROR;
        // TODO(icu-units#28): use standard normal locale resolution algorithms
        // rather than just grabbing language:
        ures_getByKey(derivationsBundle.getAlias(), locale.getLanguage(), stackBundle.getAlias(),
                      &localStatus);
        // TODO(icu-units#28):
        // - code currently assumes if the locale exists, the rules are there -
        //   instead of falling back to root when the requested rule is missing.
        // - investigate ures.h functions, see if one that uses res_findResource()
        //   might be better (or use res_findResource directly), or maybe help
        //   improve ures documentation to guide function selection?
        if (localStatus == U_MISSING_RESOURCE_ERROR) {
            ures_getByKey(derivationsBundle.getAlias(), "root", stackBundle.getAlias(), &status);
        } else {
            status = localStatus;
        }
        ures_getByKey(stackBundle.getAlias(), "component", stackBundle.getAlias(), &status);
        ures_getByKey(stackBundle.getAlias(), feature, stackBundle.getAlias(), &status);
        ures_getByKey(stackBundle.getAlias(), structure, stackBundle.getAlias(), &status);
        UnicodeString val0 = ures_getUnicodeStringByIndex(stackBundle.getAlias(), 0, &status);
        UnicodeString val1 = ures_getUnicodeStringByIndex(stackBundle.getAlias(), 1, &status);
        if (U_SUCCESS(status)) {
            if (val0.compare(UnicodeString(u"compound")) == 0) {
                compound0_ = true;
            } else {
                compound0_ = false;
                value0_.appendInvariantChars(val0, status);
            }
            if (val1.compare(UnicodeString(u"compound")) == 0) {
                compound1_ = true;
            } else {
                compound1_ = false;
                value1_.appendInvariantChars(val1, status);
            }
        }
    }

    // Returns a StringPiece that is only valid as long as the instance exists.
    StringPiece value0(const StringPiece compoundValue) const {
        return compound0_ ? compoundValue : value0_.toStringPiece();
    }

    // Returns a StringPiece that is only valid as long as the instance exists.
    StringPiece value1(const StringPiece compoundValue) const {
        return compound1_ ? compoundValue : value1_.toStringPiece();
    }

    // Returns a char* that is only valid as long as the instance exists.
    const char *value0(const char *compoundValue) const {
        return compound0_ ? compoundValue : value0_.data();
    }

    // Returns a char* that is only valid as long as the instance exists.
    const char *value1(const char *compoundValue) const {
        return compound1_ ? compoundValue : value1_.data();
    }

  private:
    UErrorCode status = U_ZERO_ERROR;

    // Holds strings referred to by value0 and value1;
    bool compound0_ = false, compound1_ = false;
    CharString value0_, value1_;
};

// TODO(icu-units#28): test somehow? Associate with an ICU ticket for adding
// testsuite support for testing with synthetic data?
/**
 * Loads and returns the value in rules that look like these:
 *
 * <deriveCompound feature="gender" structure="per" value="0"/>
 * <deriveCompound feature="gender" structure="times" value="1"/>
 *
 * Currently a fake example, but spec compliant:
 * <deriveCompound feature="gender" structure="power" value="feminine"/>
 *
 * NOTE: If U_FAILURE(status), returns an empty string.
 */ 
UnicodeString
getDeriveCompoundRule(Locale locale, const char *feature, const char *structure, UErrorCode &status) {
    StackUResourceBundle derivationsBundle, stackBundle;
    ures_openDirectFillIn(derivationsBundle.getAlias(), NULL, "grammaticalFeatures", &status);
    ures_getByKey(derivationsBundle.getAlias(), "grammaticalData", derivationsBundle.getAlias(),
                  &status);
    ures_getByKey(derivationsBundle.getAlias(), "derivations", derivationsBundle.getAlias(), &status);
    // TODO: use standard normal locale resolution algorithms rather than just grabbing language:
    ures_getByKey(derivationsBundle.getAlias(), locale.getLanguage(), stackBundle.getAlias(), &status);
    // TODO:
    // - code currently assumes if the locale exists, the rules are there -
    //   instead of falling back to root when the requested rule is missing.
    // - investigate ures.h functions, see if one that uses res_findResource()
    //   might be better (or use res_findResource directly), or maybe help
    //   improve ures documentation to guide function selection?
    if (status == U_MISSING_RESOURCE_ERROR) {
        status = U_ZERO_ERROR;
        ures_getByKey(derivationsBundle.getAlias(), "root", stackBundle.getAlias(), &status);
    }
    ures_getByKey(stackBundle.getAlias(), "compound", stackBundle.getAlias(), &status);
    ures_getByKey(stackBundle.getAlias(), feature, stackBundle.getAlias(), &status);
    UnicodeString uVal = ures_getUnicodeStringByKey(stackBundle.getAlias(), structure, &status);
    if (U_FAILURE(status)) {
        return {};
    }
    U_ASSERT(!uVal.isBogus());
    return uVal;
}

// Returns the gender string for structures following these rules:
//
// <deriveCompound feature="gender" structure="per" value="0"/>
// <deriveCompound feature="gender" structure="times" value="1"/>
//
// Fake example:
// <deriveCompound feature="gender" structure="power" value="feminine"/>
//
// data0 and data1 should be pattern arrays (UnicodeString[ARRAY_SIZE]) that
// correspond to value="0" and value="1".
//
// Pass a nullptr to data1 if the structure has no concept of value="1" (e.g.
// "prefix" doesn't).
UnicodeString getDerivedGender(Locale locale,
                               const char *structure,
                               UnicodeString *data0,
                               UnicodeString *data1,
                               UErrorCode &status) {
    UnicodeString val = getDeriveCompoundRule(locale, "gender", structure, status);
    if (val.length() == 1) {
        switch (val[0]) {
        case u'0':
            return data0[GENDER_INDEX];
        case u'1':
            if (data1 == nullptr) {
                return {};
            }
            return data1[GENDER_INDEX];
        }
    }
    return val;
}

////////////////////////
/// END DATA LOADING ///
////////////////////////

// TODO: promote this somewhere? It's based on patternprops.cpp' trimWhitespace
const UChar *trimSpaceChars(const UChar *s, int32_t &length) {
    if (length <= 0 || (!u_isJavaSpaceChar(s[0]) && !u_isJavaSpaceChar(s[length - 1]))) {
        return s;
    }
    int32_t start = 0;
    int32_t limit = length;
    while (start < limit && u_isJavaSpaceChar(s[start])) {
        ++start;
    }
    if (start < limit) {
        // There is non-white space at start; we will not move limit below that,
        // so we need not test start<limit in the loop.
        while (u_isJavaSpaceChar(s[limit - 1])) {
            --limit;
        }
    }
    length = limit - start;
    return s + start;
}

/**
 * Calculates the gender of an arbitrary unit: this is the *second*
 * implementation of an algorithm to do this:
 *
 * Gender is also calculated in "processPatternTimes": that code path is "bottom
 * up", loading the gender for every component of a compound unit (at the same
 * time as loading the Long Names formatting patterns), even if the gender is
 * unneeded, then combining the single units' genders into the compound unit's
 * gender, according to the rules. This algorithm does a lazier "top-down"
 * evaluation, starting with the compound unit, calculating which single unit's
 * gender is needed by breaking it down according to the rules, and then loading
 * only the gender of the one single unit who's gender is needed.
 *
 * For future refactorings:
 * 1. we could drop processPatternTimes' gender calculation and just call this
 *    function: for UNUM_UNIT_WIDTH_FULL_NAME, the unit gender is in the very
 *    same table as the formatting patterns, so loading it then may be
 *    efficient. For other unit widths however, it needs to be explicitly looked
 *    up anyway.
 * 2. alternatively, if CLDR is providing all the genders we need such that we
 *    don't need to calculate them in ICU anymore, we could drop this function
 *    and keep only processPatternTimes' calculation. (And optimise it a bit?)
 *
 * @param locale The desired locale.
 * @param unit The measure unit to calculate the gender for.
 * @return The gender string for the unit, or an empty string if unknown or
 *     ungendered.
 */
UnicodeString calculateGenderForUnit(const Locale &locale, const MeasureUnit &unit, UErrorCode &status) {
    MeasureUnitImpl impl;
    const MeasureUnitImpl& mui = MeasureUnitImpl::forMeasureUnit(unit, impl, status);
    int32_t singleUnitIndex = 0;
    if (mui.complexity == UMEASURE_UNIT_COMPOUND) {
        int32_t startSlice = 0;
        // inclusive
        int32_t endSlice = mui.singleUnits.length()-1;
        U_ASSERT(endSlice > 0); // Else it would not be COMPOUND
        if (mui.singleUnits[endSlice]->dimensionality < 0) {
            // We have a -per- construct
            UnicodeString perRule = getDeriveCompoundRule(locale, "gender", "per", status);
            if (perRule.length() != 1) {
                // Fixed gender for -per- units
                return perRule;
            }
            if (perRule[0] == u'1') {
                // Find the start of the denominator. We already know there is one.
                while (mui.singleUnits[startSlice]->dimensionality >= 0) {
                    startSlice++;
                }
            } else {
                // Find the end of the numerator
                while (endSlice >= 0 && mui.singleUnits[endSlice]->dimensionality < 0) {
                    endSlice--;
                }
                if (endSlice < 0) {
                    // We have only a denominator, e.g. "per-second".
                    // TODO(icu-units#28): find out what gender to use in the
                    // absence of a first value - mentioned in CLDR-14253.
                    return {};
                }
            }
        }
        if (endSlice > startSlice) {
            // We have a -times- construct
            UnicodeString timesRule = getDeriveCompoundRule(locale, "gender", "times", status);
            if (timesRule.length() != 1) {
                // Fixed gender for -times- units
                return timesRule;
            }
            if (timesRule[0] == u'0') {
                endSlice = startSlice;
            } else {
                // We assume timesRule[0] == u'1'
                startSlice = endSlice;
            }
        }
        U_ASSERT(startSlice == endSlice);
        singleUnitIndex = startSlice;
    } else if (mui.complexity == UMEASURE_UNIT_MIXED) {
        status = U_INTERNAL_PROGRAM_ERROR;
        return {};
    } else {
        U_ASSERT(mui.complexity == UMEASURE_UNIT_SINGLE);
        U_ASSERT(mui.singleUnits.length() == 1);
    }

    // Now we know which singleUnit's gender we want
    const SingleUnitImpl *singleUnit = mui.singleUnits[singleUnitIndex];
    // Check for any power-prefix gender override:
    if (std::abs(singleUnit->dimensionality) != 1) {
        UnicodeString powerRule = getDeriveCompoundRule(locale, "gender", "power", status);
        if (powerRule.length() != 1) {
            // Fixed gender for -powN- units
            return powerRule;
        }
        // powerRule[0] == u'0'; u'1' not currently in spec.
    }
    // Check for any SI and binary prefix gender override:
    if (std::abs(singleUnit->dimensionality) != 1) {
        UnicodeString prefixRule = getDeriveCompoundRule(locale, "gender", "prefix", status);
        if (prefixRule.length() != 1) {
            // Fixed gender for -powN- units
            return prefixRule;
        }
        // prefixRule[0] == u'0'; u'1' not currently in spec.
    }
    // Now we've boiled it down to the gender of one simple unit identifier:
    return getGenderForBuiltin(locale, MeasureUnit::forIdentifier(singleUnit->getSimpleUnitID(), status),
                               status);
}

void maybeCalculateGender(const Locale &locale,
                          const MeasureUnit &unitRef,
                          UnicodeString *outArray,
                          UErrorCode &status) {
    if (outArray[GENDER_INDEX].isBogus()) {
        UnicodeString meterGender = getGenderForBuiltin(locale, MeasureUnit::getMeter(), status);
        if (meterGender.isEmpty()) {
            // No gender for meter: assume ungendered language
            return;
        }
        // We have a gendered language, but are lacking gender for unitRef.
        outArray[GENDER_INDEX] = calculateGenderForUnit(locale, unitRef, status);
    }
}

} // namespace

void LongNameHandler::forMeasureUnit(const Locale &loc,
                                     const MeasureUnit &unitRef,
                                     const UNumberUnitWidth &width,
                                     const char *unitDisplayCase,
                                     const PluralRules *rules,
                                     const MicroPropsGenerator *parent,
                                     LongNameHandler *fillIn,
                                     UErrorCode &status) {
    // From https://unicode.org/reports/tr35/tr35-general.html#compound-units -
    // Points 1 and 2 are mostly handled by MeasureUnit:
    //
    // 1. If the unitId is empty or invalid, fail
    // 2. Put the unitId into normalized order
    U_ASSERT(fillIn != nullptr);

    if (uprv_strcmp(unitRef.getType(), "") != 0) {
        // Handling built-in units:
        //
        // 3. Set result to be getValue(unitId with length, pluralCategory, caseVariant)
        //    - If result is not empty, return it
        UnicodeString simpleFormats[ARRAY_LENGTH];
        getMeasureData(loc, unitRef, width, unitDisplayCase, simpleFormats, status);
        maybeCalculateGender(loc, unitRef, simpleFormats, status);
        if (U_FAILURE(status)) {
            return;
        }
        fillIn->rules = rules;
        fillIn->parent = parent;
        fillIn->simpleFormatsToModifiers(simpleFormats,
                                         {UFIELD_CATEGORY_NUMBER, UNUM_MEASURE_UNIT_FIELD}, status);
        if (!simpleFormats[GENDER_INDEX].isBogus()) {
            fillIn->gender = getGenderString(simpleFormats[GENDER_INDEX], status);
        }
        return;

        // TODO(icu-units#145): figure out why this causes a failure in
        // format/MeasureFormatTest/TestIndividualPluralFallback and other
        // tests, when it should have been an alternative for the lines above:

        // forArbitraryUnit(loc, unitRef, width, unitDisplayCase, fillIn, status);
        // fillIn->rules = rules;
        // fillIn->parent = parent;
        // return;
    } else {
        // Check if it is a MeasureUnit this constructor handles: this
        // constructor does not handle mixed units
        U_ASSERT(unitRef.getComplexity(status) != UMEASURE_UNIT_MIXED);
        forArbitraryUnit(loc, unitRef, width, unitDisplayCase, fillIn, status);
        fillIn->rules = rules;
        fillIn->parent = parent;
        return;
    }
}

void LongNameHandler::forArbitraryUnit(const Locale &loc,
                                       const MeasureUnit &unitRef,
                                       const UNumberUnitWidth &width,
                                       const char *unitDisplayCase,
                                       LongNameHandler *fillIn,
                                       UErrorCode &status) {
    if (U_FAILURE(status)) {
        return;
    }
    if (fillIn == nullptr) {
        status = U_INTERNAL_PROGRAM_ERROR;
        return;
    }

    // Numbered list items are from the algorithms at
    // https://unicode.org/reports/tr35/tr35-general.html#compound-units:
    //
    // 4. Divide the unitId into numerator (the part before the "-per-") and
    //    denominator (the part after the "-per-). If both are empty, fail
    MeasureUnitImpl unit;
    MeasureUnitImpl perUnit;
    {
        MeasureUnitImpl fullUnit = MeasureUnitImpl::forMeasureUnitMaybeCopy(unitRef, status);
        if (U_FAILURE(status)) {
            return;
        }
        for (int32_t i = 0; i < fullUnit.singleUnits.length(); i++) {
            SingleUnitImpl *subUnit = fullUnit.singleUnits[i];
            if (subUnit->dimensionality > 0) {
                unit.appendSingleUnit(*subUnit, status);
            } else {
                subUnit->dimensionality *= -1;
                perUnit.appendSingleUnit(*subUnit, status);
            }
        }
    }

    // TODO(icu-units#28): check placeholder logic, see if it needs to be
    // present here instead of only in processPatternTimes:
    //
    // 5. Set both globalPlaceholder and globalPlaceholderPosition to be empty

    DerivedComponents derivedPerCases(loc, "case", "per");

    // 6. numeratorUnitString
    UnicodeString numeratorUnitData[ARRAY_LENGTH];
    processPatternTimes(std::move(unit), loc, width, derivedPerCases.value0(unitDisplayCase),
                        numeratorUnitData, status);

    // 7. denominatorUnitString
    UnicodeString denominatorUnitData[ARRAY_LENGTH];
    processPatternTimes(std::move(perUnit), loc, width, derivedPerCases.value1(unitDisplayCase),
                        denominatorUnitData, status);

    // TODO(icu-units#139):
    // - implement DerivedComponents for "plural/times" and "plural/power":
    //   French has different rules, we'll be producing the wrong results
    //   currently. (Prove via tests!)
    // - implement DerivedComponents for "plural/per", "plural/prefix",
    //   "case/times", "case/power", and "case/prefix" - although they're
    //   currently hardcoded. Languages with different rules are surely on the
    //   way.
    //
    // Currently we only use "case/per", "plural/times", "case/times", and
    // "case/power".
    //
    // This may have impact on multiSimpleFormatsToModifiers(...) below too?
    // These rules are currently (ICU 69) all the same and hard-coded below.
    UnicodeString perUnitPattern;
    if (!denominatorUnitData[PER_INDEX].isBogus()) {
        // If we have no denominator, we obtain the empty string:
        perUnitPattern = denominatorUnitData[PER_INDEX];
    } else {
        // 8. Set perPattern to be getValue([per], locale, length)
        UnicodeString rawPerUnitFormat = getCompoundValue("per", loc, width, status);
        // rawPerUnitFormat is something like "{0} per {1}"; we need to substitute in the secondary unit.
        SimpleFormatter perPatternFormatter(rawPerUnitFormat, 2, 2, status);
        if (U_FAILURE(status)) {
            return;
        }
        // Plural and placeholder handling for 7. denominatorUnitString:
        // TODO(icu-units#139): hardcoded:
        // <deriveComponent feature="plural" structure="per" value0="compound" value1="one"/>
        UnicodeString denominatorFormat =
            getWithPlural(denominatorUnitData, StandardPlural::Form::ONE, status);
        // Some "one" pattern may not contain "{0}". For example in "ar" or "ne" locale.
        SimpleFormatter denominatorFormatter(denominatorFormat, 0, 1, status);
        if (U_FAILURE(status)) {
            return;
        }
        UnicodeString denominatorPattern = denominatorFormatter.getTextWithNoArguments();
        int32_t trimmedLen = denominatorPattern.length();
        const UChar *trimmed = trimSpaceChars(denominatorPattern.getBuffer(), trimmedLen);
        UnicodeString denominatorString(false, trimmed, trimmedLen);
        // 9. If the denominatorString is empty, set result to
        //    [numeratorString], otherwise set result to format(perPattern,
        //    numeratorString, denominatorString)
        //
        // TODO(icu-units#28): Why does UnicodeString need to be explicit in the
        // following line?
        perPatternFormatter.format(UnicodeString(u"{0}"), denominatorString, perUnitPattern, status);
        if (U_FAILURE(status)) {
            return;
        }
    }
    if (perUnitPattern.length() == 0) {
        fillIn->simpleFormatsToModifiers(numeratorUnitData,
                                         {UFIELD_CATEGORY_NUMBER, UNUM_MEASURE_UNIT_FIELD}, status);
    } else {
        fillIn->multiSimpleFormatsToModifiers(numeratorUnitData, perUnitPattern,
                                              {UFIELD_CATEGORY_NUMBER, UNUM_MEASURE_UNIT_FIELD}, status);
    }

    // Gender
    //
    // TODO(icu-units#28): find out what gender to use in the absence of a first
    // value - e.g. what's the gender of "per-second"? Mentioned in CLDR-14253.
    //
    // gender/per deriveCompound rules don't say:
    // <deriveCompound feature="gender" structure="per" value="0"/> <!-- gender(gram-per-meter) ←  gender(gram) -->
    fillIn->gender = getGenderString(
        getDerivedGender(loc, "per", numeratorUnitData, denominatorUnitData, status), status);
}

void LongNameHandler::processPatternTimes(MeasureUnitImpl &&productUnit,
                                          Locale loc,
                                          const UNumberUnitWidth &width,
                                          const char *caseVariant,
                                          UnicodeString *outArray,
                                          UErrorCode &status) {
    if (U_FAILURE(status)) {
        return;
    }
    if (productUnit.complexity == UMEASURE_UNIT_MIXED) {
        // These are handled by MixedUnitLongNameHandler
        status = U_UNSUPPORTED_ERROR;
        return;
    }

#if U_DEBUG
    for (int32_t pluralIndex = 0; pluralIndex < ARRAY_LENGTH; pluralIndex++) {
        U_ASSERT(outArray[pluralIndex].length() == 0);
        U_ASSERT(!outArray[pluralIndex].isBogus());
    }
#endif

    if (productUnit.identifier.isEmpty()) {
        // TODO(icu-units#28): consider when serialize should be called.
        // identifier might also be empty for MeasureUnit().
        productUnit.serialize(status);
    }
    if (U_FAILURE(status)) {
        return;
    }
    if (productUnit.identifier.length() == 0) {
        // MeasureUnit(): no units: return empty strings.
        return;
    }

    MeasureUnit builtinUnit;
    if (MeasureUnit::findBySubType(productUnit.identifier.toStringPiece(), &builtinUnit)) {
        // TODO(icu-units#145): spec doesn't cover builtin-per-builtin, it
        // breaks them all down. Do we want to drop this?
        // - findBySubType isn't super efficient, if we skip it and go to basic
        //   singles, we don't have to construct MeasureUnit's anymore.
        // - Check all the existing unit tests that fail without this: is it due
        //   to incorrect fallback via getMeasureData?
        // - Do those unit tests cover this code path representatively?
        if (builtinUnit != MeasureUnit()) {
            getMeasureData(loc, builtinUnit, width, caseVariant, outArray, status);
            maybeCalculateGender(loc, builtinUnit, outArray, status);
        }
        return;
    }

    // 2. Set timesPattern to be getValue(times, locale, length)
    UnicodeString timesPattern = getCompoundValue("times", loc, width, status);
    SimpleFormatter timesPatternFormatter(timesPattern, 2, 2, status);
    if (U_FAILURE(status)) {
        return;
    }

    PlaceholderPosition globalPlaceholder[ARRAY_LENGTH];
    UChar globalJoinerChar = 0;
    // Numbered list items are from the algorithms at
    // https://unicode.org/reports/tr35/tr35-general.html#compound-units:
    //
    // pattern(...) point 5:
    // - Set both globalPlaceholder and globalPlaceholderPosition to be empty
    //
    // 3. Set result to be empty
    for (int32_t pluralIndex = 0; pluralIndex < ARRAY_LENGTH; pluralIndex++) {
        // Initial state: empty string pattern, via all falling back to OTHER:
        if (pluralIndex == StandardPlural::Form::OTHER) {
            outArray[pluralIndex].remove();
        } else {
            outArray[pluralIndex].setToBogus();
        }
        globalPlaceholder[pluralIndex] = PH_EMPTY;
    }

    // Empty string represents "compound" (propagate the plural form).
    const char *pluralCategory = "";
    DerivedComponents derivedTimesPlurals(loc, "plural", "times");
    DerivedComponents derivedTimesCases(loc, "case", "times");
    DerivedComponents derivedPowerCases(loc, "case", "power");

    // 4. For each single_unit in product_unit
    for (int32_t singleUnitIndex = 0; singleUnitIndex < productUnit.singleUnits.length();
         singleUnitIndex++) {
        SingleUnitImpl *singleUnit = productUnit.singleUnits[singleUnitIndex];
        const char *singlePluralCategory;
        const char *singleCaseVariant;
        // TODO(icu-units#28): ensure we have unit tests that change/fail if we
        // assign incorrect case variants here:
        if (singleUnitIndex < productUnit.singleUnits.length() - 1) {
            // 4.1. If hasMultiple
            singlePluralCategory = derivedTimesPlurals.value0(pluralCategory);
            singleCaseVariant = derivedTimesCases.value0(caseVariant);
            pluralCategory = derivedTimesPlurals.value1(pluralCategory);
            caseVariant = derivedTimesCases.value1(caseVariant);
        } else {
            singlePluralCategory = derivedTimesPlurals.value1(pluralCategory);
            singleCaseVariant = derivedTimesCases.value1(caseVariant);
        }

        // 4.2. Get the gender of that single_unit
        MeasureUnit simpleUnit;
        if (!MeasureUnit::findBySubType(singleUnit->getSimpleUnitID(), &simpleUnit)) {
            // Ideally all simple units should be known, but they're not:
            // 100-kilometer is internally treated as a simple unit, but it is
            // not a built-in unit and does not have formatting data in CLDR 39.
            //
            // TODO(icu-units#28): test (desirable) invariants in unit tests.
            status = U_UNSUPPORTED_ERROR;
            return;
        }
        const char *gender = getGenderString(getGenderForBuiltin(loc, simpleUnit, status), status);

        // 4.3. If singleUnit starts with a dimensionality_prefix, such as 'square-'
        U_ASSERT(singleUnit->dimensionality > 0);
        int32_t dimensionality = singleUnit->dimensionality;
        UnicodeString dimensionalityPrefixPatterns[ARRAY_LENGTH];
        if (dimensionality != 1) {
            // 4.3.1. set dimensionalityPrefixPattern to be
            //   getValue(that dimensionality_prefix, locale, length, singlePluralCategory, singleCaseVariant, gender),
            //   such as "{0} kwadratowym"
            CharString dimensionalityKey("compound/power", status);
            dimensionalityKey.appendNumber(dimensionality, status);
            getInflectedMeasureData(dimensionalityKey.toStringPiece(), loc, width, gender,
                                    singleCaseVariant, dimensionalityPrefixPatterns, status);
            if (U_FAILURE(status)) {
                // At the time of writing, only pow2 and pow3 are supported.
                // Attempting to format other powers results in a
                // U_RESOURCE_TYPE_MISMATCH. We convert the error if we
                // understand it:
                if (status == U_RESOURCE_TYPE_MISMATCH && dimensionality > 3) {
                    status = U_UNSUPPORTED_ERROR;
                }
                return;
            }

            // TODO(icu-units#139):
            // 4.3.2. set singlePluralCategory to be power0(singlePluralCategory)

            // 4.3.3. set singleCaseVariant to be power0(singleCaseVariant)
            singleCaseVariant = derivedPowerCases.value0(singleCaseVariant);
            // 4.3.4. remove the dimensionality_prefix from singleUnit
            singleUnit->dimensionality = 1;
        }

        // 4.4. if singleUnit starts with an si_prefix, such as 'centi'
        UMeasurePrefix prefix = singleUnit->unitPrefix;
        UnicodeString prefixPattern;
        if (prefix != UMEASURE_PREFIX_ONE) {
            // 4.4.1. set siPrefixPattern to be getValue(that si_prefix, locale,
            //        length), such as "centy{0}"
            CharString prefixKey;
            // prefixKey looks like "1024p3" or "10p-2":
            prefixKey.appendNumber(umeas_getPrefixBase(prefix), status);
            prefixKey.append('p', status);
            prefixKey.appendNumber(umeas_getPrefixPower(prefix), status);
            // Contains a pattern like "centy{0}".
            prefixPattern = getCompoundValue(prefixKey.toStringPiece(), loc, width, status);

            // 4.4.2. set singlePluralCategory to be prefix0(singlePluralCategory)
            //
            // TODO(icu-units#139): that refers to these rules:
            // <deriveComponent feature="plural" structure="prefix" value0="one" value1="compound"/>
            // though I'm not sure what other value they might end up having.
            //
            // 4.4.3. set singleCaseVariant to be prefix0(singleCaseVariant)
            //
            // TODO(icu-units#139): that refers to:
            // <deriveComponent feature="case" structure="prefix" value0="nominative"
            // value1="compound"/> but the prefix (value0) doesn't have case, the rest simply
            // propagates.

            // 4.4.4. remove the si_prefix from singleUnit
            singleUnit->unitPrefix = UMEASURE_PREFIX_ONE;
        }

        // 4.5. Set corePattern to be the getValue(singleUnit, locale, length,
        //      singlePluralCategory, singleCaseVariant), such as "{0} metrem"
        UnicodeString singleUnitArray[ARRAY_LENGTH];
        // At this point we are left with a Simple Unit:
        U_ASSERT(uprv_strcmp(singleUnit->build(status).getIdentifier(), singleUnit->getSimpleUnitID()) ==
                 0);
        getMeasureData(loc, singleUnit->build(status), width, singleCaseVariant, singleUnitArray,
                       status);
        if (U_FAILURE(status)) {
            // Shouldn't happen if we have data for all single units
            return;
        }

        // Calculate output gender
        if (!singleUnitArray[GENDER_INDEX].isBogus()) {
            U_ASSERT(!singleUnitArray[GENDER_INDEX].isEmpty());
            UnicodeString uVal;

            if (prefix != UMEASURE_PREFIX_ONE) {
                singleUnitArray[GENDER_INDEX] =
                    getDerivedGender(loc, "prefix", singleUnitArray, nullptr, status);
            }

            if (dimensionality != 1) {
                singleUnitArray[GENDER_INDEX] =
                    getDerivedGender(loc, "power", singleUnitArray, nullptr, status);
            }

            UnicodeString timesGenderRule = getDeriveCompoundRule(loc, "gender", "times", status);
            if (timesGenderRule.length() == 1) {
                switch (timesGenderRule[0]) {
                case u'0':
                    if (singleUnitIndex == 0) {
                        U_ASSERT(outArray[GENDER_INDEX].isBogus());
                        outArray[GENDER_INDEX] = singleUnitArray[GENDER_INDEX];
                    }
                    break;
                case u'1':
                    if (singleUnitIndex == productUnit.singleUnits.length() - 1) {
                        U_ASSERT(outArray[GENDER_INDEX].isBogus());
                        outArray[GENDER_INDEX] = singleUnitArray[GENDER_INDEX];
                    }
                }
            } else {
                if (outArray[GENDER_INDEX].isBogus()) {
                    outArray[GENDER_INDEX] = timesGenderRule;
                }
            }
        }

        // Calculate resulting patterns for each plural form
        for (int32_t pluralIndex = 0; pluralIndex < StandardPlural::Form::COUNT; pluralIndex++) {
            StandardPlural::Form plural = static_cast<StandardPlural::Form>(pluralIndex);

            // singleUnitArray[pluralIndex] looks something like "{0} Meter"
            if (outArray[pluralIndex].isBogus()) {
                if (singleUnitArray[pluralIndex].isBogus()) {
                    // Let the usual plural fallback mechanism take care of this
                    // plural form
                    continue;
                } else {
                    // Since our singleUnit can have a plural form that outArray
                    // doesn't yet have (relying on fallback to OTHER), we start
                    // by grabbing it with the normal plural fallback mechanism
                    outArray[pluralIndex] = getWithPlural(outArray, plural, status);
                    if (U_FAILURE(status)) {
                        return;
                    }
                }
            }

            if (uprv_strcmp(singlePluralCategory, "") != 0) {
                plural = static_cast<StandardPlural::Form>(getIndex(singlePluralCategory, status));
            }

            // 4.6. Extract(corePattern, coreUnit, placeholder, placeholderPosition) from that pattern.
            UnicodeString coreUnit;
            PlaceholderPosition placeholderPosition;
            UChar joinerChar;
            extractCorePattern(getWithPlural(singleUnitArray, plural, status), coreUnit,
                               placeholderPosition, joinerChar);

            // 4.7 If the position is middle, then fail
            if (placeholderPosition == PH_MIDDLE) {
                status = U_UNSUPPORTED_ERROR;
                return;
            }

            // 4.8. If globalPlaceholder is empty
            if (globalPlaceholder[pluralIndex] == PH_EMPTY) {
                globalPlaceholder[pluralIndex] = placeholderPosition;
                globalJoinerChar = joinerChar;
            } else {
                // Expect all units involved to have the same placeholder position
                U_ASSERT(globalPlaceholder[pluralIndex] == placeholderPosition);
                // TODO(icu-units#28): Do we want to add a unit test that checks
                // for consistent joiner chars? Probably not, given how
                // inconsistent they are. File a CLDR ticket with examples?
            }
            // Now coreUnit would be just "Meter"

            // 4.9. If siPrefixPattern is not empty
            if (prefix != UMEASURE_PREFIX_ONE) {
                SimpleFormatter prefixCompiled(prefixPattern, 1, 1, status);
                if (U_FAILURE(status)) {
                    return;
                }

                // 4.9.1. Set coreUnit to be the combineLowercasing(locale, length, siPrefixPattern,
                //        coreUnit)
                UnicodeString tmp;
                // combineLowercasing(locale, length, prefixPattern, coreUnit)
                //
                // TODO(icu-units#28): run this only if prefixPattern does not
                // contain space characters - do languages "as", "bn", "hi",
                // "kk", etc have concepts of upper and lower case?:
                if (width == UNUM_UNIT_WIDTH_FULL_NAME) {
                    coreUnit.toLower(loc);
                }
                prefixCompiled.format(coreUnit, tmp, status);
                if (U_FAILURE(status)) {
                    return;
                }
                coreUnit = tmp;
            }

            // 4.10. If dimensionalityPrefixPattern is not empty
            if (dimensionality != 1) {
                SimpleFormatter dimensionalityCompiled(
                    getWithPlural(dimensionalityPrefixPatterns, plural, status), 1, 1, status);
                if (U_FAILURE(status)) {
                    return;
                }

                // 4.10.1. Set coreUnit to be the combineLowercasing(locale, length,
                //         dimensionalityPrefixPattern, coreUnit)
                UnicodeString tmp;
                // combineLowercasing(locale, length, prefixPattern, coreUnit)
                //
                // TODO(icu-units#28): run this only if prefixPattern does not
                // contain space characters - do languages "as", "bn", "hi",
                // "kk", etc have concepts of upper and lower case?:
                if (width == UNUM_UNIT_WIDTH_FULL_NAME) {
                    coreUnit.toLower(loc);
                }
                dimensionalityCompiled.format(coreUnit, tmp, status);
                if (U_FAILURE(status)) {
                    return;
                }
                coreUnit = tmp;
            }

            if (outArray[pluralIndex].length() == 0) {
                // 4.11. If the result is empty, set result to be coreUnit
                outArray[pluralIndex] = coreUnit;
            } else {
                // 4.12. Otherwise set result to be format(timesPattern, result, coreUnit)
                UnicodeString tmp;
                timesPatternFormatter.format(outArray[pluralIndex], coreUnit, tmp, status);
                outArray[pluralIndex] = tmp;
            }
        }
    }
    for (int32_t pluralIndex = 0; pluralIndex < StandardPlural::Form::COUNT; pluralIndex++) {
        if (globalPlaceholder[pluralIndex] == PH_BEGINNING) {
            UnicodeString tmp;
            tmp.append(u"{0}", 3);
            if (globalJoinerChar != 0) {
                tmp.append(globalJoinerChar);
            }
            tmp.append(outArray[pluralIndex]);
            outArray[pluralIndex] = tmp;
        } else if (globalPlaceholder[pluralIndex] == PH_END) {
            if (globalJoinerChar != 0) {
                outArray[pluralIndex].append(globalJoinerChar);
            }
            outArray[pluralIndex].append(u"{0}", 3);
        }
    }
}

UnicodeString LongNameHandler::getUnitDisplayName(
        const Locale& loc,
        const MeasureUnit& unit,
        UNumberUnitWidth width,
        UErrorCode& status) {
    if (U_FAILURE(status)) {
        return ICU_Utility::makeBogusString();
    }
    UnicodeString simpleFormats[ARRAY_LENGTH];
    getMeasureData(loc, unit, width, "", simpleFormats, status);
    return simpleFormats[DNAM_INDEX];
}

UnicodeString LongNameHandler::getUnitPattern(
        const Locale& loc,
        const MeasureUnit& unit,
        UNumberUnitWidth width,
        StandardPlural::Form pluralForm,
        UErrorCode& status) {
    if (U_FAILURE(status)) {
        return ICU_Utility::makeBogusString();
    }
    UnicodeString simpleFormats[ARRAY_LENGTH];
    getMeasureData(loc, unit, width, "", simpleFormats, status);
    // The above already handles fallback from other widths to short
    if (U_FAILURE(status)) {
        return ICU_Utility::makeBogusString();
    }
    // Now handle fallback from other plural forms to OTHER
    return (!(simpleFormats[pluralForm]).isBogus())? simpleFormats[pluralForm]:
            simpleFormats[StandardPlural::Form::OTHER];
}

LongNameHandler* LongNameHandler::forCurrencyLongNames(const Locale &loc, const CurrencyUnit &currency,
                                                      const PluralRules *rules,
                                                      const MicroPropsGenerator *parent,
                                                      UErrorCode &status) {
    auto* result = new LongNameHandler(rules, parent);
    if (result == nullptr) {
        status = U_MEMORY_ALLOCATION_ERROR;
        return nullptr;
    }
    UnicodeString simpleFormats[ARRAY_LENGTH];
    getCurrencyLongNameData(loc, currency, simpleFormats, status);
    if (U_FAILURE(status)) { return nullptr; }
    result->simpleFormatsToModifiers(simpleFormats, {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}, status);
    // TODO(icu-units#28): currency gender?
    return result;
}

void LongNameHandler::simpleFormatsToModifiers(const UnicodeString *simpleFormats, Field field,
                                               UErrorCode &status) {
    for (int32_t i = 0; i < StandardPlural::Form::COUNT; i++) {
        StandardPlural::Form plural = static_cast<StandardPlural::Form>(i);
        UnicodeString simpleFormat = getWithPlural(simpleFormats, plural, status);
        if (U_FAILURE(status)) { return; }
        SimpleFormatter compiledFormatter(simpleFormat, 0, 1, status);
        if (U_FAILURE(status)) { return; }
        fModifiers[i] = SimpleModifier(compiledFormatter, field, false, {this, SIGNUM_POS_ZERO, plural});
    }
}

void LongNameHandler::multiSimpleFormatsToModifiers(const UnicodeString *leadFormats, UnicodeString trailFormat,
                                                    Field field, UErrorCode &status) {
    SimpleFormatter trailCompiled(trailFormat, 1, 1, status);
    if (U_FAILURE(status)) { return; }
    for (int32_t i = 0; i < StandardPlural::Form::COUNT; i++) {
        StandardPlural::Form plural = static_cast<StandardPlural::Form>(i);
        UnicodeString leadFormat = getWithPlural(leadFormats, plural, status);
        if (U_FAILURE(status)) { return; }
        UnicodeString compoundFormat;
        if (leadFormat.length() == 0) {
            compoundFormat = trailFormat;
        } else {
            trailCompiled.format(leadFormat, compoundFormat, status);
            if (U_FAILURE(status)) { return; }
        }
        SimpleFormatter compoundCompiled(compoundFormat, 0, 1, status);
        if (U_FAILURE(status)) { return; }
        fModifiers[i] = SimpleModifier(compoundCompiled, field, false, {this, SIGNUM_POS_ZERO, plural});
    }
}

void LongNameHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micros,
                                      UErrorCode &status) const {
    if (parent != NULL) {
        parent->processQuantity(quantity, micros, status);
    }
    StandardPlural::Form pluralForm = utils::getPluralSafe(micros.rounder, rules, quantity, status);
    micros.modOuter = &fModifiers[pluralForm];
    micros.gender = gender;
}

const Modifier* LongNameHandler::getModifier(Signum /*signum*/, StandardPlural::Form plural) const {
    return &fModifiers[plural];
}

void MixedUnitLongNameHandler::forMeasureUnit(const Locale &loc,
                                              const MeasureUnit &mixedUnit,
                                              const UNumberUnitWidth &width,
                                              const char *unitDisplayCase,
                                              const PluralRules *rules,
                                              const MicroPropsGenerator *parent,
                                              MixedUnitLongNameHandler *fillIn,
                                              UErrorCode &status) {
    U_ASSERT(mixedUnit.getComplexity(status) == UMEASURE_UNIT_MIXED);
    U_ASSERT(fillIn != nullptr);
    if (U_FAILURE(status)) {
        return;
    }

    MeasureUnitImpl temp;
    const MeasureUnitImpl &impl = MeasureUnitImpl::forMeasureUnit(mixedUnit, temp, status);
    // Defensive, for production code:
    if (impl.complexity != UMEASURE_UNIT_MIXED) {
        // Should be using the normal LongNameHandler
        status = U_UNSUPPORTED_ERROR;
        return;
    }

    fillIn->fMixedUnitCount = impl.singleUnits.length();
    fillIn->fMixedUnitData.adoptInstead(new UnicodeString[fillIn->fMixedUnitCount * ARRAY_LENGTH]);
    for (int32_t i = 0; i < fillIn->fMixedUnitCount; i++) {
        // Grab data for each of the components.
        UnicodeString *unitData = &fillIn->fMixedUnitData[i * ARRAY_LENGTH];
        // TODO(CLDR-14502): check from the CLDR-14502 ticket whether this
        // propagation of unitDisplayCase is correct:
        getMeasureData(loc, impl.singleUnits[i]->build(status), width, unitDisplayCase, unitData,
                       status);
        // TODO(ICU-21494): if we add support for gender for mixed units, we may
        // need maybeCalculateGender() here.
    }

    // TODO(icu-units#120): Make sure ICU doesn't output zero-valued
    // high-magnitude fields
    // * for mixed units count N, produce N listFormatters, one for each subset
    //   that might be formatted.
    UListFormatterWidth listWidth = ULISTFMT_WIDTH_SHORT;
    if (width == UNUM_UNIT_WIDTH_NARROW) {
        listWidth = ULISTFMT_WIDTH_NARROW;
    } else if (width == UNUM_UNIT_WIDTH_FULL_NAME) {
        // This might be the same as SHORT in most languages:
        listWidth = ULISTFMT_WIDTH_WIDE;
    }
    fillIn->fListFormatter.adoptInsteadAndCheckErrorCode(
        ListFormatter::createInstance(loc, ULISTFMT_TYPE_UNITS, listWidth, status), status);
    // TODO(ICU-21494): grab gender of each unit, calculate the gender
    // associated with this list formatter, save it for later.
    fillIn->rules = rules;
    fillIn->parent = parent;

    // We need a localised NumberFormatter for the numbers of the bigger units
    // (providing Arabic numerals, for example).
    fillIn->fNumberFormatter = NumberFormatter::withLocale(loc);
}

void MixedUnitLongNameHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micros,
                                               UErrorCode &status) const {
    U_ASSERT(fMixedUnitCount > 1);
    if (parent != nullptr) {
        parent->processQuantity(quantity, micros, status);
    }
    micros.modOuter = getMixedUnitModifier(quantity, micros, status);
}

const Modifier *MixedUnitLongNameHandler::getMixedUnitModifier(DecimalQuantity &quantity,
                                                               MicroProps &micros,
                                                               UErrorCode &status) const {
    if (micros.mixedMeasuresCount == 0) {
        U_ASSERT(micros.mixedMeasuresCount > 0); // Mixed unit: we must have more than one unit value
        status = U_UNSUPPORTED_ERROR;
        return &micros.helpers.emptyWeakModifier;
    }

    // Algorithm:
    //
    // For the mixed-units measurement of: "3 yard, 1 foot, 2.6 inch", we should
    // find "3 yard" and "1 foot" in micros.mixedMeasures.
    //
    // Obtain long-names with plural forms corresponding to measure values:
    //   * {0} yards, {0} foot, {0} inches
    //
    // Format the integer values appropriately and modify with the format
    // strings:
    //   - 3 yards, 1 foot
    //
    // Use ListFormatter to combine, with one placeholder:
    //   - 3 yards, 1 foot and {0} inches
    //
    // Return a SimpleModifier for this pattern, letting the rest of the
    // pipeline take care of the remaining inches.

    LocalArray<UnicodeString> outputMeasuresList(new UnicodeString[fMixedUnitCount], status);
    if (U_FAILURE(status)) {
        return &micros.helpers.emptyWeakModifier;
    }

    StandardPlural::Form quantityPlural = StandardPlural::Form::OTHER;
    for (int32_t i = 0; i < micros.mixedMeasuresCount; i++) {
        DecimalQuantity fdec;

        // If numbers are negative, only the first number needs to have its
        // negative sign formatted.
        int64_t number = i > 0 ? std::abs(micros.mixedMeasures[i]) : micros.mixedMeasures[i];

        if (micros.indexOfQuantity == i) { // Insert placeholder for `quantity`
            // If quantity is not the first value and quantity is negative
            if (micros.indexOfQuantity > 0 && quantity.isNegative()) {
                quantity.negate();
            }

            StandardPlural::Form quantityPlural =
                utils::getPluralSafe(micros.rounder, rules, quantity, status);
            UnicodeString quantityFormatWithPlural =
                getWithPlural(&fMixedUnitData[i * ARRAY_LENGTH], quantityPlural, status);
            SimpleFormatter quantityFormatter(quantityFormatWithPlural, 0, 1, status);
            quantityFormatter.format(UnicodeString(u"{0}"), outputMeasuresList[i], status);
        } else {
            fdec.setToLong(number);
            StandardPlural::Form pluralForm = utils::getStandardPlural(rules, fdec);
            UnicodeString simpleFormat =
                getWithPlural(&fMixedUnitData[i * ARRAY_LENGTH], pluralForm, status);
            SimpleFormatter compiledFormatter(simpleFormat, 0, 1, status);
            UnicodeString num;
            auto appendable = UnicodeStringAppendable(num);

            fNumberFormatter.formatDecimalQuantity(fdec, status).appendTo(appendable, status);
            compiledFormatter.format(num, outputMeasuresList[i], status);
        }
    }

    // TODO(ICU-21494): implement gender for lists of mixed units. Presumably we
    // can set micros.gender to the gender associated with the list formatter in
    // use below (once we have correct support for that). And then document this
    // appropriately? "getMixedUnitModifier" doesn't sound like it would do
    // something like this.

    // Combine list into a "premixed" pattern
    UnicodeString premixedFormatPattern;
    fListFormatter->format(outputMeasuresList.getAlias(), fMixedUnitCount, premixedFormatPattern,
                           status);
    SimpleFormatter premixedCompiled(premixedFormatPattern, 0, 1, status);
    if (U_FAILURE(status)) {
        return &micros.helpers.emptyWeakModifier;
    }

    micros.helpers.mixedUnitModifier =
        SimpleModifier(premixedCompiled, kUndefinedField, false, {this, SIGNUM_POS_ZERO, quantityPlural});
    return &micros.helpers.mixedUnitModifier;
}

const Modifier *MixedUnitLongNameHandler::getModifier(Signum /*signum*/,
                                                      StandardPlural::Form /*plural*/) const {
    // TODO(icu-units#28): investigate this method when investigating where
    // ModifierStore::getModifier() gets used. To be sure it remains
    // unreachable:
    UPRV_UNREACHABLE_EXIT;
    return nullptr;
}

LongNameMultiplexer *LongNameMultiplexer::forMeasureUnits(const Locale &loc,
                                                          const MaybeStackVector<MeasureUnit> &units,
                                                          const UNumberUnitWidth &width,
                                                          const char *unitDisplayCase,
                                                          const PluralRules *rules,
                                                          const MicroPropsGenerator *parent,
                                                          UErrorCode &status) {
    LocalPointer<LongNameMultiplexer> result(new LongNameMultiplexer(parent), status);
    if (U_FAILURE(status)) {
        return nullptr;
    }
    U_ASSERT(units.length() > 0);
    if (result->fHandlers.resize(units.length()) == nullptr) {
        status = U_MEMORY_ALLOCATION_ERROR;
        return nullptr;
    }
    result->fMeasureUnits.adoptInstead(new MeasureUnit[units.length()]);
    for (int32_t i = 0, length = units.length(); i < length; i++) {
        const MeasureUnit &unit = *units[i];
        result->fMeasureUnits[i] = unit;
        if (unit.getComplexity(status) == UMEASURE_UNIT_MIXED) {
            MixedUnitLongNameHandler *mlnh = result->fMixedUnitHandlers.createAndCheckErrorCode(status);
            MixedUnitLongNameHandler::forMeasureUnit(loc, unit, width, unitDisplayCase, rules, NULL,
                                                     mlnh, status);
            result->fHandlers[i] = mlnh;
        } else {
            LongNameHandler *lnh = result->fLongNameHandlers.createAndCheckErrorCode(status);
            LongNameHandler::forMeasureUnit(loc, unit, width, unitDisplayCase, rules, NULL, lnh, status);
            result->fHandlers[i] = lnh;
        }
        if (U_FAILURE(status)) {
            return nullptr;
        }
    }
    return result.orphan();
}

void LongNameMultiplexer::processQuantity(DecimalQuantity &quantity, MicroProps &micros,
                                          UErrorCode &status) const {
    // We call parent->processQuantity() from the Multiplexer, instead of
    // letting LongNameHandler handle it: we don't know which LongNameHandler to
    // call until we've called the parent!
    fParent->processQuantity(quantity, micros, status);

    // Call the correct LongNameHandler based on outputUnit
    for (int i = 0; i < fHandlers.getCapacity(); i++) {
        if (fMeasureUnits[i] == micros.outputUnit) {
            fHandlers[i]->processQuantity(quantity, micros, status);
            return;
        }
    }
    if (U_FAILURE(status)) {
        return;
    }
    // We shouldn't receive any outputUnit for which we haven't already got a
    // LongNameHandler:
    status = U_INTERNAL_PROGRAM_ERROR;
}

#endif /* #if !UCONFIG_NO_FORMATTING */
