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

#include "utypeinfo.h"  // for 'typeid' to work

#include "unicode/utypes.h"

#if !UCONFIG_NO_SERVICE

#include "cmemory.h"
#include "icusvtst.h"
#include "servloc.h"
#include <stdio.h>


class MyListener : public EventListener {
};

class WrongListener : public EventListener {
};

class ICUNSubclass : public ICUNotifier {
    public:
    UBool acceptsListener(const EventListener& /*l*/) const override {
        return true;
        // return l instanceof MyListener;
    }

    virtual void notifyListener(EventListener& /*l*/) const override {
    }
};

// This factory does nothing
class LKFSubclass0 : public LocaleKeyFactory {
public:
        LKFSubclass0()
                : LocaleKeyFactory(VISIBLE, "LKFSubclass0")
        {
        }
};

class LKFSubclass : public LocaleKeyFactory {
    Hashtable table;

    public:
    LKFSubclass(UBool visible) 
        : LocaleKeyFactory(visible ? VISIBLE : INVISIBLE, "LKFSubclass")
    {
        UErrorCode status = U_ZERO_ERROR;
        table.put("en_US", this, status);
    }

    protected:
    virtual const Hashtable* getSupportedIDs(UErrorCode &/*status*/) const override {
        return &table;
    }
};

class Integer : public UObject {
    public:
    const int32_t _val;

    Integer(int32_t val) : _val(val) {
    }

    Integer(const Integer& rhs) : UObject(rhs), _val(rhs._val) {
    }
    virtual ~Integer() {
    }

    public:
    /**
     * UObject boilerplate.
     */
    static UClassID getStaticClassID() { 
        return (UClassID)&fgClassID;
    }

    virtual UClassID getDynamicClassID() const override {
        return getStaticClassID();
    }

    virtual bool operator==(const UObject& other) const
    {
        return typeid(*this) == typeid(other) &&
            _val == ((Integer&)other)._val;
    }

    public:
    virtual UnicodeString& debug(UnicodeString& result) const {
        debugClass(result);
        result.append(" val: ");
        result.append(_val);
        return result;
    }

    virtual UnicodeString& debugClass(UnicodeString& result) const {
        return result.append("Integer");
    }

    private:
    static const char fgClassID;
};

const char Integer::fgClassID = '\0';

// use locale keys
class TestIntegerService : public ICUService {
    public:
    ICUServiceKey* createKey(const UnicodeString* id, UErrorCode& status) const override {
        return LocaleKey::createWithCanonicalFallback(id, NULL, status); // no fallback locale
    }

    virtual ICUServiceFactory* createSimpleFactory(UObject* obj, const UnicodeString& id, UBool visible, UErrorCode& status) override
    {
        Integer* i;
        if (U_SUCCESS(status) && obj && (i = dynamic_cast<Integer*>(obj)) != NULL) {
            return new SimpleFactory(i, id, visible);
        }
        return NULL;
    }

    virtual UObject* cloneInstance(UObject* instance) const override {
        return instance ? new Integer(*(Integer*)instance) : NULL;
    }
};


ICUServiceTest::ICUServiceTest() {
}

ICUServiceTest::~ICUServiceTest() {
}

void 
ICUServiceTest::runIndexedTest(int32_t index, UBool exec, const char* &name,
char* /*par*/)
{
    switch (index) {
        TESTCASE(0,testAPI_One);
        TESTCASE(1,testAPI_Two);
        TESTCASE(2,testRBF);
        TESTCASE(3,testNotification);
        TESTCASE(4,testLocale);
        TESTCASE(5,testWrapFactory);
        TESTCASE(6,testCoverage);
    default: name = ""; break;
    }
}

UnicodeString append(UnicodeString& result, const UObject* obj) 
{
    char buffer[128];
    if (obj == NULL) {
        result.append("NULL");
    } else {
        const UnicodeString* s;
        const Locale* loc;
        const Integer* i;
        if ((s = dynamic_cast<const UnicodeString*>(obj)) != NULL) {
            result.append(*s);
        } else if ((loc = dynamic_cast<const Locale*>(obj)) != NULL) {
            result.append(loc->getName());
        } else if ((i = dynamic_cast<const Integer*>(obj)) != NULL) {
            snprintf(buffer, sizeof(buffer), "%d", (int)i->_val);
            result.append(buffer);
        } else {
            snprintf(buffer, sizeof(buffer), "%p", (const void*)obj);
            result.append(buffer);
        }
    }
    return result;
}

UnicodeString& 
ICUServiceTest::lrmsg(UnicodeString& result, const UnicodeString& message, const UObject* lhs, const UObject* rhs) const 
{
    result.append(message);
    result.append(" lhs: ");
    append(result, lhs);
    result.append(", rhs: ");
    append(result, rhs);
    return result;
}

void 
ICUServiceTest::confirmBoolean(const UnicodeString& message, UBool val)
{
    if (val) {
        logln(message);
    } else {
        errln(message);
    }
}

#if 0
void
ICUServiceTest::confirmEqual(const UnicodeString& message, const UObject* lhs, const UObject* rhs) 
{
    UBool equ = (lhs == NULL)
        ? (rhs == NULL)
        : (rhs != NULL && lhs->operator==(*rhs));

    UnicodeString temp;
    lrmsg(temp, message, lhs, rhs);

    if (equ) {
        logln(temp);
    } else {
        errln(temp);
    }
}
#else
void
ICUServiceTest::confirmEqual(const UnicodeString& message, const Integer* lhs, const Integer* rhs) 
{
    UBool equ = (lhs == NULL)
        ? (rhs == NULL)
        : (rhs != NULL && lhs->operator==(*rhs));

    UnicodeString temp;
    lrmsg(temp, message, lhs, rhs);

    if (equ) {
        logln(temp);
    } else {
        errln(temp);
    }
}

void
ICUServiceTest::confirmEqual(const UnicodeString& message, const UnicodeString* lhs, const UnicodeString* rhs) 
{
    UBool equ = (lhs == NULL)
        ? (rhs == NULL)
        : (rhs != NULL && lhs->operator==(*rhs));

    UnicodeString temp;
    lrmsg(temp, message, lhs, rhs);

    if (equ) {
        logln(temp);
    } else {
        errln(temp);
    }
}

void
ICUServiceTest::confirmEqual(const UnicodeString& message, const Locale* lhs, const Locale* rhs) 
{
    UBool equ = (lhs == NULL)
        ? (rhs == NULL)
        : (rhs != NULL && lhs->operator==(*rhs));

    UnicodeString temp;
    lrmsg(temp, message, lhs, rhs);

    if (equ) {
        logln(temp);
    } else {
        errln(temp);
    }
}
#endif

// use these for now
void
ICUServiceTest::confirmStringsEqual(const UnicodeString& message, const UnicodeString& lhs, const UnicodeString& rhs) 
{
    UBool equ = lhs == rhs;

    UnicodeString temp = message;
    temp.append(" lhs: ");
    temp.append(lhs);
    temp.append(" rhs: ");
    temp.append(rhs);

    if (equ) {
        logln(temp);
    } else {
        dataerrln(temp);
    }
}


void 
ICUServiceTest::confirmIdentical(const UnicodeString& message, const UObject* lhs, const UObject *rhs) 
{
    UnicodeString temp;
    lrmsg(temp, message, lhs, rhs);
    if (lhs == rhs) {
        logln(temp);
    } else {
        errln(temp);
    }
}

void
ICUServiceTest::confirmIdentical(const UnicodeString& message, int32_t lhs, int32_t rhs)  
{
    if (lhs == rhs) {
        logln(message + " lhs: " + lhs + " rhs: " + rhs);
    } else {
        errln(message + " lhs: " + lhs + " rhs: " + rhs);
    }
}

void
ICUServiceTest::msgstr(const UnicodeString& message, UObject* obj, UBool err)
{
    if (obj) {
    UnicodeString* str = (UnicodeString*)obj;
        logln(message + *str);
        delete str;
    } else if (err) {
        errln("Error " + message + "string is NULL");
    }
}

void 
ICUServiceTest::testAPI_One() 
{
    // create a service using locale keys,
    TestIntegerService service;

    // register an object with one locale, 
    // search for an object with a more specific locale
    // should return the original object
    UErrorCode status = U_ZERO_ERROR;
    Integer* singleton0 = new Integer(0);
    service.registerInstance(singleton0, "en_US", status);
    {
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("en_US_FOO", status);
        confirmEqual("1) en_US_FOO -> en_US", result, singleton0);
        delete result;
    }

    // register a new object with the more specific locale
    // search for an object with that locale
    // should return the new object
    Integer* singleton1 = new Integer(1);
    service.registerInstance(singleton1, "en_US_FOO", status);
    {
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("en_US_FOO", status);
        confirmEqual("2) en_US_FOO -> en_US_FOO", result, singleton1);
        delete result;
    }

    // search for an object that falls back to the first registered locale
    {
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("en_US_BAR", status);
        confirmEqual("3) en_US_BAR -> en_US", result, singleton0);
        delete result;
    }

    // get a list of the factories, should be two
    {
        confirmIdentical("4) factory size", service.countFactories(), 2);
    }

    // register a new object with yet another locale
    Integer* singleton2 = new Integer(2);
    service.registerInstance(singleton2, "en", status);
    {
        confirmIdentical("5) factory size", service.countFactories(), 3);
    }

    // search for an object with the new locale
    // stack of factories is now en, en_US_FOO, en_US
    // search for en_US should still find en_US object
    {
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("en_US_BAR", status);
        confirmEqual("6) en_US_BAR -> en_US", result, singleton0);
        delete result;
    }

    // register a new object with an old id, should hide earlier factory using this id, but leave it there
    Integer* singleton3 = new Integer(3);
    URegistryKey s3key = service.registerInstance(singleton3, "en_US", status);
    {
        confirmIdentical("9) factory size", service.countFactories(), 4);
    }

    // should get data from that new factory
    {
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("en_US_BAR", status);
        confirmEqual("10) en_US_BAR -> (3)", result, singleton3);
        delete result;
    }

    // remove new factory
    // should have fewer factories again
    // singleton3 dead!
    {
        UErrorCode status = U_ZERO_ERROR;
        service.unregister(s3key, status);
        confirmIdentical("11) factory size", service.countFactories(), 3);
    }

    // should get original data again after remove factory
    {
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("en_US_BAR", status);
        confirmEqual("12) en_US_BAR -> (3)", result, singleton0);
        delete result;
    }

    // shouldn't find unregistered ids
    {
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("foo", status);
        confirmIdentical("13) foo -> null", result, NULL);
        delete result;
    }

    // should find non-canonical strings
    {
        UnicodeString resultID;
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("EN_us_fOo", &resultID, status);
        confirmEqual("14a) find-non-canonical", result, singleton1);
        confirmStringsEqual("14b) find non-canonical", resultID, "en_US_FOO");
        delete result;
    }

    // should be able to register non-canonical strings and get them canonicalized
    Integer* singleton4 = new Integer(4);
    service.registerInstance(singleton4, "eN_ca_dUde", status);
    {
        UnicodeString resultID;
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("En_Ca_DuDe", &resultID, status);
        confirmEqual("15a) find-non-canonical", result, singleton4);
        confirmStringsEqual("15b) register non-canonical", resultID, "en_CA_DUDE");
        delete result;
    }

    // should be able to register invisible factories, these will not
    // be visible by default, but if you know the secret password you
    // can still access these services...
    Integer* singleton5 = new Integer(5);
    service.registerInstance(singleton5, "en_US_BAR", false, status);
    {
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("en_US_BAR", status);
        confirmEqual("17) get invisible", result, singleton5);
        delete result;
    }
    
    // should not be able to locate invisible services
    {
        UErrorCode status = U_ZERO_ERROR;
        UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, status);
        service.getVisibleIDs(ids, status);
        UnicodeString target = "en_US_BAR";
        confirmBoolean("18) find invisible", !ids.contains(&target));
    }

    // clear factory and caches
    service.reset();
    confirmBoolean("19) is default", service.isDefault());
}

/*
 ******************************************************************
 */
class TestStringSimpleKeyService : public ICUService {
public:
 
        virtual ICUServiceFactory* createSimpleFactory(UObject* obj, const UnicodeString& id, UBool visible, UErrorCode& status) override
    {
                // We could put this type check into ICUService itself, but we'd still
                // have to implement cloneInstance.  Otherwise we could just tell the service
                // what the object type is when we create it, and the default implementation
                // could handle everything for us.  Phooey.
        if (obj && dynamic_cast<UnicodeString*>(obj) != NULL) {
                        return ICUService::createSimpleFactory(obj, id, visible, status);
        }
        return NULL;
    }

    virtual UObject* cloneInstance(UObject* instance) const override {
        return instance ? new UnicodeString(*(UnicodeString*)instance) : NULL;
    }
};

class TestStringService : public ICUService {
    public:
    ICUServiceKey* createKey(const UnicodeString* id, UErrorCode& status) const override {
        return LocaleKey::createWithCanonicalFallback(id, NULL, status); // no fallback locale
    }

  virtual ICUServiceFactory* createSimpleFactory(UObject* obj, const UnicodeString& id, UBool visible, UErrorCode& /* status */) override
    {
        UnicodeString* s;
        if (obj && (s = dynamic_cast<UnicodeString*>(obj)) != NULL) {
            return new SimpleFactory(s, id, visible);
        }
        return NULL;
    }

    virtual UObject* cloneInstance(UObject* instance) const override {
        return instance ? new UnicodeString(*(UnicodeString*)instance) : NULL;
    }
};

// this creates a string for any id, but doesn't report anything
class AnonymousStringFactory : public ICUServiceFactory
{
    public:
    virtual UObject* create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& /* status */) const override {
        return new UnicodeString(key.getID());
    }

    virtual void updateVisibleIDs(Hashtable& /*result*/, UErrorCode& /*status*/) const override {
        // do nothing
    }

    virtual UnicodeString& getDisplayName(const UnicodeString& /*id*/, const Locale& /*locale*/, UnicodeString& result) const override {
        // do nothing
        return result;
    }

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

    virtual UClassID getDynamicClassID() const override {
        return getStaticClassID();
    }

    private:
    static const char fgClassID;
};

const char AnonymousStringFactory::fgClassID = '\0';

class TestMultipleKeyStringFactory : public ICUServiceFactory {
    UErrorCode _status;
    UVector _ids;
    UnicodeString _factoryID;

    public:
    TestMultipleKeyStringFactory(const UnicodeString ids[], int32_t count, const UnicodeString& factoryID)
        : _status(U_ZERO_ERROR)
        , _ids(uprv_deleteUObject, uhash_compareUnicodeString, count, _status)
        , _factoryID(factoryID + ": ") 
    {
        for (int i = 0; i < count; ++i) {
            _ids.adoptElement(new UnicodeString(ids[i]), _status);
        }
    }
  
    ~TestMultipleKeyStringFactory() {
    }

    UObject* create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const override {
        if (U_FAILURE(status)) {
        return NULL;
        }
        UnicodeString temp;
        key.currentID(temp);
        if (U_SUCCESS(_status)) {
        if (_ids.contains(&temp)) {
                return new UnicodeString(_factoryID + temp);
        }
        } else {
        status = _status;
    }
        return NULL;
    }

    void updateVisibleIDs(Hashtable& result, UErrorCode& status) const override {
        if (U_SUCCESS(_status)) {
            for (int32_t i = 0; i < _ids.size(); ++i) {
                result.put(*(UnicodeString*)_ids[i], (void*)this, status);
            }
        }
    }

    UnicodeString& getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const override {
        if (U_SUCCESS(_status) && _ids.contains((void*)&id)) {
            char buffer[128];
            UErrorCode status = U_ZERO_ERROR;
            int32_t len = id.extract(buffer, sizeof(buffer), NULL, status);
            if (U_SUCCESS(status)) {
                if (len == sizeof(buffer)) {
                    --len;
                }
                buffer[len] = 0;
                Locale loc = Locale::createFromName(buffer);
                loc.getDisplayName(locale, result);
                return result;
            }
        }
        result.setToBogus(); // shouldn't happen
        return result;
    }

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

    virtual UClassID getDynamicClassID() const override {
        return getStaticClassID();
    }

    private:
    static const char fgClassID;
};

const char TestMultipleKeyStringFactory::fgClassID = '\0';

void 
ICUServiceTest::testAPI_Two()
{
    UErrorCode status = U_ZERO_ERROR;
    TestStringService service;
    service.registerFactory(new AnonymousStringFactory(), status);

    // anonymous factory will still handle the id
    {
        UErrorCode status = U_ZERO_ERROR;
        const UnicodeString en_US = "en_US";
        UnicodeString* result = (UnicodeString*)service.get(en_US, status);
        confirmEqual("21) locale", result, &en_US);
        delete result;
    }

    // still normalizes id
    {
        UErrorCode status = U_ZERO_ERROR;
        const UnicodeString en_US_BAR = "en_US_BAR";
        UnicodeString resultID;
        UnicodeString* result = (UnicodeString*)service.get("EN_us_bar", &resultID, status);
        confirmEqual("22) locale", &resultID, &en_US_BAR);
        delete result;
    }

    // we can override for particular ids
    UnicodeString* singleton0 = new UnicodeString("Zero");
    service.registerInstance(singleton0, "en_US_BAR", status);
    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* result = (UnicodeString*)service.get("en_US_BAR", status);
        confirmEqual("23) override super", result, singleton0);
        delete result;
    }

    // empty service should not recognize anything 
    service.reset();
    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* result = (UnicodeString*)service.get("en_US", status);
        confirmIdentical("24) empty", result, NULL);
    }

    // create a custom multiple key factory
    {
        UnicodeString xids[] = {
            "en_US_VALLEY_GIRL", 
            "en_US_VALLEY_BOY",
            "en_US_SURFER_GAL",
            "en_US_SURFER_DUDE"
        };
        int32_t count = UPRV_LENGTHOF(xids);

        ICUServiceFactory* f = new TestMultipleKeyStringFactory(xids, count, "Later");
        service.registerFactory(f, status);
    }

    // iterate over the visual ids returned by the multiple factory
    {
        UErrorCode status = U_ZERO_ERROR;
        UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, 0, status);
        service.getVisibleIDs(ids, status);
        for (int i = 0; i < ids.size(); ++i) {
            const UnicodeString* id = (const UnicodeString*)ids[i];
            UnicodeString* result = (UnicodeString*)service.get(*id, status);
            if (result) {
                logln("  " + *id + " --> " + *result);
                delete result;
            } else {
                errln("could not find " + *id);
            }
        }
        // four visible ids
        confirmIdentical("25) visible ids", ids.size(), 4);
    }

    // iterate over the display names
    {
        UErrorCode status = U_ZERO_ERROR;
        UVector names(status);
        service.getDisplayNames(names, status);
        for (int i = 0; i < names.size(); ++i) {
            const StringPair* pair = (const StringPair*)names[i];
            logln("  " + pair->displayName + " --> " + pair->id);
        }
        confirmIdentical("26) display names", names.size(), 4);
    }

    // no valid display name
    {
        UnicodeString name;
        service.getDisplayName("en_US_VALLEY_GEEK", name);
        confirmBoolean("27) get display name", name.isBogus());
    }

    {
        UnicodeString name;
        service.getDisplayName("en_US_SURFER_DUDE", name, Locale::getEnglish());
        confirmStringsEqual("28) get display name", name, "English (United States, SURFER_DUDE)");
    }

    // register another multiple factory
    {
        UnicodeString xids[] = {
            "en_US_SURFER", 
            "en_US_SURFER_GAL", 
            "en_US_SILICON", 
            "en_US_SILICON_GEEK",
        };
        int32_t count = UPRV_LENGTHOF(xids);

        ICUServiceFactory* f = new TestMultipleKeyStringFactory(xids, count, "Rad dude");
        service.registerFactory(f, status);
    }

    // this time, we have seven display names
    // Rad dude's surfer gal 'replaces' Later's surfer gal
    {
        UErrorCode status = U_ZERO_ERROR;
        UVector names(status);
        service.getDisplayNames(names, Locale("es"), status);
        for (int i = 0; i < names.size(); ++i) {
            const StringPair* pair = (const StringPair*)names[i];
            logln("  " + pair->displayName + " --> " + pair->id);
        }
        confirmIdentical("29) display names", names.size(), 7);
    }

    // we should get the display name corresponding to the actual id
    // returned by the id we used.
    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString actualID;
        UnicodeString id = "en_us_surfer_gal";
        UnicodeString* gal = (UnicodeString*)service.get(id, &actualID, status);
        if (gal != NULL) {
            UnicodeString displayName;
            logln("actual id: " + actualID);
            service.getDisplayName(actualID, displayName, Locale::getEnglish());
            logln("found actual: " + *gal + " with display name: " + displayName);
            confirmBoolean("30) found display name for actual", !displayName.isBogus());

            service.getDisplayName(id, displayName, Locale::getEnglish());
            logln("found actual: " + *gal + " with display name: " + displayName);
            confirmBoolean("31) found display name for query", displayName.isBogus());

            delete gal;
        } else {
            errln("30) service could not find entry for " + id);
        }
    }

    // this should be handled by the 'dude' factory, since it overrides en_US_SURFER.
    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString actualID;
        UnicodeString id = "en_US_SURFER_BOZO";
        UnicodeString* bozo = (UnicodeString*)service.get(id, &actualID, status);
        if (bozo != NULL) {
            UnicodeString displayName;
            service.getDisplayName(actualID, displayName, Locale::getEnglish());
            logln("found actual: " + *bozo + " with display name: " + displayName);
            confirmBoolean("32) found display name for actual", !displayName.isBogus());

            service.getDisplayName(id, displayName, Locale::getEnglish());
            logln("found actual: " + *bozo + " with display name: " + displayName);
            confirmBoolean("33) found display name for query", displayName.isBogus());

            delete bozo;
        } else {
            errln("32) service could not find entry for " + id);
        }
    }

    // certainly not default...
    {
        confirmBoolean("34) is default ", !service.isDefault());
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, 0, status);
        service.getVisibleIDs(ids, status);
        for (int i = 0; i < ids.size(); ++i) {
            const UnicodeString* id = (const UnicodeString*)ids[i];
            msgstr(*id + "? ", service.get(*id, status));
        }

        logstr("valleygirl?  ", service.get("en_US_VALLEY_GIRL", status));
        logstr("valleyboy?   ", service.get("en_US_VALLEY_BOY", status));
        logstr("valleydude?  ", service.get("en_US_VALLEY_DUDE", status));
        logstr("surfergirl?  ", service.get("en_US_SURFER_GIRL", status));
    }
}


class CalifornioLanguageFactory : public ICUResourceBundleFactory 
{
    public:
    static const char* californio; // = "en_US_CA";
    static const char* valley; // = californio ## "_VALLEY";
    static const char* surfer; // = californio ## "_SURFER";
    static const char* geek; // = californio ## "_GEEK";
    static Hashtable* supportedIDs; // = NULL;

    static void cleanup(void) {
      delete supportedIDs;
      supportedIDs = NULL;
    }

    const Hashtable* getSupportedIDs(UErrorCode& status) const override
    {
        if (supportedIDs == NULL) {
            Hashtable* table = new Hashtable();
            table->put(UnicodeString(californio), (void*)table, status);
            table->put(UnicodeString(valley), (void*)table, status);
            table->put(UnicodeString(surfer), (void*)table, status);
            table->put(UnicodeString(geek), (void*)table, status);

            // not necessarily atomic, but this is a test...
            supportedIDs = table;
        }
        return supportedIDs;
    }

    UnicodeString& getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const override
    {
        UnicodeString prefix = "";
        UnicodeString suffix = "";
        UnicodeString ls = locale.getName();
        if (LocaleUtility::isFallbackOf(californio, ls)) {
            if (!ls.caseCompare(valley, 0)) {
                prefix = "Like, you know, it's so totally ";
            } else if (!ls.caseCompare(surfer, 0)) {
                prefix = "Dude, it's ";
            } else if (!ls.caseCompare(geek, 0)) {
                prefix = "I'd estimate it is approximately ";
            } else {
                prefix = "Huh?  Maybe ";
            }
        }
        if (LocaleUtility::isFallbackOf(californio, id)) {
            if (!id.caseCompare(valley, 0)) {
                suffix = "like the Valley, you know?  Let's go to the mall!";
            } else if (!id.caseCompare(surfer, 0)) {
                suffix = "time to hit those gnarly waves, Dude!!!";
            } else if (!id.caseCompare(geek, 0)) {
                suffix = "all systems go.  T-Minus 9, 8, 7...";
            } else {
                suffix = "No Habla Englais";
            }
        } else {
            suffix = ICUResourceBundleFactory::getDisplayName(id, locale, result);
        }

        result = prefix + suffix;
        return result;
    }
};

const char* CalifornioLanguageFactory::californio = "en_US_CA";
const char* CalifornioLanguageFactory::valley = "en_US_CA_VALLEY";
const char* CalifornioLanguageFactory::surfer = "en_US_CA_SURFER";
const char* CalifornioLanguageFactory::geek = "en_US_CA_GEEK";
Hashtable* CalifornioLanguageFactory::supportedIDs = NULL;

void
ICUServiceTest::testRBF()
{
    // resource bundle factory.
    UErrorCode status = U_ZERO_ERROR;
    TestStringService service;
    service.registerFactory(new ICUResourceBundleFactory(), status);

    // list all of the resources 
    {
        UErrorCode status = U_ZERO_ERROR;
        UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, 0, status);
        service.getVisibleIDs(ids, status);
        logln("all visible ids:");
        for (int i = 0; i < ids.size(); ++i) {
            const UnicodeString* id = (const UnicodeString*)ids[i];
            logln(*id);
        }
    }

    // get all the display names of these resources
    // this should be fast since the display names were cached.
    {
        UErrorCode status = U_ZERO_ERROR;
        UVector names(status);
        service.getDisplayNames(names, Locale::getGermany(), status);
        logln("service display names for de_DE");
        for (int i = 0; i < names.size(); ++i) {
            const StringPair* pair = (const StringPair*)names[i];
            logln("  " + pair->displayName + " --> " + pair->id);
        }
    }

    service.registerFactory(new CalifornioLanguageFactory(), status);

    // get all the display names of these resources
    {
        logln("californio language factory:");
        const char* idNames[] = {
            CalifornioLanguageFactory::californio, 
            CalifornioLanguageFactory::valley, 
            CalifornioLanguageFactory::surfer, 
            CalifornioLanguageFactory::geek,
        };
        int32_t count = UPRV_LENGTHOF(idNames);

        for (int i = 0; i < count; ++i) {
            logln(UnicodeString("\n  --- ") + idNames[i] + " ---");
            {
                UErrorCode status = U_ZERO_ERROR;
                UVector names(status);
                service.getDisplayNames(names, idNames[i], status);
                for (int i = 0; i < names.size(); ++i) {
                    const StringPair* pair = (const StringPair*)names[i];
                    logln("  " + pair->displayName + " --> " + pair->id);
                }
            }
        }
    }
    CalifornioLanguageFactory::cleanup();
}

class SimpleListener : public ServiceListener {
    ICUServiceTest* _test;
    UnicodeString _name;

    public:
    SimpleListener(ICUServiceTest* test, const UnicodeString& name) : _test(test), _name(name) {}

    virtual void serviceChanged(const ICUService& service) const override {
        UnicodeString serviceName = "listener ";
        serviceName.append(_name);
        serviceName.append(" n++");
        serviceName.append(" service changed: " );
        service.getName(serviceName);
        _test->logln(serviceName);
    }
};

void
ICUServiceTest::testNotification()
{
    SimpleListener one(this, "one");
    SimpleListener two(this, "two");
    {
        UErrorCode status = U_ZERO_ERROR;

        logln("simple registration notification");
        TestStringService ls;
        ls.addListener(&one, status);
        ls.addListener(&two, status);

        logln("registering foo... ");
        ls.registerInstance(new UnicodeString("Foo"), "en_FOO", status);
        logln("registering bar... ");
        ls.registerInstance(new UnicodeString("Bar"), "en_BAR", status);
        logln("getting foo...");
        UnicodeString* result = (UnicodeString*)ls.get("en_FOO", status);
        logln(*result);
        delete result;

        logln("removing listener 2...");
        ls.removeListener(&two, status);
        logln("registering baz...");
        ls.registerInstance(new UnicodeString("Baz"), "en_BAZ", status);
        logln("removing listener 1");
        ls.removeListener(&one, status);
        logln("registering burp...");
        ls.registerInstance(new UnicodeString("Burp"), "en_BURP", status);

        // should only get one notification even if register multiple times
        logln("... trying multiple registration");
        ls.addListener(&one, status);
        ls.addListener(&one, status);
        ls.addListener(&one, status);
        ls.addListener(&two, status);
        ls.registerInstance(new UnicodeString("Foo"), "en_FOO", status);
        logln("... registered foo");
    }
#if 0
    // same thread, so we can't callback within notification, unlike Java
    ServiceListener l3 = new ServiceListener() {
private int n;
public void serviceChanged(ICUService s) {
    logln("listener 3 report " + n++ + " service changed...");
    if (s.get("en_BOINK") == null) { // don't recurse on ourselves!!!
        logln("registering boink...");
        s.registerInstance("boink", "en_BOINK");
    }
}
    };
    ls.addListener(l3);
    logln("registering boo...");
    ls.registerInstance("Boo", "en_BOO");
#endif

    logln("...done");
}

class TestStringLocaleService : public ICULocaleService {
    public:
    virtual UObject* cloneInstance(UObject* instance) const override {
        return instance ? new UnicodeString(*(UnicodeString*)instance) : NULL;
    }
};

void ICUServiceTest::testLocale() {
    UErrorCode status = U_ZERO_ERROR;
    TestStringLocaleService service;

    UnicodeString* root = new UnicodeString("root");
    UnicodeString* german = new UnicodeString("german");
    UnicodeString* germany = new UnicodeString("german_Germany");
    UnicodeString* japanese = new UnicodeString("japanese");
    UnicodeString* japan = new UnicodeString("japanese_Japan");

    service.registerInstance(root, "", status);
    service.registerInstance(german, "de", status);
    service.registerInstance(germany, Locale::getGermany(), status);
    service.registerInstance(japanese, (UnicodeString)"ja", true, status);
    service.registerInstance(japan, Locale::getJapan(), status);

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("de_US", status);
        confirmEqual("test de_US", german, target);
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("de_US", LocaleKey::KIND_ANY, status);
        confirmEqual("test de_US 2", german, target);
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("de_US", 1234, status);
        confirmEqual("test de_US 3", german, target);
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        Locale actualReturn;
        UnicodeString* target = (UnicodeString*)service.get("de_US", &actualReturn, status);
        confirmEqual("test de_US 5", german, target);
        confirmEqual("test de_US 6", &actualReturn, &Locale::getGerman());
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        Locale actualReturn;
        UnicodeString* target = (UnicodeString*)service.get("de_US", LocaleKey::KIND_ANY, &actualReturn, status);
        confirmEqual("test de_US 7", &actualReturn, &Locale::getGerman());
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        Locale actualReturn;
        UnicodeString* target = (UnicodeString*)service.get("de_US", 1234, &actualReturn, status);
        confirmEqual("test de_US 8", german, target);
        confirmEqual("test de_US 9", &actualReturn, &Locale::getGerman());
        delete target;
    }

    UnicodeString* one = new UnicodeString("one/de_US");
    UnicodeString* two = new UnicodeString("two/de_US");

    service.registerInstance(one, Locale("de_US"), 1, status);
    service.registerInstance(two, Locale("de_US"), 2, status);

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("de_US", 1, status);
        confirmEqual("test de_US kind 1", one, target);
        delete target;
    }
        
    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("de_US", 2, status);
        confirmEqual("test de_US kind 2", two, target);
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("de_US", status);
        confirmEqual("test de_US kind 3", german, target);
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString english = "en";
        Locale localeResult;
        UnicodeString result;
        LocaleKey* lkey = LocaleKey::createWithCanonicalFallback(&english, NULL, 1234, status);
        logln("lkey prefix: " + lkey->prefix(result));
        result.remove();
        logln("lkey descriptor: " + lkey->currentDescriptor(result));
        result.remove();
        logln(UnicodeString("lkey current locale: ") + lkey->currentLocale(localeResult).getName());
        result.remove();

        lkey->fallback();
        logln("lkey descriptor 2: " + lkey->currentDescriptor(result));
        result.remove();

        lkey->fallback();
        logln("lkey descriptor 3: " + lkey->currentDescriptor(result));
        result.remove();
        delete lkey; // tentatively weiv
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("za_PPP", status);
        confirmEqual("test zappp", root, target);
        delete target;
    }

    Locale loc = Locale::getDefault();
    Locale::setDefault(Locale::getJapanese(), status);
    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("za_PPP", status);
        confirmEqual("test with ja locale", japanese, target);
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, 0, status);
        service.getVisibleIDs(ids, status);
        logln("all visible ids:");
        for (int i = 0; i < ids.size(); ++i) {
            const UnicodeString* id = (const UnicodeString*)ids[i];
            logln(*id);
        }
    }

    Locale::setDefault(loc, status);
    {
        UErrorCode status = U_ZERO_ERROR;
        UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, 0, status);
        service.getVisibleIDs(ids, status);
        logln("all visible ids:");
        for (int i = 0; i < ids.size(); ++i) {
            const UnicodeString* id = (const UnicodeString*)ids[i];
            logln(*id);
        }
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("za_PPP", status);
        confirmEqual("test with en locale", root, target);
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        StringEnumeration* locales = service.getAvailableLocales();
        if (locales) {
            confirmIdentical("test available locales", locales->count(status), 6);
            logln("locales: ");
            {
                const char* p;
                while ((p = locales->next(NULL, status))) {
                    logln(p);
                }
            }
            logln(" ");
            delete locales;
        } else {
            errln("could not create available locales");
        }
    }
}

class WrapFactory : public ICUServiceFactory {
    public:
    static const UnicodeString& getGreetingID() {
      if (greetingID == NULL) {
    greetingID = new UnicodeString("greeting");
      }
      return *greetingID;
    }

  static void cleanup() {
    delete greetingID;
    greetingID = NULL;
  }

    UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const override {
        if (U_SUCCESS(status)) {
            UnicodeString temp;
            if (key.currentID(temp).compare(getGreetingID()) == 0) {
                UnicodeString* previous = (UnicodeString*)service->getKey((ICUServiceKey&)key, NULL, this, status);
                if (previous) {
                    previous->insert(0, "A different greeting: \"");
                    previous->append("\"");
                    return previous;
                }
            }
        }
        return NULL;
    }

    void updateVisibleIDs(Hashtable& result, UErrorCode& status) const override {
        if (U_SUCCESS(status)) {
            result.put("greeting", (void*)this, status);
        }
    }

    UnicodeString& getDisplayName(const UnicodeString& id, const Locale& /* locale */, UnicodeString& result) const override {
        result.append("wrap '");
        result.append(id);
        result.append("'");
        return result;
    }

    /**
     * UObject boilerplate.
     */
    static UClassID getStaticClassID() { 
        return (UClassID)&fgClassID;
    }

    virtual UClassID getDynamicClassID() const override {
        return getStaticClassID();
    }

    private:
    static const char fgClassID;
    static UnicodeString* greetingID;
};

UnicodeString* WrapFactory::greetingID = NULL;
const char WrapFactory::fgClassID = '\0';

void 
ICUServiceTest::testWrapFactory() 
{
    UnicodeString* greeting = new UnicodeString("Hello There");
    UnicodeString greetingID = "greeting";
    UErrorCode status = U_ZERO_ERROR;
    TestStringService service;
    service.registerInstance(greeting, greetingID, status);

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* result = (UnicodeString*)service.get(greetingID, status);
        if (result) {
            logln("test one: " + *result);
            delete result;
        }
    }

    service.registerFactory(new WrapFactory(), status);
    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* result = (UnicodeString*)service.get(greetingID, status);
        UnicodeString target = "A different greeting: \"Hello There\"";
        confirmEqual("wrap test: ", result, &target);
        delete result;
    }

    WrapFactory::cleanup();
}

  // misc coverage tests
void ICUServiceTest::testCoverage() 
{
  // ICUServiceKey
  {
    UnicodeString temp;
    ICUServiceKey key("foobar");
    logln("ID: " + key.getID());
    logln("canonicalID: " + key.canonicalID(temp));
    logln("currentID: " + key.currentID(temp.remove()));
    logln("has fallback: " + UnicodeString(key.fallback() ? "true" : "false"));

    if (key.getDynamicClassID() != ICUServiceKey::getStaticClassID()) {
      errln("service key rtt failed.");
    }
  }

  // SimpleFactory
  {
    UErrorCode status = U_ZERO_ERROR;

    UnicodeString* obj = new UnicodeString("An Object");
    SimpleFactory* sf = new SimpleFactory(obj, "object");

    UnicodeString temp;
    logln(sf->getDisplayName("object", Locale::getDefault(), temp));

    if (sf->getDynamicClassID() != SimpleFactory::getStaticClassID()) {
      errln("simple factory rtti failed.");
    }

    // ICUService
        {
                TestStringService service;
                service.registerFactory(sf,     status);

                {
                        UnicodeString* result   = (UnicodeString*)service.get("object", status);
                        if (result) {
                                logln("object is: "     + *result);
                                delete result;
                        }       else {
                                errln("could not get object");
                        }
                }
        }
  }
  
  // ICUServiceKey
  {
      UErrorCode status = U_ZERO_ERROR;
          UnicodeString* howdy = new UnicodeString("Howdy");

          TestStringSimpleKeyService service;
          service.registerInstance(howdy, "Greetings", status);
          {
                  UnicodeString* result = (UnicodeString*)service.get("Greetings",      status);
                  if (result) {
                          logln("object is: "   + *result);
                          delete result;
                  }     else {
                          errln("could not get object");
                  }
          }

      UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, status);
          // yuck, this is awkward to use.  All because we pass null in an overload.
          // TODO: change this.
          UnicodeString str("Greet");
      service.getVisibleIDs(ids, &str, status);
      confirmIdentical("no fallback of greet", ids.size(), 0);
  }

  // ICULocaleService

  // LocaleKey
  {
    UnicodeString primary("en_US");
    UnicodeString fallback("ja_JP");
    UErrorCode status = U_ZERO_ERROR;
    LocaleKey* key = LocaleKey::createWithCanonicalFallback(&primary, &fallback, status);

    if (key->getDynamicClassID() != LocaleKey::getStaticClassID()) {
      errln("localekey rtti error");
    }

    if (!key->isFallbackOf("en_US_FOOBAR")) {
      errln("localekey should be fallback for en_US_FOOBAR");
    }
    if (!key->isFallbackOf("en_US")) {
      errln("localekey should be fallback for en_US");
    }
    if (key->isFallbackOf("en")) {
      errln("localekey should not be fallback for en");
    }

    do {
      Locale loc;
      logln(UnicodeString("current locale: ") + key->currentLocale(loc).getName());
      logln(UnicodeString("canonical locale: ") + key->canonicalLocale(loc).getName());
      logln(UnicodeString("is fallback of en: ") + (key->isFallbackOf("en") ? "true" : " false"));
    } while (key->fallback());
    delete key;

    // LocaleKeyFactory 
    key = LocaleKey::createWithCanonicalFallback(&primary, &fallback, status);

    UnicodeString result;
    LKFSubclass lkf(true); // empty
    Hashtable table;

    UObject *obj = lkf.create(*key, NULL, status);
    logln("obj: " + UnicodeString(obj ? "obj" : "null"));
    logln(lkf.getDisplayName("en_US", Locale::getDefault(), result));
    lkf.updateVisibleIDs(table, status);
    delete obj;
    if (table.count() != 1) {
      errln("visible IDs does not contain en_US");
    }

    LKFSubclass invisibleLKF(false);
    obj = lkf.create(*key, NULL, status);
    logln("obj: " + UnicodeString(obj ? "obj" : "null"));
    logln(invisibleLKF.getDisplayName("en_US", Locale::getDefault(), result.remove()));
    invisibleLKF.updateVisibleIDs(table, status);
    if (table.count() != 0) {
      errln("visible IDs contains en_US");
    }
    delete obj;
    delete key;

        key = LocaleKey::createWithCanonicalFallback(&primary, &fallback, 123, status);
        if (U_SUCCESS(status)) {
                UnicodeString str;
                key->currentDescriptor(str);
                key->parsePrefix(str);
                if (str != "123") {
                        errln("did not get expected prefix");
                }
                delete key;
        }

        // coverage, getSupportedIDs is either overridden or the calling method is
        LKFSubclass0 lkFactory;
        Hashtable table0;
        lkFactory.updateVisibleIDs(table0, status);
        if (table0.count() != 0) {
                errln("LKF returned non-empty hashtable");
        }


        // ResourceBundleFactory
    key = LocaleKey::createWithCanonicalFallback(&primary, &fallback, status);
        ICUResourceBundleFactory rbf;
        UObject* icurb = rbf.create(*key, NULL, status);
        if (icurb != NULL) {
                logln("got resource bundle for key");
                delete icurb;
        }
        delete key;
  }

 #if 0
 // ICUNotifier
  ICUNotifier nf = new ICUNSubclass();
  try {
    nf.addListener(null);
    errln("added null listener");
  }
  catch (NullPointerException e) {
    logln(e.getMessage());
  }
  catch (Exception e) {
    errln("got wrong exception");
  }

  try {
    nf.addListener(new WrongListener());
    errln("added wrong listener");
  }
  catch (InternalError e) {
    logln(e.getMessage());
  }
  catch (Exception e) {
    errln("got wrong exception");
  }

  try {
    nf.removeListener(null);
    errln("removed null listener");
  }
  catch (NullPointerException e) {
    logln(e.getMessage());
  }
  catch (Exception e) {
    errln("got wrong exception");
  }

  nf.removeListener(new MyListener());
  nf.notifyChanged();
  nf.addListener(new MyListener());
  nf.removeListener(new MyListener());
#endif
}


/* !UCONFIG_NO_SERVICE */
#endif


