// © 2020 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 "charstr.h"
#include "cmemory.h"
#include "double-conversion-string-to-double.h"
#include "measunit_impl.h"
#include "uassert.h"
#include "unicode/errorcode.h"
#include "unicode/localpointer.h"
#include "unicode/stringpiece.h"
#include "units_converter.h"
#include <algorithm>
#include <cmath>
#include <stdlib.h>
#include <utility>

U_NAMESPACE_BEGIN
namespace units {

void U_I18N_API Factor::multiplyBy(const Factor &rhs) {
    factorNum *= rhs.factorNum;
    factorDen *= rhs.factorDen;
    for (int i = 0; i < CONSTANTS_COUNT; i++) {
        constantExponents[i] += rhs.constantExponents[i];
    }

    // NOTE
    //  We need the offset when the source and the target are simple units. e.g. the source is
    //  celsius and the target is Fahrenheit. Therefore, we just keep the value using `std::max`.
    offset = std::max(rhs.offset, offset);
}

void U_I18N_API Factor::divideBy(const Factor &rhs) {
    factorNum *= rhs.factorDen;
    factorDen *= rhs.factorNum;
    for (int i = 0; i < CONSTANTS_COUNT; i++) {
        constantExponents[i] -= rhs.constantExponents[i];
    }

    // NOTE
    //  We need the offset when the source and the target are simple units. e.g. the source is
    //  celsius and the target is Fahrenheit. Therefore, we just keep the value using `std::max`.
    offset = std::max(rhs.offset, offset);
}

void U_I18N_API Factor::power(int32_t power) {
    // multiply all the constant by the power.
    for (int i = 0; i < CONSTANTS_COUNT; i++) {
        constantExponents[i] *= power;
    }

    bool shouldFlip = power < 0; // This means that after applying the absolute power, we should flip
                                 // the Numerator and Denominator.

    factorNum = std::pow(factorNum, std::abs(power));
    factorDen = std::pow(factorDen, std::abs(power));

    if (shouldFlip) {
        // Flip Numerator and Denominator.
        std::swap(factorNum, factorDen);
    }
}

void U_I18N_API Factor::applyPrefix(UMeasurePrefix unitPrefix) {
    if (unitPrefix == UMeasurePrefix::UMEASURE_PREFIX_ONE) {
        // No need to do anything
        return;
    }

    int32_t prefixPower = umeas_getPrefixPower(unitPrefix);
    double prefixFactor = std::pow((double)umeas_getPrefixBase(unitPrefix), (double)std::abs(prefixPower));
    if (prefixPower >= 0) {
        factorNum *= prefixFactor;
    } else {
        factorDen *= prefixFactor;
    }
}

void U_I18N_API Factor::substituteConstants() {
    for (int i = 0; i < CONSTANTS_COUNT; i++) {
        if (this->constantExponents[i] == 0) {
            continue;
        }

        auto absPower = std::abs(this->constantExponents[i]);
        Signum powerSig = this->constantExponents[i] < 0 ? Signum::NEGATIVE : Signum::POSITIVE;
        double absConstantValue = std::pow(constantsValues[i], absPower);

        if (powerSig == Signum::NEGATIVE) {
            this->factorDen *= absConstantValue;
        } else {
            this->factorNum *= absConstantValue;
        }

        this->constantExponents[i] = 0;
    }
}

namespace {

/* Helpers */

using icu::double_conversion::StringToDoubleConverter;

// TODO: Make this a shared-utility function.
// Returns `double` from a scientific number(i.e. "1", "2.01" or "3.09E+4")
double strToDouble(StringPiece strNum, UErrorCode &status) {
    // We are processing well-formed input, so we don't need any special options to
    // StringToDoubleConverter.
    StringToDoubleConverter converter(0, 0, 0, "", "");
    int32_t count;
    double result = converter.StringToDouble(strNum.data(), strNum.length(), &count);
    if (count != strNum.length()) {
        status = U_INVALID_FORMAT_ERROR;
    }

    return result;
}

// Returns `double` from a scientific number that could has a division sign (i.e. "1", "2.01", "3.09E+4"
// or "2E+2/3")
double strHasDivideSignToDouble(StringPiece strWithDivide, UErrorCode &status) {
    int divisionSignInd = -1;
    for (int i = 0, n = strWithDivide.length(); i < n; ++i) {
        if (strWithDivide.data()[i] == '/') {
            divisionSignInd = i;
            break;
        }
    }

    if (divisionSignInd >= 0) {
        return strToDouble(strWithDivide.substr(0, divisionSignInd), status) /
               strToDouble(strWithDivide.substr(divisionSignInd + 1), status);
    }

    return strToDouble(strWithDivide, status);
}

/*
  Adds single factor to a `Factor` object. Single factor means "23^2", "23.3333", "ft2m^3" ...etc.
  However, complex factor are not included, such as "ft2m^3*200/3"
*/
void addFactorElement(Factor &factor, StringPiece elementStr, Signum signum, UErrorCode &status) {
    StringPiece baseStr;
    StringPiece powerStr;
    int32_t power =
        1; // In case the power is not written, then, the power is equal 1 ==> `ft2m^1` == `ft2m`

    // Search for the power part
    int32_t powerInd = -1;
    for (int32_t i = 0, n = elementStr.length(); i < n; ++i) {
        if (elementStr.data()[i] == '^') {
            powerInd = i;
            break;
        }
    }

    if (powerInd > -1) {
        // There is power
        baseStr = elementStr.substr(0, powerInd);
        powerStr = elementStr.substr(powerInd + 1);

        power = static_cast<int32_t>(strToDouble(powerStr, status));
    } else {
        baseStr = elementStr;
    }

    addSingleFactorConstant(baseStr, power, signum, factor, status);
}

/*
 * Extracts `Factor` from a complete string factor. e.g. "ft2m^3*1007/cup2m3*3"
 */
Factor extractFactorConversions(StringPiece stringFactor, UErrorCode &status) {
    Factor result;
    Signum signum = Signum::POSITIVE;
    auto factorData = stringFactor.data();
    for (int32_t i = 0, start = 0, n = stringFactor.length(); i < n; i++) {
        if (factorData[i] == '*' || factorData[i] == '/') {
            StringPiece factorElement = stringFactor.substr(start, i - start);
            addFactorElement(result, factorElement, signum, status);

            start = i + 1; // Set `start` to point to the start of the new element.
        } else if (i == n - 1) {
            // Last element
            addFactorElement(result, stringFactor.substr(start, i + 1), signum, status);
        }

        if (factorData[i] == '/') {
            signum = Signum::NEGATIVE; // Change the signum because we reached the Denominator.
        }
    }

    return result;
}

// Load factor for a single source
Factor loadSingleFactor(StringPiece source, const ConversionRates &ratesInfo, UErrorCode &status) {
    const auto conversionUnit = ratesInfo.extractConversionInfo(source, status);
    if (U_FAILURE(status)) return Factor();
    if (conversionUnit == nullptr) {
        status = U_INTERNAL_PROGRAM_ERROR;
        return Factor();
    }

    Factor result = extractFactorConversions(conversionUnit->factor.toStringPiece(), status);
    result.offset = strHasDivideSignToDouble(conversionUnit->offset.toStringPiece(), status);

    return result;
}

// Load Factor of a compound source unit.
// In ICU4J, this is a pair of ConversionRates.getFactorToBase() functions.
Factor loadCompoundFactor(const MeasureUnitImpl &source, const ConversionRates &ratesInfo,
                          UErrorCode &status) {

    Factor result;
    for (int32_t i = 0, n = source.singleUnits.length(); i < n; i++) {
        SingleUnitImpl singleUnit = *source.singleUnits[i];

        Factor singleFactor = loadSingleFactor(singleUnit.getSimpleUnitID(), ratesInfo, status);
        if (U_FAILURE(status)) return result;

        // Prefix before power, because:
        // - square-kilometer to square-meter: (1000)^2
        // - square-kilometer to square-foot (approximate): (3.28*1000)^2
        singleFactor.applyPrefix(singleUnit.unitPrefix);

        // Apply the power of the `dimensionality`
        singleFactor.power(singleUnit.dimensionality);

        result.multiplyBy(singleFactor);
    }

    return result;
}

/**
 * Checks if the source unit and the target unit are simple. For example celsius or fahrenheit. But not
 * square-celsius or square-fahrenheit.
 *
 * NOTE:
 *  Empty unit means simple unit.
 *
 * In ICU4J, this is ConversionRates.checkSimpleUnit().
 */
UBool checkSimpleUnit(const MeasureUnitImpl &unit, UErrorCode &status) {
    if (U_FAILURE(status)) return false;

    if (unit.complexity != UMEASURE_UNIT_SINGLE) {
        return false;
    }
    if (unit.singleUnits.length() == 0) {
        // Empty units means simple unit.
        return true;
    }

    auto singleUnit = *(unit.singleUnits[0]);

    if (singleUnit.dimensionality != 1 || singleUnit.unitPrefix != UMEASURE_PREFIX_ONE) {
        return false;
    }

    return true;
}

/**
 *  Extract conversion rate from `source` to `target`
 */
// In ICU4J, this function is partially inlined in the UnitsConverter constructor.
void loadConversionRate(ConversionRate &conversionRate, const MeasureUnitImpl &source,
                        const MeasureUnitImpl &target, Convertibility unitsState,
                        const ConversionRates &ratesInfo, UErrorCode &status) {
    // Represents the conversion factor from the source to the target.
    Factor finalFactor;

    // Represents the conversion factor from the source to the base unit that specified in the conversion
    // data which is considered as the root of the source and the target.
    Factor sourceToBase = loadCompoundFactor(source, ratesInfo, status);
    Factor targetToBase = loadCompoundFactor(target, ratesInfo, status);

    // Merger Factors
    finalFactor.multiplyBy(sourceToBase);
    if (unitsState == Convertibility::CONVERTIBLE) {
        finalFactor.divideBy(targetToBase);
    } else if (unitsState == Convertibility::RECIPROCAL) {
        finalFactor.multiplyBy(targetToBase);
    } else {
        status = UErrorCode::U_ARGUMENT_TYPE_MISMATCH;
        return;
    }

    finalFactor.substituteConstants();

    conversionRate.factorNum = finalFactor.factorNum;
    conversionRate.factorDen = finalFactor.factorDen;

    // This code corresponds to ICU4J's ConversionRates.getOffset().
    // In case of simple units (such as: celsius or fahrenheit), offsets are considered.
    if (checkSimpleUnit(source, status) && checkSimpleUnit(target, status)) {
        conversionRate.sourceOffset =
            sourceToBase.offset * sourceToBase.factorDen / sourceToBase.factorNum;
        conversionRate.targetOffset =
            targetToBase.offset * targetToBase.factorDen / targetToBase.factorNum;
    }
    // TODO(icu-units#127): should we consider failure if there's an offset for
    // a not-simple-unit? What about kilokelvin / kilocelsius?

    conversionRate.reciprocal = unitsState == Convertibility::RECIPROCAL;
}

struct UnitIndexAndDimension : UMemory {
    int32_t index = 0;
    int32_t dimensionality = 0;

    UnitIndexAndDimension(const SingleUnitImpl &singleUnit, int32_t multiplier) {
        index = singleUnit.index;
        dimensionality = singleUnit.dimensionality * multiplier;
    }
};

void mergeSingleUnitWithDimension(MaybeStackVector<UnitIndexAndDimension> &unitIndicesWithDimension,
                                  const SingleUnitImpl &shouldBeMerged, int32_t multiplier) {
    for (int32_t i = 0; i < unitIndicesWithDimension.length(); i++) {
        auto &unitWithIndex = *unitIndicesWithDimension[i];
        if (unitWithIndex.index == shouldBeMerged.index) {
            unitWithIndex.dimensionality += shouldBeMerged.dimensionality * multiplier;
            return;
        }
    }

    unitIndicesWithDimension.emplaceBack(shouldBeMerged, multiplier);
}

void mergeUnitsAndDimensions(MaybeStackVector<UnitIndexAndDimension> &unitIndicesWithDimension,
                             const MeasureUnitImpl &shouldBeMerged, int32_t multiplier) {
    for (int32_t unit_i = 0; unit_i < shouldBeMerged.singleUnits.length(); unit_i++) {
        auto singleUnit = *shouldBeMerged.singleUnits[unit_i];
        mergeSingleUnitWithDimension(unitIndicesWithDimension, singleUnit, multiplier);
    }
}

UBool checkAllDimensionsAreZeros(const MaybeStackVector<UnitIndexAndDimension> &dimensionVector) {
    for (int32_t i = 0; i < dimensionVector.length(); i++) {
        if (dimensionVector[i]->dimensionality != 0) {
            return false;
        }
    }

    return true;
}

} // namespace

// Conceptually, this modifies factor: factor *= baseStr^(signum*power).
//
// baseStr must be a known constant or a value that strToDouble() is able to
// parse.
void U_I18N_API addSingleFactorConstant(StringPiece baseStr, int32_t power, Signum signum,
                                        Factor &factor, UErrorCode &status) {
    if (baseStr == "ft_to_m") {
        factor.constantExponents[CONSTANT_FT2M] += power * signum;
    } else if (baseStr == "ft2_to_m2") {
        factor.constantExponents[CONSTANT_FT2M] += 2 * power * signum;
    } else if (baseStr == "ft3_to_m3") {
        factor.constantExponents[CONSTANT_FT2M] += 3 * power * signum;
    } else if (baseStr == "in3_to_m3") {
        factor.constantExponents[CONSTANT_FT2M] += 3 * power * signum;
        factor.factorDen *= 12 * 12 * 12;
    } else if (baseStr == "gal_to_m3") {
        factor.factorNum *= 231;
        factor.constantExponents[CONSTANT_FT2M] += 3 * power * signum;
        factor.factorDen *= 12 * 12 * 12;
    } else if (baseStr == "gal_imp_to_m3") {
        factor.constantExponents[CONSTANT_GAL_IMP2M3] += power * signum;
    } else if (baseStr == "G") {
        factor.constantExponents[CONSTANT_G] += power * signum;
    } else if (baseStr == "gravity") {
        factor.constantExponents[CONSTANT_GRAVITY] += power * signum;
    } else if (baseStr == "lb_to_kg") {
        factor.constantExponents[CONSTANT_LB2KG] += power * signum;
    } else if (baseStr == "glucose_molar_mass") {
        factor.constantExponents[CONSTANT_GLUCOSE_MOLAR_MASS] += power * signum;
    } else if (baseStr == "item_per_mole") {
        factor.constantExponents[CONSTANT_ITEM_PER_MOLE] += power * signum;
    } else if (baseStr == "PI") {
        factor.constantExponents[CONSTANT_PI] += power * signum;
    } else {
        if (signum == Signum::NEGATIVE) {
            factor.factorDen *= std::pow(strToDouble(baseStr, status), power);
        } else {
            factor.factorNum *= std::pow(strToDouble(baseStr, status), power);
        }
    }
}

/**
 * Extracts the compound base unit of a compound unit (`source`). For example, if the source unit is
 * `square-mile-per-hour`, the compound base unit will be `square-meter-per-second`
 */
MeasureUnitImpl U_I18N_API extractCompoundBaseUnit(const MeasureUnitImpl &source,
                                                   const ConversionRates &conversionRates,
                                                   UErrorCode &status) {

    MeasureUnitImpl result;
    if (U_FAILURE(status)) return result;

    const auto &singleUnits = source.singleUnits;
    for (int i = 0, count = singleUnits.length(); i < count; ++i) {
        const auto &singleUnit = *singleUnits[i];
        // Extract `ConversionRateInfo` using the absolute unit. For example: in case of `square-meter`,
        // we will use `meter`
        const auto rateInfo =
            conversionRates.extractConversionInfo(singleUnit.getSimpleUnitID(), status);
        if (U_FAILURE(status)) {
            return result;
        }
        if (rateInfo == nullptr) {
            status = U_INTERNAL_PROGRAM_ERROR;
            return result;
        }

        // Multiply the power of the singleUnit by the power of the baseUnit. For example, square-hectare
        // must be pow4-meter. (NOTE: hectare --> square-meter)
        auto baseUnits =
            MeasureUnitImpl::forIdentifier(rateInfo->baseUnit.toStringPiece(), status).singleUnits;
        for (int32_t i = 0, baseUnitsCount = baseUnits.length(); i < baseUnitsCount; i++) {
            baseUnits[i]->dimensionality *= singleUnit.dimensionality;
            // TODO: Deal with SI-prefix
            result.appendSingleUnit(*baseUnits[i], status);

            if (U_FAILURE(status)) {
                return result;
            }
        }
    }

    return result;
}

/**
 * Determine the convertibility between `source` and `target`.
 * For example:
 *    `meter` and `foot` are `CONVERTIBLE`.
 *    `meter-per-second` and `second-per-meter` are `RECIPROCAL`.
 *    `meter` and `pound` are `UNCONVERTIBLE`.
 *
 * NOTE:
 *    Only works with SINGLE and COMPOUND units. If one of the units is a
 *    MIXED unit, an error will occur. For more information, see UMeasureUnitComplexity.
 */
Convertibility U_I18N_API extractConvertibility(const MeasureUnitImpl &source,
                                                const MeasureUnitImpl &target,
                                                const ConversionRates &conversionRates,
                                                UErrorCode &status) {

    if (source.complexity == UMeasureUnitComplexity::UMEASURE_UNIT_MIXED ||
        target.complexity == UMeasureUnitComplexity::UMEASURE_UNIT_MIXED) {
        status = U_INTERNAL_PROGRAM_ERROR;
        return UNCONVERTIBLE;
    }

    MeasureUnitImpl sourceBaseUnit = extractCompoundBaseUnit(source, conversionRates, status);
    MeasureUnitImpl targetBaseUnit = extractCompoundBaseUnit(target, conversionRates, status);
    if (U_FAILURE(status)) return UNCONVERTIBLE;

    MaybeStackVector<UnitIndexAndDimension> convertible;
    MaybeStackVector<UnitIndexAndDimension> reciprocal;

    mergeUnitsAndDimensions(convertible, sourceBaseUnit, 1);
    mergeUnitsAndDimensions(reciprocal, sourceBaseUnit, 1);

    mergeUnitsAndDimensions(convertible, targetBaseUnit, -1);
    mergeUnitsAndDimensions(reciprocal, targetBaseUnit, 1);

    if (checkAllDimensionsAreZeros(convertible)) {
        return CONVERTIBLE;
    }

    if (checkAllDimensionsAreZeros(reciprocal)) {
        return RECIPROCAL;
    }

    return UNCONVERTIBLE;
}

UnitsConverter::UnitsConverter(const MeasureUnitImpl &source, const MeasureUnitImpl &target,
                             const ConversionRates &ratesInfo, UErrorCode &status)
    : conversionRate_(source.copy(status), target.copy(status)) {
    if (source.complexity == UMeasureUnitComplexity::UMEASURE_UNIT_MIXED ||
        target.complexity == UMeasureUnitComplexity::UMEASURE_UNIT_MIXED) {
        status = U_INTERNAL_PROGRAM_ERROR;
        return;
    }

    Convertibility unitsState = extractConvertibility(source, target, ratesInfo, status);
    if (U_FAILURE(status)) return;
    if (unitsState == Convertibility::UNCONVERTIBLE) {
        status = U_INTERNAL_PROGRAM_ERROR;
        return;
    }

    loadConversionRate(conversionRate_, conversionRate_.source, conversionRate_.target, unitsState,
                       ratesInfo, status);
}

int32_t UnitsConverter::compareTwoUnits(const MeasureUnitImpl &firstUnit,
                                       const MeasureUnitImpl &secondUnit,
                                       const ConversionRates &ratesInfo, UErrorCode &status) {
    if (U_FAILURE(status)) {
        return 0;
    }

    if (firstUnit.complexity == UMeasureUnitComplexity::UMEASURE_UNIT_MIXED ||
        secondUnit.complexity == UMeasureUnitComplexity::UMEASURE_UNIT_MIXED) {
        status = U_INTERNAL_PROGRAM_ERROR;
        return 0;
    }

    Convertibility unitsState = extractConvertibility(firstUnit, secondUnit, ratesInfo, status);
    if (U_FAILURE(status)) {
        return 0;
    }

    if (unitsState == Convertibility::UNCONVERTIBLE || unitsState == Convertibility::RECIPROCAL) {
        status = U_INTERNAL_PROGRAM_ERROR;
        return 0;
    }

    // Represents the conversion factor from the firstUnit to the base unit that specified in the
    // conversion data which is considered as the root of the firstUnit and the secondUnit.
    Factor firstUnitToBase = loadCompoundFactor(firstUnit, ratesInfo, status);
    Factor secondUnitToBase = loadCompoundFactor(secondUnit, ratesInfo, status);

    firstUnitToBase.substituteConstants();
    secondUnitToBase.substituteConstants();

    double firstUnitToBaseConversionRate = firstUnitToBase.factorNum / firstUnitToBase.factorDen;
    double secondUnitToBaseConversionRate = secondUnitToBase.factorNum / secondUnitToBase.factorDen;

    double diff = firstUnitToBaseConversionRate - secondUnitToBaseConversionRate;
    if (diff > 0) {
        return 1;
    }

    if (diff < 0) {
        return -1;
    }

    return 0;
}

double UnitsConverter::convert(double inputValue) const {
    double result =
        inputValue + conversionRate_.sourceOffset; // Reset the input to the target zero index.
    // Convert the quantity to from the source scale to the target scale.
    result *= conversionRate_.factorNum / conversionRate_.factorDen;

    result -= conversionRate_.targetOffset; // Set the result to its index.

    if (conversionRate_.reciprocal) {
        if (result == 0) {
            // TODO: demonstrate the resulting behaviour in tests... and figure
            // out desired behaviour. (Theoretical result should be infinity,
            // not 0.)
            return 0.0;
        }
        result = 1.0 / result;
    }

    return result;
}

double UnitsConverter::convertInverse(double inputValue) const {
    double result = inputValue;
    if (conversionRate_.reciprocal) {
        if (result == 0) {
            // TODO: demonstrate the resulting behaviour in tests... and figure
            // out desired behaviour. (Theoretical result should be infinity,
            // not 0.)
            return 0.0;
        }
        result = 1.0 / result;
    }
    result += conversionRate_.targetOffset;
    result *= conversionRate_.factorDen / conversionRate_.factorNum;
    result -= conversionRate_.sourceOffset;
    return result;
}

ConversionInfo UnitsConverter::getConversionInfo() const {
    ConversionInfo result;
    result.conversionRate = conversionRate_.factorNum / conversionRate_.factorDen;
    result.offset =
        (conversionRate_.sourceOffset * (conversionRate_.factorNum / conversionRate_.factorDen)) -
        conversionRate_.targetOffset;
    result.reciprocal = conversionRate_.reciprocal;

    return result;
}

} // namespace units
U_NAMESPACE_END

#endif /* #if !UCONFIG_NO_FORMATTING */
