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

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

// Allow implicit conversion from char16_t* to UnicodeString for this file:
// Helpful in toString methods and elsewhere.
#define UNISTR_FROM_STRING_EXPLICIT

#include "fphdlimp.h"
#include "number_utypes.h"
#include "numparse_types.h"
#include "formattedval_impl.h"
#include "numrange_impl.h"
#include "number_decnum.h"
#include "unicode/numberrangeformatter.h"
#include "unicode/unumberrangeformatter.h"

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


U_NAMESPACE_BEGIN
namespace number {
namespace impl {

/**
 * Implementation class for UNumberRangeFormatter. Wraps a LocalizedRangeNumberFormatter.
 */
struct UNumberRangeFormatterData : public UMemory,
        // Magic number as ASCII == "NRF" (NumberRangeFormatter)
        public IcuCApiHelper<UNumberRangeFormatter, UNumberRangeFormatterData, 0x4E524600> {
    LocalizedNumberRangeFormatter fFormatter;
};

struct UFormattedNumberRangeImpl;

// Magic number as ASCII == "FDN" (FormatteDNumber)
typedef IcuCApiHelper<UFormattedNumberRange, UFormattedNumberRangeImpl, 0x46444E00> UFormattedNumberRangeApiHelper;

struct UFormattedNumberRangeImpl : public UFormattedValueImpl, public UFormattedNumberRangeApiHelper {
    UFormattedNumberRangeImpl();
    ~UFormattedNumberRangeImpl();

    FormattedNumberRange fImpl;
    UFormattedNumberRangeData fData;
};

UFormattedNumberRangeImpl::UFormattedNumberRangeImpl()
        : fImpl(&fData) {
    fFormattedValue = &fImpl;
}

UFormattedNumberRangeImpl::~UFormattedNumberRangeImpl() {
    // Disown the data from fImpl so it doesn't get deleted twice
    fImpl.fData = nullptr;
}

} // namespace impl
} // namespace number
U_NAMESPACE_END


UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(
    UFormattedNumberRange,
    UFormattedNumberRangeImpl,
    UFormattedNumberRangeApiHelper,
    unumrf)


const UFormattedNumberRangeData* number::impl::validateUFormattedNumberRange(
        const UFormattedNumberRange* uresult, UErrorCode& status) {
    auto* result = UFormattedNumberRangeApiHelper::validate(uresult, status);
    if (U_FAILURE(status)) {
        return nullptr;
    }
    return &result->fData;
}


U_CAPI UNumberRangeFormatter* U_EXPORT2
unumrf_openForSkeletonWithCollapseAndIdentityFallback(
        const UChar* skeleton,
        int32_t skeletonLen,
        UNumberRangeCollapse collapse,
        UNumberRangeIdentityFallback identityFallback,
        const char* locale,
        UParseError* perror,
        UErrorCode* ec) {
    auto* impl = new UNumberRangeFormatterData();
    if (impl == nullptr) {
        *ec = U_MEMORY_ALLOCATION_ERROR;
        return nullptr;
    }
    // Readonly-alias constructor (first argument is whether we are NUL-terminated)
    UnicodeString skeletonString(skeletonLen == -1, skeleton, skeletonLen);
    impl->fFormatter = NumberRangeFormatter::withLocale(locale)
        .numberFormatterBoth(NumberFormatter::forSkeleton(skeletonString, *perror, *ec))
        .collapse(collapse)
        .identityFallback(identityFallback);
    return impl->exportForC();
}

U_CAPI void U_EXPORT2
unumrf_formatDoubleRange(
        const UNumberRangeFormatter* uformatter,
        double first,
        double second,
        UFormattedNumberRange* uresult,
        UErrorCode* ec) {
    const UNumberRangeFormatterData* formatter = UNumberRangeFormatterData::validate(uformatter, *ec);
    auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec);
    if (U_FAILURE(*ec)) { return; }

    result->fData.getStringRef().clear();
    result->fData.quantity1.setToDouble(first);
    result->fData.quantity2.setToDouble(second);
    formatter->fFormatter.formatImpl(result->fData, first == second, *ec);
}

U_CAPI void U_EXPORT2
unumrf_formatDecimalRange(
        const UNumberRangeFormatter* uformatter,
        const char* first, int32_t firstLen,
        const char* second, int32_t secondLen,
        UFormattedNumberRange* uresult,
        UErrorCode* ec) {
    const UNumberRangeFormatterData* formatter = UNumberRangeFormatterData::validate(uformatter, *ec);
    auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec);
    if (U_FAILURE(*ec)) { return; }

    result->fData.getStringRef().clear();
    result->fData.quantity1.setToDecNumber({first, firstLen}, *ec);
    result->fData.quantity2.setToDecNumber({second, secondLen}, *ec);
    formatter->fFormatter.formatImpl(result->fData, first == second, *ec);
}

U_CAPI UNumberRangeIdentityResult U_EXPORT2
unumrf_resultGetIdentityResult(
        const UFormattedNumberRange* uresult,
        UErrorCode* ec) {
    auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec);
    if (U_FAILURE(*ec)) {
        return UNUM_IDENTITY_RESULT_COUNT;
    }
    return result->fData.identityResult;
}

U_CAPI int32_t U_EXPORT2
unumrf_resultGetFirstDecimalNumber(
        const UFormattedNumberRange* uresult,
        char* dest,
        int32_t destCapacity,
        UErrorCode* ec) {
    const auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec);
    if (U_FAILURE(*ec)) {
        return 0;
    }
    DecNum decnum;
    return result->fData.quantity1.toDecNum(decnum, *ec)
        .toCharString(*ec)
        .extract(dest, destCapacity, *ec);
}

U_CAPI int32_t U_EXPORT2
unumrf_resultGetSecondDecimalNumber(
        const UFormattedNumberRange* uresult,
        char* dest,
        int32_t destCapacity,
        UErrorCode* ec) {
    const auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec);
    if (U_FAILURE(*ec)) {
        return 0;
    }
    DecNum decnum;
    return result->fData.quantity2
        .toDecNum(decnum, *ec)
        .toCharString(*ec)
        .extract(dest, destCapacity, *ec);
}

U_CAPI void U_EXPORT2
unumrf_close(UNumberRangeFormatter* f) {
    UErrorCode localStatus = U_ZERO_ERROR;
    const UNumberRangeFormatterData* impl = UNumberRangeFormatterData::validate(f, localStatus);
    delete impl;
}


#endif /* #if !UCONFIG_NO_FORMATTING */
