/*
 *******************************************************************************
 * Copyright (C) 2008-2012, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.dev.test.localespi;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.util.ULocale;

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

    private static final Method GETDISPLAYSCRIPT_METHOD;

    static {
        Method mGetDisplayScript = null;
        try {
            mGetDisplayScript = Locale.class.getMethod("getDisplayScript", new Class[] {Locale.class});
        } catch (Exception e) {
            // fall through
        }
        GETDISPLAYSCRIPT_METHOD = mGetDisplayScript;
    }

    public void TestLanguageNames() {
        Locale[] locales = Locale.getAvailableLocales();
        StringBuffer icuid = new StringBuffer();
        for (Locale inLocale : locales) {
            if (TestUtil.isProblematicIBMLocale(inLocale)) {
                logln("Skipped " + inLocale);
                continue;
            }

            ULocale inULocale = ULocale.forLocale(inLocale);
            Locale inLocaleICU = TestUtil.toICUExtendedLocale(inLocale);
            for (Locale forLocale : locales) {
                if (forLocale.getLanguage().length() == 0) {
                    continue;
                }
                icuid.setLength(0);
                icuid.append(forLocale.getLanguage());
                String country = forLocale.getCountry();
                String variant = forLocale.getVariant();
                if (country.length() != 0) {
                    icuid.append("_");
                    icuid.append(country);
                }
                if (variant.length() != 0) {
                    if (country.length() == 0) {
                        icuid.append("_");
                    }
                    icuid.append("_");
                    icuid.append(variant);
                }
                ULocale forULocale = new ULocale(icuid.toString());
                String icuname = ULocale.getDisplayLanguage(forULocale.getLanguage(), inULocale);
                if (icuname.equals(forULocale.getLanguage()) || icuname.length() == 0) {
                    continue;
                }

                String name = forLocale.getDisplayLanguage(inLocale);

                if (TestUtil.isICUExtendedLocale(inLocale)) {
                    // The name should be taken from ICU
                    if (!name.equals(icuname)) {
                        errln("FAIL: Language name by ICU is " + icuname + ", but got " + name
                                + " for locale " + forLocale + " in locale " + inLocale);
                    }
                } else {
                    if (!name.equals(icuname)) {
                        logln("INFO: Language name by JDK is " + name + ", but " + icuname + 
                              " by ICU, for locale " + forLocale + " in locale " + inLocale);
                    }
                    // Try explicit ICU locale (xx_yy_ICU)
                    name = forLocale.getDisplayLanguage(inLocaleICU);
                    if (!name.equals(icuname)) {
                        errln("FAIL: Language name by ICU is " + icuname + ", but got " + name
                              + " for locale " + forLocale + " in locale " + inLocaleICU);
                    }
                }
            }
        }
    }

    public void TestScriptNames() {
        if (GETDISPLAYSCRIPT_METHOD == null) {
            logln("INFO: Locale#getDisplayScript(Locale) is not available.");
            return;
        }

        Locale[] locales = Locale.getAvailableLocales();
        for (Locale inLocale : locales) {
            if (TestUtil.isProblematicIBMLocale(inLocale)) {
                logln("Skipped " + inLocale);
                continue;
            }

            ULocale inULocale = ULocale.forLocale(inLocale);
            Locale inLocaleICU = TestUtil.toICUExtendedLocale(inLocale);
            for (ULocale forULocale : ULocale.getAvailableLocales()) {
                if (forULocale.getScript().length() == 0) {
                    continue;
                }
                Locale forLocale = forULocale.toLocale();
                String icuname = forULocale.getDisplayScript(inULocale);
                if (icuname.equals(forULocale.getScript()) || icuname.length() == 0) {
                    continue;
                }

                String name = null;
                try {
                    name = (String)GETDISPLAYSCRIPT_METHOD.invoke(forLocale, new Object[] {inLocale});
                } catch (Exception e) {
                    errln("FAIL: JDK Locale#getDisplayScript(\"" + inLocale + "\") throws exception: " + e.getMessage());
                    continue;
                }

                if (TestUtil.isICUExtendedLocale(inLocale)) {
                    // The name should be taken from ICU
                    if (!name.equals(icuname)) {
                        errln("FAIL: Script name by ICU is " + icuname + ", but got " + name
                                + " for locale " + forLocale + " in locale " + inLocale);
                    }
                } else {
                    // The name might be taken from JDK
                    if (!name.equals(icuname)) {
                        logln("INFO: Script name by JDK is " + name + ", but " + icuname + 
                                " in ICU, for locale " + forLocale + " in locale " + inLocale);
                    }
                    // Try explicit ICU locale (xx_yy_ICU)
                    try {
                        name = (String)GETDISPLAYSCRIPT_METHOD.invoke(forLocale, new Object[] {inLocaleICU});
                    } catch (Exception e) {
                        errln("FAIL: JDK Locale#getDisplayScript(\"" + inLocaleICU + "\") throws exception: " + e.getMessage());
                        continue;
                    }
                    if (!name.equals(icuname)) {
                        errln("FAIL: Script name by ICU is " + icuname + ", but got " + name
                                + " for locale " + forLocale + " in locale " + inLocaleICU);
                    }
                }
            }
        }
    }

    public void TestCountryNames() {
        Locale[] locales = Locale.getAvailableLocales();
        for (Locale inLocale : locales) {
            if (TestUtil.isProblematicIBMLocale(inLocale)) {
                logln("Skipped " + inLocale);
                continue;
            }

            ULocale inULocale = ULocale.forLocale(inLocale);
            Locale inLocaleICU = TestUtil.toICUExtendedLocale(inLocale);
            for (Locale forLocale : locales) {
                if (forLocale.getCountry().length() == 0) {
                    continue;
                }
                // ULocale#forLocale preserves country always
                ULocale forULocale = ULocale.forLocale(forLocale);
                String icuname = forULocale.getDisplayCountry(inULocale);
                if (icuname.equals(forULocale.getCountry()) || icuname.length() == 0) {
                    continue;
                }

                String name = forLocale.getDisplayCountry(inLocale);
                if (TestUtil.isICUExtendedLocale(inLocale)) {
                    // The name should be taken from ICU
                    if (!name.equals(icuname)) {
                        errln("FAIL: Country name by ICU is " + icuname + ", but got " + name
                                + " for locale " + forLocale + " in locale " + inLocale);
                    }
                } else {
                    // The name might be taken from JDK
                    if (!name.equals(icuname)) {
                        logln("INFO: Country name by JDK is " + name + ", but " + icuname + 
                              " in ICU, for locale " + forLocale + " in locale " + inLocale);
                    }
                    // Try explicit ICU locale (xx_yy_ICU)
                    name = forLocale.getDisplayCountry(inLocaleICU);
                    if (!name.equals(icuname)) {
                        errln("FAIL: Country name by ICU is " + icuname + ", but got " + name
                              + " for locale " + forLocale + " in locale " + inLocaleICU);
                    }
                }
            }
        }
    }

    public void TestVariantNames() {
        Set<Locale> locales = new HashSet<Locale>();
        for (Locale l : Locale.getAvailableLocales()) {
            locales.add(l);
        }
        // Add some locales with variant
        final Locale[] additionalLocales = {
            new Locale("fr", "FR", "1694acad"),
            new Locale("de", "DE", "1901"),
            new Locale("en", "US", "boont"),
            new Locale("el", "GR", "monoton"),
        };
        for (Locale l : additionalLocales) {
            locales.add(l);
        }

        for (Locale inLocale : locales) {
            if (TestUtil.isProblematicIBMLocale(inLocale)) {
                logln("Skipped " + inLocale);
                continue;
            }

            ULocale inULocale = ULocale.forLocale(inLocale);
            Locale inLocaleICU = TestUtil.toICUExtendedLocale(inLocale);
            for (Locale forLocale : locales) {
                String locVar = forLocale.getVariant();
                if (locVar.length() == 0) {
                    continue;
                }
                // Note: JDK resolves a display name for each variant subtag
                String[] locVarSubtags = locVar.split("_");

                for (String locSingleVar : locVarSubtags) {
                    if (locSingleVar.equals(TestUtil.ICU_VARIANT)
                            || locSingleVar.equals("Cyrl") || locSingleVar.equals("Latn")) { // IBM Java 6 has locales with 'variant' Cryl/Latn
                        continue;
                    }
                    Locale forLocaleSingleVar = new Locale(forLocale.getLanguage(), forLocale.getCountry(), locSingleVar);
                    ULocale forULocaleSingleVar = new ULocale("und_ZZ_" + locSingleVar);
                    String icuname = forULocaleSingleVar.getDisplayVariant(inULocale);
                    if (icuname.equals(locSingleVar) || icuname.length() == 0) {
                        continue;
                    }

                    String name = forLocaleSingleVar.getDisplayVariant(inLocale);
                    if (name.equalsIgnoreCase(locSingleVar)) {
                        // ICU does not have any localized display name.
                        // Note: ICU turns variant to upper case string, while Java does not.
                        continue;
                    }
                    if (TestUtil.isICUExtendedLocale(inLocale)) {
                        // The name should be taken from ICU
                        if (!name.equals(icuname)) {
                            errln("FAIL: Variant name by ICU is " + icuname + ", but got " + name
                                    + " for locale " + forLocaleSingleVar + " in locale " + inLocale);
                        }
                    } else {
                        if (!name.equals(icuname)) {
                            logln("INFO: Variant name by JDK is " + name + ", but " + icuname + 
                                  " in ICU, for locale " + forLocaleSingleVar + " in locale " + inLocale);
                        }
                        // Try explicit ICU locale (xx_yy_ICU)
                        name = forLocaleSingleVar.getDisplayVariant(inLocaleICU);
                        if (!name.equals(icuname)) {
                            errln("FAIL: Variant name by ICU is " + icuname + ", but got " + name
                                  + " for locale " + forLocaleSingleVar + " in locale " + inLocaleICU);
                        }
                    }
                }
            }
        }
    }
}
