// © 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.resetString();
    result->fData.quantity1.clear();
    result->fData.quantity2.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.resetString();
    result->fData.quantity1.clear();
    result->fData.quantity2.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 */
