/*
 *******************************************************************************
 * Copyright (C) 2003, International Business Machines Corporation and         *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */

#include "unicode/utypes.h"

#if !UCONFIG_NO_COLLATION

#include "svccoll.h"
#include "unicode/coll.h"
#include "unicode/strenum.h"
#include "hash.h"

#include "ucol_imp.h" // internal api needed to test ucollator equality
#include "cstring.h" // internal api used to compare locale strings

void CollationServiceTest::TestRegister() 
{
  // register a singleton
    const Locale& FR = Locale::getFrance();
    const Locale& US = Locale::getUS();
    const Locale US_FOO("en", "US", "FOO");
    
    UErrorCode status = U_ZERO_ERROR;
    
    Collator* frcol = Collator::createInstance(FR, status);
    Collator* uscol = Collator::createInstance(US, status);
    if(U_FAILURE(status)) {
        errln("Failed to create collators with %s", u_errorName(status));
        delete frcol;
        delete uscol;
        return;
    }
    
    { // try override en_US collator
        URegistryKey key = Collator::registerInstance(frcol, US, status);
        
        Collator* ncol = Collator::createInstance(US_FOO, status);
        if (*frcol != *ncol) {
            errln("register of french collator for en_US failed on request for en_US_FOO");
        }
        // ensure original collator's params not touched
        Locale loc = frcol->getLocale(ULOC_REQUESTED_LOCALE, status);
        if (loc != FR) {
            errln(UnicodeString("fr collator's requested locale changed to ") + loc.getName());
        }
        loc = frcol->getLocale(ULOC_VALID_LOCALE, status);
        if (loc != FR) {
            errln(UnicodeString("fr collator's valid locale changed to ") + loc.getName());
        }
        
        loc = ncol->getLocale(ULOC_REQUESTED_LOCALE, status);
        if (loc != US_FOO) {
            errln(UnicodeString("requested locale for en_US_FOO is not en_US_FOO but ") + loc.getName());
        }
        loc = ncol->getLocale(ULOC_VALID_LOCALE, status);
        if (loc != US) {
            errln(UnicodeString("valid locale for en_US_FOO is not en_US but ") + loc.getName());
        }
        loc = ncol->getLocale(ULOC_ACTUAL_LOCALE, status);
        if (loc != US) {
            errln(UnicodeString("actual locale for en_US_FOO is not en_US but ") + loc.getName());
        }
        delete ncol; ncol = NULL;
        
        if (!Collator::unregister(key, status)) {
            errln("failed to unregister french collator");
        }
        // !!! frcol pointer is now invalid !!!
        
        ncol = Collator::createInstance(US, status);
        if (*uscol != *ncol) {
            errln("collator after unregister does not match original");
        }
        delete ncol; ncol = NULL;
    }
    
    // recreate frcol
    frcol = Collator::createInstance(FR, status);
    
    UCollator* frFR = ucol_open("fr_FR", &status);
    
    { // try create collator for new locale
        Locale fu_FU_FOO("fu", "FU", "FOO");
        Locale fu_FU("fu", "FU", "");
        
        Collator* fucol = Collator::createInstance(fu_FU, status);
        URegistryKey key = Collator::registerInstance(frcol, fu_FU, status);
        Collator* ncol = Collator::createInstance(fu_FU_FOO, status);
        if (*frcol != *ncol) {
            errln("register of fr collator for fu_FU failed");
        }
        
        UnicodeString locName = fu_FU.getName();
        StringEnumeration* localeEnum = Collator::getAvailableLocales();
        UBool found = FALSE;
        const UnicodeString* locStr, *ls2;
        for (locStr = localeEnum->snext(status);
        !found && locStr != NULL;
        locStr = localeEnum->snext(status)) {
            //
            if (locName == *locStr) {
                found = TRUE;
            }
        }

        StringEnumeration *le2 = NULL;
        localeEnum->reset(status);
        int32_t i, count;
        count = localeEnum->count(status);
        for(i = 0; i < count; ++i) {
            if(i == count / 2) {
                le2 = localeEnum->clone();
                if(le2 == NULL || count != le2->count(status)) {
                    errln("ServiceEnumeration.clone() failed");
                    break;
                }
            }
            if(i >= count / 2) {
                locStr = localeEnum->snext(status);
                ls2 = le2->snext(status);
                if(*locStr != *ls2) {
                    errln("ServiceEnumeration.clone() failed for item %d", i);
                }
            } else {
                localeEnum->snext(status);
            }
        }

        delete localeEnum;
        delete le2;
        
        if (!found) {
            errln("new locale fu_FU not reported as supported locale");
        }
        
        UnicodeString displayName;
        Collator::getDisplayName(fu_FU, displayName);
        if (displayName != "fu (FU)") {
            errln(UnicodeString("found ") + displayName + " for fu_FU");
        }
        
        Collator::getDisplayName(fu_FU, fu_FU, displayName);
        if (displayName != "fu (FU)") {
            errln(UnicodeString("found ") + displayName + " for fu_FU");
        }
        
        // test ucol_open
        UCollator* fufu = ucol_open("fu_FU_FOO", &status);
        if (!fufu) {
            errln("could not open fu_FU_FOO with ucol_open");
        } else {
            if (!ucol_equals(fufu, frFR)) {
                errln("collator fufu != collator frFR");
            }
        }
        
        if (!Collator::unregister(key, status)) {
            errln("failed to unregister french collator");
        }
        // !!! note frcoll invalid again, but we're no longer using it
        
        // other collators should still work ok
        Locale nloc = ncol->getLocale(ULOC_VALID_LOCALE, status);
        if (nloc != fu_FU) {
            errln(UnicodeString("asked for nloc valid locale after close and got") + nloc.getName());
        }
        delete ncol; ncol = NULL;
        
        if (fufu) {
            const char* nlocstr = ucol_getLocale(fufu, ULOC_VALID_LOCALE, &status);
            if (uprv_strcmp(nlocstr, "fu_FU") != 0) {
                errln(UnicodeString("asked for uloc valid locale after close and got ") + nlocstr);
            }
            ucol_close(fufu);
        }
        ucol_close(frFR);
        
        ncol = Collator::createInstance(fu_FU, status);
        if (*fucol != *ncol) {
            errln("collator after unregister does not match original fu_FU");
        }
        delete uscol; uscol = NULL;
        delete ncol; ncol = NULL;
        delete fucol; fucol = NULL;
    }
}

// ------------------

struct CollatorInfo {
  Locale locale;
  Collator* collator;
  Hashtable* displayNames; // locale name -> string

  CollatorInfo(const Locale& locale, Collator* collatorToAdopt, Hashtable* displayNamesToAdopt);
  ~CollatorInfo();
  UnicodeString& getDisplayName(const Locale& displayLocale, UnicodeString& name) const;
};

CollatorInfo::CollatorInfo(const Locale& _locale, Collator* _collator, Hashtable* _displayNames)
  : locale(_locale)
  , collator(_collator)
  , displayNames(_displayNames)
{
}

CollatorInfo::~CollatorInfo() {
  delete collator;
  delete displayNames;
}

UnicodeString& 
CollatorInfo::getDisplayName(const Locale& displayLocale, UnicodeString& name) const {
  if (displayNames) {
    UnicodeString* val = (UnicodeString*)displayNames->get(displayLocale.getName());
    if (val) {
      name = *val;
      return name;
    }
  }

  return locale.getDisplayName(displayLocale, name);
}

// ---------------

class TestFactory : public CollatorFactory {
  CollatorInfo** info;
  int32_t count;
  UnicodeString* ids;

  const CollatorInfo* getInfo(const Locale& loc) const {
    for (CollatorInfo** p = info; *p; ++p) {
      if (loc == (**p).locale) {
        return *p;
      }
    }
    return NULL;
  }

public:       
  TestFactory(CollatorInfo** _info) 
    : info(_info)
    , count(0)
    , ids(NULL)
  {
    CollatorInfo** p;
    for (p = info; *p; ++p) {}
    count = p - info;
  }

  ~TestFactory() {
    for (CollatorInfo** p = info; *p; ++p) {
      delete *p;
    }
    delete[] info;
    delete[] ids;
  }

  virtual Collator* createCollator(const Locale& loc) {
    const CollatorInfo* ci = getInfo(loc);
    if (ci) {
      return ci->collator->clone();
    }
    return NULL;
  }

  virtual UnicodeString& getDisplayName(const Locale& objectLocale, 
                                        const Locale& displayLocale,
                                        UnicodeString& result)
  {
    const CollatorInfo* ci = getInfo(objectLocale);
    if (ci) {
      ci->getDisplayName(displayLocale, result);
    } else {
      result.setToBogus();
    }
    return result;
  }

  const UnicodeString* getSupportedIDs(int32_t& _count, UErrorCode& status) {
    if (U_SUCCESS(status)) {
      if (!ids) {
        ids = new UnicodeString[count];
        if (!ids) {
          status = U_MEMORY_ALLOCATION_ERROR;
          _count = 0;
          return NULL;
        }

        for (int i = 0; i < count; ++i) {
          ids[i] = info[i]->locale.getName();
        }
      }

      _count = count;
      return ids;
    }
    return NULL;
  }

  virtual inline UClassID getDynamicClassID() const {
    return (UClassID)&gClassID;
  }

  static UClassID getStaticClassID() {
    return (UClassID)&gClassID;
  }

private:
  static char gClassID;
};

char TestFactory::gClassID = 0;

void CollationServiceTest::TestRegisterFactory(void) 
{
    Locale fu_FU("fu", "FU", "");
    Locale fu_FU_FOO("fu", "FU", "FOO");
    
    UErrorCode status = U_ZERO_ERROR;
    
    Hashtable* fuFUNames = new Hashtable(FALSE, status);
    if (!fuFUNames) {
        errln("memory allocation error");
        return;
    }
    fuFUNames->setValueDeleter(uhash_deleteUnicodeString);
    
    fuFUNames->put(fu_FU.getName(), new UnicodeString("ze leetle bunny Fu-Fu"), status);
    fuFUNames->put(fu_FU_FOO.getName(), new UnicodeString("zee leetel bunny Foo-Foo"), status);
    fuFUNames->put(Locale::getUS().getName(), new UnicodeString("little bunny Foo Foo"), status);
    
    Collator* frcol = Collator::createInstance(Locale::getFrance(), status);
    Collator* gecol = Collator::createInstance(Locale::getGermany(), status);
    Collator* jpcol = Collator::createInstance(Locale::getJapan(), status);
    if(U_FAILURE(status)) {
      errln("Failed to create collators with %s", u_errorName(status));
      delete frcol;
      delete gecol;
      delete jpcol;
      delete fuFUNames;
      return;
    }
    
    CollatorInfo** info = new CollatorInfo*[4];
    if (!info) {
        errln("memory allocation error");
        return;
    }
    
    info[0] = new CollatorInfo(Locale::getUS(), frcol, NULL);
    info[1] = new CollatorInfo(Locale::getFrance(), gecol, NULL);
    info[2] = new CollatorInfo(fu_FU, jpcol, fuFUNames);
    info[3] = NULL;
    
    TestFactory* factory = new TestFactory(info);
    if (!factory) {
        errln("memory allocation error");
        return;
    }
    
    Collator* uscol = Collator::createInstance(Locale::getUS(), status);
    Collator* fucol = Collator::createInstance(fu_FU, status);
    
    {
        URegistryKey key = Collator::registerFactory(factory, status);
        Collator* ncol = Collator::createInstance(Locale::getUS(), status);
        if (*frcol != *ncol) {
            errln("frcoll for en_US failed");
        }
        delete ncol; ncol = NULL;
        
        ncol = Collator::createInstance(fu_FU_FOO, status);
        if (*jpcol != *ncol) {
            errln("jpcol for fu_FU_FOO failed");
        }
        
        Locale loc = ncol->getLocale(ULOC_REQUESTED_LOCALE, status);
        if (loc != fu_FU_FOO) {
            errln(UnicodeString("requested locale for fu_FU_FOO is not fu_FU_FOO but ") + loc.getName());
        }
        loc = ncol->getLocale(ULOC_VALID_LOCALE, status);
        if (loc != fu_FU) {
            errln(UnicodeString("valid locale for fu_FU_FOO is not fu_FU but ") + loc.getName());
        }
        delete ncol; ncol = NULL;
        
        UnicodeString locName = fu_FU.getName();
        StringEnumeration* localeEnum = Collator::getAvailableLocales();
        UBool found = FALSE;
        const UnicodeString* locStr;
        for (locStr = localeEnum->snext(status);
            !found && locStr != NULL;
            locStr = localeEnum->snext(status))
        {
            if (locName == *locStr) {
                found = TRUE;
            }
        }
        delete localeEnum;
        
        if (!found) {
            errln("new locale fu_FU not reported as supported locale");
        }
        
        UnicodeString name;
        Collator::getDisplayName(fu_FU, name);
        if (name != "little bunny Foo Foo") {
            errln(UnicodeString("found ") + name + " for fu_FU");
        }
        
        Collator::getDisplayName(fu_FU, fu_FU_FOO, name);
        if (name != "zee leetel bunny Foo-Foo") {
            errln(UnicodeString("found ") + name + " for fu_FU in fu_FU_FOO");
        }
        
        if (!Collator::unregister(key, status)) {
            errln("failed to unregister factory");
        }
        // ja, fr, ge collators no longer valid
        
        ncol = Collator::createInstance(fu_FU, status);
        if (*fucol != *ncol) {
            errln("collator after unregister does not match original fu_FU");
        }
	delete ncol;
    }
    
    delete fucol;
    delete uscol;
}

void CollationServiceTest::runIndexedTest(int32_t index, UBool exec, const char* &name, char* /*par */)
{
    if (exec) logln("TestSuite CollationServiceTest: ");
    switch (index) {
        TESTCASE(0, TestRegister);
        TESTCASE(1, TestRegisterFactory);
    default: name = ""; break;
    }
}

#endif
