/*
*******************************************************************************
* Copyright (C) 2010, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*
*
* File NUMSYS.CPP
*
* Modification History:*
*   Date        Name        Description
*
********************************************************************************
*/

#include "unicode/utypes.h"
#include "unicode/localpointer.h"
#include "unicode/uchar.h"
#include "unicode/unistr.h"
#include "unicode/ures.h"
#include "unicode/ustring.h"
#include "unicode/uloc.h"
#include "unicode/schriter.h"
#include "unicode/numsys.h"

#include "uresimp.h"

#if !UCONFIG_NO_FORMATTING

U_NAMESPACE_BEGIN

// Useful constants

#define DEFAULT_DIGITS UNICODE_STRING_SIMPLE("0123456789");
static const char gNumberingSystems[] = "numberingSystems";
static const char gDefaultNumberingSystem[] = "defaultNumberingSystem";
static const char gDesc[] = "desc";
static const char gRadix[] = "radix";
static const char gAlgorithmic[] = "algorithmic";


UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NumberingSystem)

    /**
     * Default Constructor.
     *
     * @draft ICU 4.2
     */

NumberingSystem::NumberingSystem() {
     radix = 10;
     algorithmic = FALSE;
     UnicodeString defaultDigits = DEFAULT_DIGITS;
     desc.setTo(defaultDigits);
}

    /**
     * Copy constructor.
     * @draft ICU 4.2
     */

NumberingSystem::NumberingSystem(const NumberingSystem& other) 
:  UObject(other) {
    *this=other;
}

NumberingSystem* U_EXPORT2
NumberingSystem::createInstance(int32_t radix_in, UBool isAlgorithmic_in, const UnicodeString & desc_in, UErrorCode &status) {

    if ( radix_in < 2 ) {
        status = U_ILLEGAL_ARGUMENT_ERROR;
        return NULL;
    }

    if ( !isAlgorithmic_in ) {
       if ( desc_in.countChar32() != radix_in || !isValidDigitString(desc_in)) {
           status = U_ILLEGAL_ARGUMENT_ERROR;
           return NULL;
       }
    }

    NumberingSystem *ns = new NumberingSystem();

    ns->setRadix(radix_in);
    ns->setDesc(desc_in);
    ns->setAlgorithmic(isAlgorithmic_in);
    return ns;
    
}


NumberingSystem* U_EXPORT2
NumberingSystem::createInstance(const Locale & inLocale, UErrorCode& status) {

    char buffer[ULOC_KEYWORDS_CAPACITY];
    int32_t count = inLocale.getKeywordValue("numbers",buffer, sizeof(buffer),status);
    if ( count > 0 ) { // @numbers keyword was specified in the locale
        buffer[count] = '\0'; // Make sure it is null terminated.
        return NumberingSystem::createInstanceByName(buffer,status);
    } else { // Find the default numbering system for this locale.
        LocalUResourceBundlePointer resource(ures_open(NULL, inLocale.getName(), &status));
        if (U_FAILURE(status)) {
            status = U_USING_FALLBACK_WARNING;
            NumberingSystem *ns = new NumberingSystem();
            return ns;
        } 
        const UChar *defaultNSName =
            ures_getStringByKeyWithFallback(resource.getAlias(), gDefaultNumberingSystem, &count, &status);
        if (U_FAILURE(status)) {
               return NULL;
        }
        if ( count > 0 && count < ULOC_KEYWORDS_CAPACITY ) { // Default numbering system found
           u_UCharsToChars(defaultNSName,buffer,count); 
           buffer[count] = '\0'; // Make sure it is null terminated.
           return NumberingSystem::createInstanceByName(buffer,status);
        } else {
            status = U_USING_FALLBACK_WARNING;
            NumberingSystem *ns = new NumberingSystem();
            return ns;
        }
        
    }
}

NumberingSystem* U_EXPORT2
NumberingSystem::createInstance(UErrorCode& status) {
    return NumberingSystem::createInstance(Locale::getDefault(), status);
}

NumberingSystem* U_EXPORT2
NumberingSystem::createInstanceByName(const char *name, UErrorCode& status) {
    
     UResourceBundle *numberingSystemsInfo = NULL;
     UResourceBundle *nsTop, *nsCurrent;
     const UChar* description = NULL;
     int32_t radix = 10;
     int32_t algorithmic = 0;
     int32_t len;

     numberingSystemsInfo = ures_openDirect(NULL,gNumberingSystems, &status);
     nsCurrent = ures_getByKey(numberingSystemsInfo,gNumberingSystems,NULL,&status);
     nsTop = ures_getByKey(nsCurrent,name,NULL,&status);
     description = ures_getStringByKey(nsTop,gDesc,&len,&status);

	 ures_getByKey(nsTop,gRadix,nsCurrent,&status);
     radix = ures_getInt(nsCurrent,&status);

     ures_getByKey(nsTop,gAlgorithmic,nsCurrent,&status);
     algorithmic = ures_getInt(nsCurrent,&status);

     UBool isAlgorithmic = ( algorithmic == 1 );
     UnicodeString nsd;
     nsd.setTo(description);

	 ures_close(nsCurrent);
	 ures_close(nsTop);
     ures_close(numberingSystemsInfo);

     if (U_FAILURE(status)) {
         status = U_UNSUPPORTED_ERROR;
         return NULL;
     }

     return NumberingSystem::createInstance(radix,isAlgorithmic,nsd,status);

}

    /**
     * Destructor.
     * @draft ICU 4.2
     */
NumberingSystem::~NumberingSystem() {
}

int32_t NumberingSystem::getRadix() {
    return radix;
}

UnicodeString NumberingSystem::getDescription() {
    return desc;
}

void NumberingSystem::setRadix(int32_t r) {
    radix = r;
}

void NumberingSystem::setAlgorithmic(UBool c) {
    algorithmic = c;
}

void NumberingSystem::setDesc(UnicodeString d) {
    desc.setTo(d);
}

UBool NumberingSystem::isAlgorithmic() const {
    return ( algorithmic );
}


UBool NumberingSystem::isValidDigitString(const UnicodeString& str) {

    StringCharacterIterator it(str);
    UChar32 c;
    UChar32 prev = 0;
    int32_t i = 0;

    for ( it.setToStart(); it.hasNext(); ) {
       c = it.next32PostInc();
       if ( u_charDigitValue(c) != i ) {  // Digits outside the Unicode decimal digit class are not currently supported
           return FALSE;
       }
       if ( prev != 0 && c != prev + 1 ) { // Non-contiguous digits are not currently supported
          return FALSE;
       }
       if ( c > 0xFFFF ) { // Digits outside the BMP are not currently supported
          return FALSE;
       }
       i++;
       prev = c;
    }
    return TRUE;   
}
U_NAMESPACE_END

#endif /* #if !UCONFIG_NO_FORMATTING */

//eof
