// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
 *******************************************************************************
 * Copyright (C) 2009-2014, International Business Machines Corporation and
 * others. All Rights Reserved.
 *******************************************************************************
 */

#include "unicode/currpinf.h"

#if !UCONFIG_NO_FORMATTING

//#define CURRENCY_PLURAL_INFO_DEBUG 1

#ifdef CURRENCY_PLURAL_INFO_DEBUG
#include <iostream>
#endif

#include "unicode/locid.h"
#include "unicode/plurrule.h"
#include "unicode/strenum.h"
#include "unicode/ures.h"
#include "unicode/numsys.h"
#include "cstring.h"
#include "hash.h"
#include "uresimp.h"
#include "ureslocs.h"

U_NAMESPACE_BEGIN

static const UChar gNumberPatternSeparator = 0x3B; // ;

U_CDECL_BEGIN

/**
 * @internal ICU 4.2
 */
static UBool U_CALLCONV ValueComparator(UHashTok val1, UHashTok val2);

UBool
U_CALLCONV ValueComparator(UHashTok val1, UHashTok val2) {
    const UnicodeString* affix_1 = (UnicodeString*)val1.pointer;
    const UnicodeString* affix_2 = (UnicodeString*)val2.pointer;
    return  *affix_1 == *affix_2;
}

U_CDECL_END


UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CurrencyPluralInfo)

static const UChar gDefaultCurrencyPluralPattern[] = {'0', '.', '#', '#', ' ', 0xA4, 0xA4, 0xA4, 0};
static const UChar gTripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
static const UChar gPluralCountOther[] = {0x6F, 0x74, 0x68, 0x65, 0x72, 0};
static const UChar gPart0[] = {0x7B, 0x30, 0x7D, 0};
static const UChar gPart1[] = {0x7B, 0x31, 0x7D, 0};

static const char gNumberElementsTag[]="NumberElements";
static const char gLatnTag[]="latn";
static const char gPatternsTag[]="patterns";
static const char gDecimalFormatTag[]="decimalFormat";
static const char gCurrUnitPtnTag[]="CurrencyUnitPatterns";

CurrencyPluralInfo::CurrencyPluralInfo(UErrorCode& status)
:   fPluralCountToCurrencyUnitPattern(nullptr),
    fPluralRules(nullptr),
    fLocale(nullptr),
    fInternalStatus(U_ZERO_ERROR) {
    initialize(Locale::getDefault(), status);
}

CurrencyPluralInfo::CurrencyPluralInfo(const Locale& locale, UErrorCode& status)
:   fPluralCountToCurrencyUnitPattern(nullptr),
    fPluralRules(nullptr),
    fLocale(nullptr),
    fInternalStatus(U_ZERO_ERROR) {
    initialize(locale, status);
}

CurrencyPluralInfo::CurrencyPluralInfo(const CurrencyPluralInfo& info) 
:   UObject(info),
    fPluralCountToCurrencyUnitPattern(nullptr),
    fPluralRules(nullptr),
    fLocale(nullptr),
    fInternalStatus(U_ZERO_ERROR) {
    *this = info;
}

CurrencyPluralInfo&
CurrencyPluralInfo::operator=(const CurrencyPluralInfo& info) {
    if (this == &info) {
        return *this;
    }

    fInternalStatus = info.fInternalStatus;
    if (U_FAILURE(fInternalStatus)) {
        // bail out early if the object we were copying from was already 'invalid'.
        return *this;
    }

    deleteHash(fPluralCountToCurrencyUnitPattern);
    fPluralCountToCurrencyUnitPattern = initHash(fInternalStatus);
    copyHash(info.fPluralCountToCurrencyUnitPattern, 
             fPluralCountToCurrencyUnitPattern, fInternalStatus);
    if ( U_FAILURE(fInternalStatus) ) {
        return *this;
    }

    delete fPluralRules;
    fPluralRules = nullptr;
    delete fLocale;
    fLocale = nullptr;

    if (info.fPluralRules != nullptr) {
        fPluralRules = info.fPluralRules->clone();
        if (fPluralRules == nullptr) {
            fInternalStatus = U_MEMORY_ALLOCATION_ERROR;
            return *this;
        }
    }
    if (info.fLocale != nullptr) {
        fLocale = info.fLocale->clone();
        if (fLocale == nullptr) {
            // Note: If clone had an error parameter, then we could check/set that instead.
            fInternalStatus = U_MEMORY_ALLOCATION_ERROR;
            return *this;
        }
        // If the other locale wasn't bogus, but our clone'd locale is bogus, then OOM happened
        // during the call to clone().
        if (!info.fLocale->isBogus() && fLocale->isBogus()) {
            fInternalStatus = U_MEMORY_ALLOCATION_ERROR;
            return *this;
        }
    }
    return *this;
}

CurrencyPluralInfo::~CurrencyPluralInfo() {
    deleteHash(fPluralCountToCurrencyUnitPattern);
    fPluralCountToCurrencyUnitPattern = nullptr;
    delete fPluralRules;
    delete fLocale;
    fPluralRules = nullptr;
    fLocale = nullptr;
}

UBool
CurrencyPluralInfo::operator==(const CurrencyPluralInfo& info) const {
#ifdef CURRENCY_PLURAL_INFO_DEBUG
    if (*fPluralRules == *info.fPluralRules) {
        std::cout << "same plural rules\n";
    }
    if (*fLocale == *info.fLocale) {
        std::cout << "same locale\n";
    }
    if (fPluralCountToCurrencyUnitPattern->equals(*info.fPluralCountToCurrencyUnitPattern)) {
        std::cout << "same pattern\n";
    }
#endif
    return *fPluralRules == *info.fPluralRules &&
           *fLocale == *info.fLocale &&
           fPluralCountToCurrencyUnitPattern->equals(*info.fPluralCountToCurrencyUnitPattern);
}


CurrencyPluralInfo*
CurrencyPluralInfo::clone() const {
    CurrencyPluralInfo* newObj = new CurrencyPluralInfo(*this);
    // Since clone doesn't have a 'status' parameter, the best we can do is return nullptr
    // if the new object was not full constructed properly (an error occurred).
    if (newObj != nullptr && U_FAILURE(newObj->fInternalStatus)) {
        delete newObj;
        newObj = nullptr;
    }
    return newObj;
}

const PluralRules* 
CurrencyPluralInfo::getPluralRules() const {
    return fPluralRules;
}

UnicodeString&
CurrencyPluralInfo::getCurrencyPluralPattern(const UnicodeString&  pluralCount,
                                             UnicodeString& result) const {
    const UnicodeString* currencyPluralPattern = 
        (UnicodeString*)fPluralCountToCurrencyUnitPattern->get(pluralCount);
    if (currencyPluralPattern == nullptr) {
        // fall back to "other"
        if (pluralCount.compare(gPluralCountOther, 5)) {
            currencyPluralPattern = 
                (UnicodeString*)fPluralCountToCurrencyUnitPattern->get(UnicodeString(TRUE, gPluralCountOther, 5));
        }
        if (currencyPluralPattern == nullptr) {
            // no currencyUnitPatterns defined, 
            // fallback to predefined default.
            // This should never happen when ICU resource files are
            // available, since currencyUnitPattern of "other" is always
            // defined in root.
            result = UnicodeString(gDefaultCurrencyPluralPattern);
            return result;
        }
    }
    result = *currencyPluralPattern;
    return result;
}

const Locale&
CurrencyPluralInfo::getLocale() const {
    return *fLocale;
}

void
CurrencyPluralInfo::setPluralRules(const UnicodeString& ruleDescription,
                                   UErrorCode& status) {
    if (U_SUCCESS(status)) {
        delete fPluralRules;
        fPluralRules = PluralRules::createRules(ruleDescription, status);
    }
}

void
CurrencyPluralInfo::setCurrencyPluralPattern(const UnicodeString& pluralCount,
                                             const UnicodeString& pattern,
                                             UErrorCode& status) {
    if (U_SUCCESS(status)) {
        UnicodeString* oldValue = static_cast<UnicodeString*>(
            fPluralCountToCurrencyUnitPattern->get(pluralCount));
        delete oldValue;
        LocalPointer<UnicodeString> p(new UnicodeString(pattern), status);
        if (U_SUCCESS(status)) {
            // the p object allocated above will be owned by fPluralCountToCurrencyUnitPattern
            // after the call to put(), even if the method returns failure.
            fPluralCountToCurrencyUnitPattern->put(pluralCount, p.orphan(), status);
        }
    }
}

void
CurrencyPluralInfo::setLocale(const Locale& loc, UErrorCode& status) {
    initialize(loc, status);
}

void 
CurrencyPluralInfo::initialize(const Locale& loc, UErrorCode& status) {
    if (U_FAILURE(status)) {
        return;
    }
    delete fLocale;
    fLocale = nullptr;    
    delete fPluralRules;
    fPluralRules = nullptr;

    fLocale = loc.clone();
    if (fLocale == nullptr) {
        status = U_MEMORY_ALLOCATION_ERROR;
        return;
    }
    // If the locale passed in wasn't bogus, but our clone'd locale is bogus, then OOM happened
    // during the call to loc.clone().
    if (!loc.isBogus() && fLocale->isBogus()) {
        status = U_MEMORY_ALLOCATION_ERROR;
        return;
    }
    fPluralRules = PluralRules::forLocale(loc, status);
    setupCurrencyPluralPattern(loc, status);
}
   
void
CurrencyPluralInfo::setupCurrencyPluralPattern(const Locale& loc, UErrorCode& status) {
    if (U_FAILURE(status)) {
        return;
    }

    deleteHash(fPluralCountToCurrencyUnitPattern);
    fPluralCountToCurrencyUnitPattern = initHash(status);
    if (U_FAILURE(status)) {
        return;
    }

    LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(loc, status), status);
    if (U_FAILURE(status)) {
        return;
    }
    UErrorCode ec = U_ZERO_ERROR;
    LocalUResourceBundlePointer rb(ures_open(nullptr, loc.getName(), &ec));
    LocalUResourceBundlePointer numElements(ures_getByKeyWithFallback(rb.getAlias(), gNumberElementsTag, nullptr, &ec));
    ures_getByKeyWithFallback(numElements.getAlias(), ns->getName(), rb.getAlias(), &ec);
    ures_getByKeyWithFallback(rb.getAlias(), gPatternsTag, rb.getAlias(), &ec);
    int32_t ptnLen;
    const UChar* numberStylePattern = ures_getStringByKeyWithFallback(rb.getAlias(), gDecimalFormatTag, &ptnLen, &ec);
    // Fall back to "latn" if num sys specific pattern isn't there.
    if ( ec == U_MISSING_RESOURCE_ERROR && (uprv_strcmp(ns->getName(), gLatnTag) != 0)) {
        ec = U_ZERO_ERROR;
        ures_getByKeyWithFallback(numElements.getAlias(), gLatnTag, rb.getAlias(), &ec);
        ures_getByKeyWithFallback(rb.getAlias(), gPatternsTag, rb.getAlias(), &ec);
        numberStylePattern = ures_getStringByKeyWithFallback(rb.getAlias(), gDecimalFormatTag, &ptnLen, &ec);
    }
    int32_t numberStylePatternLen = ptnLen;
    const UChar* negNumberStylePattern = nullptr;
    int32_t negNumberStylePatternLen = 0;
    // TODO: Java
    // parse to check whether there is ";" separator in the numberStylePattern
    UBool hasSeparator = false;
    if (U_SUCCESS(ec)) {
        for (int32_t styleCharIndex = 0; styleCharIndex < ptnLen; ++styleCharIndex) {
            if (numberStylePattern[styleCharIndex] == gNumberPatternSeparator) {
                hasSeparator = true;
                // split the number style pattern into positive and negative
                negNumberStylePattern = numberStylePattern + styleCharIndex + 1;
                negNumberStylePatternLen = ptnLen - styleCharIndex - 1;
                numberStylePatternLen = styleCharIndex;
            }
        }
    }

    if (U_FAILURE(ec)) {
        // If OOM occurred during the above code, then we want to report that back to the caller.
        if (ec == U_MEMORY_ALLOCATION_ERROR) {
            status = ec;
        }
        return;
    }

    LocalUResourceBundlePointer currRb(ures_open(U_ICUDATA_CURR, loc.getName(), &ec));
    LocalUResourceBundlePointer currencyRes(ures_getByKeyWithFallback(currRb.getAlias(), gCurrUnitPtnTag, nullptr, &ec));
    
#ifdef CURRENCY_PLURAL_INFO_DEBUG
    std::cout << "in set up\n";
#endif
    LocalPointer<StringEnumeration> keywords(fPluralRules->getKeywords(ec), ec);
    if (U_SUCCESS(ec)) {
        const char* pluralCount;
        while (((pluralCount = keywords->next(nullptr, ec)) != nullptr) && U_SUCCESS(ec)) {
            int32_t ptnLength;
            UErrorCode err = U_ZERO_ERROR;
            const UChar* patternChars = ures_getStringByKeyWithFallback(currencyRes.getAlias(), pluralCount, &ptnLength, &err);
            if (err == U_MEMORY_ALLOCATION_ERROR || patternChars == nullptr) {
                ec = err;
                break;
            }
            if (U_SUCCESS(err) && ptnLength > 0) {
                UnicodeString* pattern = new UnicodeString(patternChars, ptnLength);
                if (pattern == nullptr) {
                    ec = U_MEMORY_ALLOCATION_ERROR;
                    break;
                }
#ifdef CURRENCY_PLURAL_INFO_DEBUG
                char result_1[1000];
                pattern->extract(0, pattern->length(), result_1, "UTF-8");
                std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n";
#endif
                pattern->findAndReplace(UnicodeString(TRUE, gPart0, 3), 
                    UnicodeString(numberStylePattern, numberStylePatternLen));
                pattern->findAndReplace(UnicodeString(TRUE, gPart1, 3), UnicodeString(TRUE, gTripleCurrencySign, 3));

                if (hasSeparator) {
                    UnicodeString negPattern(patternChars, ptnLength);
                    negPattern.findAndReplace(UnicodeString(TRUE, gPart0, 3), 
                        UnicodeString(negNumberStylePattern, negNumberStylePatternLen));
                    negPattern.findAndReplace(UnicodeString(TRUE, gPart1, 3), UnicodeString(TRUE, gTripleCurrencySign, 3));
                    pattern->append(gNumberPatternSeparator);
                    pattern->append(negPattern);
                }
#ifdef CURRENCY_PLURAL_INFO_DEBUG
                pattern->extract(0, pattern->length(), result_1, "UTF-8");
                std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n";
#endif
                // the 'pattern' object allocated above will be owned by the fPluralCountToCurrencyUnitPattern after the call to
                // put(), even if the method returns failure.
                fPluralCountToCurrencyUnitPattern->put(UnicodeString(pluralCount, -1, US_INV), pattern, status);
            }
        }
    }
    // If OOM occurred during the above code, then we want to report that back to the caller.
    if (ec == U_MEMORY_ALLOCATION_ERROR) {
        status = ec;
    }
}

void
CurrencyPluralInfo::deleteHash(Hashtable* hTable) {
    if ( hTable == nullptr ) {
        return;
    }
    int32_t pos = UHASH_FIRST;
    const UHashElement* element = nullptr;
    while ( (element = hTable->nextElement(pos)) != nullptr ) {
        const UHashTok valueTok = element->value;
        const UnicodeString* value = (UnicodeString*)valueTok.pointer;
        delete value;
    }
    delete hTable;
    hTable = nullptr;
}

Hashtable*
CurrencyPluralInfo::initHash(UErrorCode& status) {
    if (U_FAILURE(status)) {
        return nullptr;
    }
    LocalPointer<Hashtable> hTable(new Hashtable(TRUE, status), status);
    if (U_FAILURE(status)) {
        return nullptr;
    }
    hTable->setValueComparator(ValueComparator);
    return hTable.orphan();
}

void
CurrencyPluralInfo::copyHash(const Hashtable* source,
                           Hashtable* target,
                           UErrorCode& status) {
    if (U_FAILURE(status)) {
        return;
    }
    int32_t pos = UHASH_FIRST;
    const UHashElement* element = nullptr;
    if (source) {
        while ( (element = source->nextElement(pos)) != nullptr ) {
            const UHashTok keyTok = element->key;
            const UnicodeString* key = (UnicodeString*)keyTok.pointer;
            const UHashTok valueTok = element->value;
            const UnicodeString* value = (UnicodeString*)valueTok.pointer;
            LocalPointer<UnicodeString> copy(new UnicodeString(*value), status);
            if (U_FAILURE(status)) {
                return;
            }
            // The HashTable owns the 'copy' object after the call to put().
            target->put(UnicodeString(*key), copy.orphan(), status);
            if (U_FAILURE(status)) {
                return;
            }
        }
    }
}

U_NAMESPACE_END

#endif
