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

package com.ibm.icu.dev.test.collator;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;

import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.text.Collator;
import com.ibm.icu.text.Collator.CollatorFactory;
import com.ibm.icu.util.ULocale;

public class CollationServiceTest extends TestFmwk {
    public static void main(String[] args) {
        new CollationServiceTest().run(args);
    }

    public void TestRegister() {
        // register a singleton
        Collator frcol = Collator.getInstance(ULocale.FRANCE);
        Collator uscol = Collator.getInstance(ULocale.US);
            
        { // try override en_US collator
            Object key = Collator.registerInstance(frcol, ULocale.US);
            Collator ncol = Collator.getInstance(ULocale.US);
            if (!frcol.equals(ncol)) {
                errln("register of french collator for en_US failed");
            }

            // coverage
            Collator test = Collator.getInstance(ULocale.GERMANY); // CollatorFactory.handleCreate
            if (!test.getLocale(ULocale.VALID_LOCALE).equals(ULocale.GERMAN)) {
                errln("Collation from Germany is really " + test.getLocale(ULocale.VALID_LOCALE));
            }

            if (!Collator.unregister(key)) {
                errln("failed to unregister french collator");
            }
            ncol = Collator.getInstance(ULocale.US);
            if (!uscol.equals(ncol)) {
                errln("collator after unregister does not match original");
            }
        }

        ULocale fu_FU = new ULocale("fu_FU_FOO");

        { // try create collator for new locale
            Collator fucol = Collator.getInstance(fu_FU);
            Object key = Collator.registerInstance(frcol, fu_FU);
            Collator ncol = Collator.getInstance(fu_FU);
            if (!frcol.equals(ncol)) {
                errln("register of fr collator for fu_FU failed");
            }
            
            ULocale[] locales = Collator.getAvailableULocales();
            boolean found = false;
            for (int i = 0; i < locales.length; ++i) {
                if (locales[i].equals(fu_FU)) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                errln("new locale fu_FU not reported as supported locale");
            }
            try{
                String name = Collator.getDisplayName(fu_FU);
                if (!"fu (FU, FOO)".equals(name)
                        && !"fu_FU_FOO".equals(name) /* no LocaleDisplayNamesImpl */) {
                    errln("found " + name + " for fu_FU");
                }
            }catch(MissingResourceException ex){
                warnln("Could not load locale data."); 
            }
            try{
                String name = Collator.getDisplayName(fu_FU, fu_FU);
                if (!"fu (FU, FOO)".equals(name)
                        && !"fu_FU_FOO".equals(name) /* no LocaleDisplayNamesImpl */) {
                    errln("found " + name + " for fu_FU");
                }
            }catch(MissingResourceException ex){
                warnln("Could not load locale data."); 
            }

            if (!Collator.unregister(key)) {
                errln("failed to unregister french collator");
            }
            ncol = Collator.getInstance(fu_FU);
            if (!fucol.equals(ncol)) {
                errln("collator after unregister does not match original fu_FU");
            }
        }

        {
            // coverage after return to default 
            ULocale[] locales = Collator.getAvailableULocales();
    
            for (int i = 0; i < locales.length; ++i) {
                if (locales[i].equals(fu_FU)) {
                    errln("new locale fu_FU not reported as supported locale");
                    break;
                }
            }

            Collator ncol = Collator.getInstance(ULocale.US);
            if (!ncol.getLocale(ULocale.VALID_LOCALE).equals(ULocale.US)) {
                errln("Collation from US is really " + ncol.getLocale(ULocale.VALID_LOCALE));
            }
        }
    }

    public void TestRegisterFactory() {

        class CollatorInfo {
            ULocale locale;
            Collator collator;
            Map displayNames; // locale -> string

            CollatorInfo(ULocale locale, Collator collator, Map displayNames) {
                this.locale = locale;
                this.collator = collator;
                this.displayNames = displayNames;
            }

            String getDisplayName(ULocale displayLocale) {
                String name = null;
                if (displayNames != null) {
                    name = (String)displayNames.get(displayLocale);
                }
                if (name == null) {
                    name = locale.getDisplayName(displayLocale);
                }
                return name;
            }
        }

        class TestFactory extends CollatorFactory {
            private Map map;
            private Set ids;
            
            TestFactory(CollatorInfo[] info) {
                map = new HashMap();
                for (int i = 0; i < info.length; ++i) {
                    CollatorInfo ci = info[i];
                    map.put(ci.locale, ci);
                }
            }

            public Collator createCollator(ULocale loc) {
                CollatorInfo ci = (CollatorInfo)map.get(loc);
                if (ci != null) {
                    return ci.collator;
                }
                return null;
            }

            public String getDisplayName(ULocale objectLocale, ULocale displayLocale) {
                CollatorInfo ci = (CollatorInfo)map.get(objectLocale);
                if (ci != null) {
                    return ci.getDisplayName(displayLocale);
                }
                return null;
            }

            public Set getSupportedLocaleIDs() {
                if (ids == null) {
                    HashSet set = new HashSet();
                    Iterator iter = map.keySet().iterator();
                    while (iter.hasNext()) {
                        ULocale locale = (ULocale)iter.next();
                        String id = locale.toString();
                        set.add(id);
                    }
                    ids = Collections.unmodifiableSet(set);
                }
                return ids;
            }
        }
    
        class TestFactoryWrapper extends CollatorFactory {
            CollatorFactory delegate;
    
            TestFactoryWrapper(CollatorFactory delegate) {
                this.delegate = delegate;
            }
    
            public Collator createCollator(ULocale loc) {
                return delegate.createCollator(loc);
            }
    
            // use CollatorFactory getDisplayName(ULocale, ULocale) for coverage
    
            public Set getSupportedLocaleIDs() {
                return delegate.getSupportedLocaleIDs();
            }
        }

        ULocale fu_FU = new ULocale("fu_FU");
        ULocale fu_FU_FOO = new ULocale("fu_FU_FOO");

        Map fuFUNames = new HashMap();
        fuFUNames.put(fu_FU, "ze leetle bunny Fu-Fu");
        fuFUNames.put(fu_FU_FOO, "zee leetel bunny Foo-Foo");
        fuFUNames.put(ULocale.US, "little bunny Foo Foo");

        Collator frcol = Collator.getInstance(ULocale.FRANCE);
       /* Collator uscol = */Collator.getInstance(ULocale.US);
        Collator gecol = Collator.getInstance(ULocale.GERMANY);
        Collator jpcol = Collator.getInstance(ULocale.JAPAN);
        Collator fucol = Collator.getInstance(fu_FU);
        
        CollatorInfo[] info = {
            new CollatorInfo(ULocale.US, frcol, null),
            new CollatorInfo(ULocale.FRANCE, gecol, null),
            new CollatorInfo(fu_FU, jpcol, fuFUNames),
        };
        TestFactory factory = null;
        try{
            factory = new TestFactory(info);
        }catch(MissingResourceException ex){
            warnln("Could not load locale data."); 
        }
        // coverage
        {
            TestFactoryWrapper wrapper = new TestFactoryWrapper(factory); // in java, gc lets us easily multiply reference!
            Object key = Collator.registerFactory(wrapper);
            String name = null;
            try{
                name = Collator.getDisplayName(fu_FU, fu_FU_FOO);
            }catch(MissingResourceException ex){
                warnln("Could not load locale data."); 
            }
            logln("*** default name: " + name);
            Collator.unregister(key);
    
            ULocale bar_BAR = new ULocale("bar_BAR");
            Collator col = Collator.getInstance(bar_BAR);
            if (!col.getLocale(ULocale.VALID_LOCALE).equals(ULocale.getDefault())) {
                errln("Collation from bar_BAR is really " + col.getLocale(ULocale.VALID_LOCALE));
            }
        }

        int n1 = checkAvailable("before registerFactory");
        
        {
            Object key = Collator.registerFactory(factory);
            
            int n2 = checkAvailable("after registerFactory");
            
            Collator ncol = Collator.getInstance(ULocale.US);
            if (!frcol.equals(ncol)) {
                errln("frcoll for en_US failed");
            }

            ncol = Collator.getInstance(fu_FU_FOO);
            if (!jpcol.equals(ncol)) {
                errln("jpcol for fu_FU_FOO failed, got: " + ncol);
            }
            
            ULocale[] locales = Collator.getAvailableULocales();
            boolean found = false;
            for (int i = 0; i < locales.length; ++i) {
                if (locales[i].equals(fu_FU)) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                errln("new locale fu_FU not reported as supported locale");
            }
            
            String name = Collator.getDisplayName(fu_FU);
            if (!"little bunny Foo Foo".equals(name)) {
                errln("found " + name + " for fu_FU");
            }

            name = Collator.getDisplayName(fu_FU, fu_FU_FOO);
            if (!"zee leetel bunny Foo-Foo".equals(name)) {
                errln("found " + name + " for fu_FU in fu_FU_FOO");
            }

            if (!Collator.unregister(key)) {
                errln("failed to unregister factory");
            }

            int n3 = checkAvailable("after unregister");
            assertTrue("register increases count", n2>n1);
            assertTrue("unregister restores count", n3==n1);
            
            ncol = Collator.getInstance(fu_FU);
            if (!fucol.equals(ncol)) {
                errln("collator after unregister does not match original fu_FU");
            }
        }
    }

    /**
     * Check the integrity of the results of Collator.getAvailableULocales().
     * Return the number of items returned.
     */
    int checkAvailable(String msg) {
        Locale locs[] = Collator.getAvailableLocales();
        if (!assertTrue("getAvailableLocales != null", locs!=null)) return -1;
        checkArray(msg, locs, null);
        ULocale ulocs[] = Collator.getAvailableULocales();
        if (!assertTrue("getAvailableULocales != null", ulocs!=null)) return -1;
        checkArray(msg, ulocs, null);
        // This is not true because since ULocale objects with script code cannot be 
        // converted to Locale objects
        //assertTrue("getAvailableLocales().length == getAvailableULocales().length", locs.length == ulocs.length);
        return locs.length;
    }
    
    private static final String KW[] = {
        "collation"
    };

    private static final String KWVAL[] = {
        "phonebook",
        "stroke"
    };

    public void TestSeparateTrees() {
        String kw[] = Collator.getKeywords();
        if (!assertTrue("getKeywords != null", kw!=null)) return;
        checkArray("getKeywords", kw, KW);
        
        String kwval[] = Collator.getKeywordValues(KW[0]);
        if (!assertTrue("getKeywordValues != null", kwval!=null)) return;
        checkArray("getKeywordValues", kwval, KWVAL);

        boolean isAvailable[] = new boolean[1];
        ULocale equiv = Collator.getFunctionalEquivalent(KW[0],
                                                         new ULocale("de"),
                                                         isAvailable);
        if (assertTrue("getFunctionalEquivalent(de)!=null", equiv!=null)) {
            assertEquals("getFunctionalEquivalent(de)", "root", equiv.toString());
        }
        assertTrue("getFunctionalEquivalent(de).isAvailable==true",
                   isAvailable[0] == true);
        
        equiv = Collator.getFunctionalEquivalent(KW[0],
                                                 new ULocale("de_DE"),
                                                 isAvailable);
        if (assertTrue("getFunctionalEquivalent(de_DE)!=null", equiv!=null)) {
            assertEquals("getFunctionalEquivalent(de_DE)", "root", equiv.toString());
        }
        assertTrue("getFunctionalEquivalent(de_DE).isAvailable==false",
                   isAvailable[0] == false);

        equiv = Collator.getFunctionalEquivalent(KW[0], new ULocale("zh_Hans"));
        if (assertTrue("getFunctionalEquivalent(zh_Hans)!=null", equiv!=null)) {
            assertEquals("getFunctionalEquivalent(zh_Hans)", "zh", equiv.toString());
        }
    }
    
    public void TestGetFunctionalEquivalent() {
        String kw[] = Collator.getKeywords();
        final String DATA[] = { 
                          "sv", "sv", "t",
                          "sv@collation=direct", "sv", "t",
                          "sv@collation=traditional", "sv", "t",
                          "sv@collation=gb2312han", "sv", "t",
                          "sv@collation=stroke", "sv", "t",
                          "sv@collation=pinyin", "sv", "t",
                          "sv@collation=standard", "sv@collation=standard", "t",
                          "sv@collation=reformed", "sv", "t",
                          "sv@collation=big5han", "sv", "t",
                          "sv_FI", "sv", "f",
                          "sv_FI@collation=direct", "sv", "f",
                          "sv_FI@collation=traditional", "sv", "f",
                          "sv_FI@collation=gb2312han", "sv", "f",
                          "sv_FI@collation=stroke", "sv", "f",
                          "sv_FI@collation=pinyin", "sv", "f",
                          "sv_FI@collation=standard", "sv@collation=standard", "f",
                          "sv_FI@collation=reformed", "sv", "f",
                          "sv_FI@collation=big5han", "sv", "f",
                          "nl", "root", "t",
                          "nl@collation=direct", "root", "t",
                          "nl_BE", "root", "f",
                          "nl_BE@collation=direct", "root", "f",
                          "nl_BE@collation=traditional", "root", "f",
                          "nl_BE@collation=gb2312han", "root", "f",
                          "nl_BE@collation=stroke", "root", "f",
                          "nl_BE@collation=pinyin", "root", "f",
                          "nl_BE@collation=big5han", "root", "f",
                          "nl_BE@collation=phonebook", "root", "f",
                          "en_US_VALLEYGIRL","root","f"
                        };
        final int DATA_COUNT=(DATA.length/3);
        
        for(int i=0;i<DATA_COUNT;i++) {
            boolean isAvailable[] = new boolean[1];
            ULocale input = new ULocale(DATA[(i*3)+0]);
            ULocale expect = new ULocale(DATA[(i*3)+1]);
            boolean expectAvailable = DATA[(i*3)+2].equals("t");
            ULocale actual = Collator.getFunctionalEquivalent(kw[0],input,isAvailable);
            if(!actual.equals(expect) || (expectAvailable!=isAvailable[0])) {
                errln("#" + i + ": Collator.getFunctionalEquivalent(" + input + ")=" + actual + ", avail " + new Boolean(isAvailable[0]) + ", " +
                        "expected " + expect + " avail " + new Boolean(expectAvailable));
            } else {
                logln("#" + i + ": Collator.getFunctionalEquivalent(" + input + ")=" + actual + ", avail " + new Boolean(isAvailable[0]));
            }
        }
    }

//    public void PrintFunctionalEquivalentList() {
//        ULocale[] locales = Collator.getAvailableULocales();
//        String[] keywords = Collator.getKeywords();
//        logln("Collation");
//        logln("Possible keyword=values pairs:");
//        for (int i = 0; i < Collator.getKeywords().length; ++i) {
//                String[] values = Collator.getKeywordValues(keywords[i]);
//                for (int j = 0; j < values.length; ++j) {
//                        System.out.println(keywords[i] + "=" + values[j]);
//                }
//        }
//        logln("Differing Collators:");
//        boolean[] isAvailable = {true};
//        for (int k = 0; k < locales.length; ++k) {
//                logln(locales[k].getDisplayName(ULocale.ENGLISH) + " [" +locales[k] + "]");
//                for (int i = 0; i < Collator.getKeywords().length; ++i) {
//                        ULocale base = Collator.getFunctionalEquivalent(keywords[i],locales[k]);
//                        String[] values = Collator.getKeywordValues(keywords[i]);
//                        for (int j = 0; j < Collator.getKeywordValues(keywords[i]).length;++j) {                          
//                                ULocale other = Collator.getFunctionalEquivalent(keywords[i], 
//                                        new ULocale(locales[k] + "@" + keywords[i] + "=" + values[j]),
//                                        isAvailable);
//                                if (isAvailable[0] && !other.equals(base)) {
//                                        logln("\t" + keywords[i] + "=" + values[j] + ";\t" + base + ";\t" + other);
//                                }
//                        }
//                }
//        }
//    }
    
    public void TestGetKeywordValues(){
        final String[][] PREFERRED = {
            {"und",             "standard", "eor", "search"},
            {"en_US",           "standard", "eor", "search"},
            {"en_029",          "standard", "eor", "search"},
            {"de_DE",           "standard", "phonebook", "search", "eor"},
            {"de_Latn_DE",      "standard", "phonebook", "search", "eor"},
            {"zh",              "pinyin", "big5han", "gb2312han", "stroke", "zhuyin", "eor", "search", "standard"},
            {"zh_Hans",         "pinyin", "big5han", "gb2312han", "stroke", "zhuyin", "eor", "search", "standard"},
            {"zh_CN",           "pinyin", "big5han", "gb2312han", "stroke", "zhuyin", "eor", "search", "standard"},
            {"zh_Hant",         "stroke", "big5han", "gb2312han", "pinyin", "zhuyin", "eor", "search", "standard"},
            {"zh_TW",           "stroke", "big5han", "gb2312han", "pinyin", "zhuyin", "eor", "search", "standard"},
            {"zh__PINYIN",      "pinyin", "big5han", "gb2312han", "stroke", "zhuyin", "eor", "search", "standard"},
            {"es_ES",           "standard", "search", "traditional", "eor"},
            {"es__TRADITIONAL", "traditional", "search", "standard", "eor"},
            {"und@collation=phonebook",     "standard", "eor", "search"},
            {"de_DE@collation=big5han",     "standard", "phonebook", "search", "eor"},
            {"zzz@collation=xxx",           "standard", "eor", "search"},
        };

        for (int i = 0; i < PREFERRED.length; i++) {
            ULocale loc = new ULocale(PREFERRED[i][0]);
            String[] expected = new String[PREFERRED[i].length - 1];
            System.arraycopy(PREFERRED[i], 1, expected, 0, expected.length);

            String[] pref = Collator.getKeywordValuesForLocale("collation", loc, true);
            boolean matchPref = false;
            if (pref.length == expected.length) {
                matchPref = true;
                for (int j = 0; j < pref.length; j++) {
                    if (!pref[j].equals(expected[j])) {
                        matchPref = false;
                    }
                }
            }
            if (!matchPref) {
                errln("FAIL: Preferred values for locale " + loc 
                        + " got:" + Arrays.toString(pref) + " expected:" + Arrays.toString(expected));
            }
 
            String[] all = Collator.getKeywordValuesForLocale("collation", loc, true);

            // Collator.getKeywordValues return the same contents for both commonlyUsed
            // true and false.
            boolean matchAll = false;
            if (pref.length == all.length) {
                matchAll = true;
                for (int j = 0; j < pref.length; j++) {
                    boolean foundMatch = false;
                    for (int k = 0; k < all.length; k++) {
                        if (pref[j].equals(all[k])) {
                            foundMatch = true;
                            break;
                        }
                    }
                    if (!foundMatch) {
                        matchAll = false;
                        break;
                    }
                }
            }
            if (!matchAll) {
                errln("FAIL: All values for locale " + loc
                        + " got:" + Arrays.toString(all) + " expected:" + Arrays.toString(pref));
            }
        }
    }
}
