/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.providers.contacts;

import android.provider.ContactsContract.FullNameStyle;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

@SmallTest
public class ContactLocaleUtilsTest extends AndroidTestCase {
    private static final String TAG = "ContactLocaleUtilsTest";

    private static final String PHONE_NUMBER_1 = "+1 (650) 555-1212";
    private static final String PHONE_NUMBER_2 = "650-555-1212";
    private static final String LATIN_NAME = "John Smith";
    private static final String LATIN_NAME_2 = "John Paul Jones";
    private static final String KANJI_NAME = "\u65e5";
    private static final String ARABIC_NAME = "\u0646\u0648\u0631"; /* Noor */
    private static final String CHINESE_NAME = "\u675C\u9D51";
    private static final String SERBIAN_NAME = "\u0408\u0435\u043B\u0435\u043D\u0430";
    private static final String UKRAINIAN_NAME = "\u0407";
    private static final String UKRAINIAN_NAME_2 = "\u0490";
    private static final String CHINESE_LATIN_MIX_NAME_1 = "D\u675C\u9D51";
    private static final String CHINESE_LATIN_MIX_NAME_2 = "MARY \u675C\u9D51";
    private static final String[] CHINESE_NAME_KEY = {"\u9D51", "\u675C\u9D51", "JUAN", "DUJUAN",
            "J", "DJ"};
    private static final String[] CHINESE_LATIN_MIX_NAME_1_KEY = {"\u9D51", "\u675C\u9D51",
        "D \u675C\u9D51", "JUAN", "DUJUAN", "J", "DJ", "D DUJUAN", "DDJ"};
    private static final String[] CHINESE_LATIN_MIX_NAME_2_KEY = {"\u9D51", "\u675C\u9D51",
        "MARY \u675C\u9D51", "JUAN", "DUJUAN", "MARY DUJUAN", "J", "DJ", "MDJ"};
    private static final String[] LATIN_NAME_KEY = {"John Smith", "Smith", "JS", "S"};
    private static final String[] LATIN_NAME_KEY_2 = {
        "John Paul Jones", "Paul Jones", "Jones", "JPJ", "PJ", "J"};
    private static final String[] LABELS_EN_US = {
        "\u2026", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
        "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
        "#", ""};
    private static final String[] LABELS_JA_JP = {
        "", "\u3042", "\u304B", "\u3055", "\u305F", "\u306A", "\u306F",
        "\u307E", "\u3084", "\u3089", "\u308F", "\u4ED6",
        "", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
        "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
        "#", ""};
    private static final String[] LABELS_ZH_TW = {
        "", "1\u5283", "2\u5283", "3\u5283", "4\u5283", "5\u5283", "6\u5283",
        "7\u5283", "8\u5283", "9\u5283", "10\u5283", "11\u5283", "12\u5283",
        "13\u5283", "14\u5283", "15\u5283", "16\u5283", "17\u5283", "18\u5283",
        "19\u5283", "20\u5283", "21\u5283", "22\u5283", "23\u5283", "24\u5283",
        "25\u5283", "26\u5283", "27\u5283", "28\u5283", "29\u5283", "30\u5283",
        "31\u5283", "32\u5283", "33\u5283",
        "35\u5283", "36\u5283", "39\u5283", "48\u5283",
        "", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
        "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
        "#", ""};
    private static final String[] LABELS_KO = {
        "", "\u3131", "\u3134", "\u3137", "\u3139", "\u3141", "\u3142",
        "\u3145", "\u3147", "\u3148", "\u314A", "\u314B", "\u314C", "\u314D",
        "\u314E",
        "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
        "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
        "#", ""};
    private static final String[] LABELS_AR = {
        "\u2026", "\u0627", "\u0628", "\u062a", "\u062b", "\u062c", "\u062d",
        "\u062e", "\u062f", "\u0630", "\u0631", "\u0632", "\u0633", "\u0634",
        "\u0635", "\u0636", "\u0637", "\u0638", "\u0639", "\u063a", "\u0641",
        "\u0642", "\u0643", "\u0644", "\u0645", "\u0646", "\u0647", "\u0648",
        "\u064a",
        "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
        "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
        "#", ""};

    private static final String JAPANESE_MISC = "\u4ed6";

    private static final Locale LOCALE_ARABIC = new Locale("ar");
    private static final Locale LOCALE_SERBIAN = new Locale("sr");
    private static final Locale LOCALE_UKRAINIAN = new Locale("uk");
    private boolean hasSimplifiedChineseCollator;
    private boolean hasTraditionalChineseCollator;
    private boolean hasJapaneseCollator;
    private boolean hasKoreanCollator;
    private boolean hasArabicCollator;
    private boolean hasGermanCollator;
    private boolean hasSerbianCollator;
    private boolean hasUkrainianCollator;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        final Locale locale[] = Collator.getAvailableLocales();
        for (int i = 0; i < locale.length; i++) {
            if (LocaleSet.isLocaleSimplifiedChinese(locale[i])) {
                hasSimplifiedChineseCollator = true;
            } else if (LocaleSet.isLocaleTraditionalChinese(locale[i])) {
                hasTraditionalChineseCollator = true;
            } else if (locale[i].equals(Locale.JAPAN)) {
                hasJapaneseCollator = true;
            } else if (locale[i].equals(Locale.KOREA)) {
                hasKoreanCollator = true;
            } else if (locale[i].equals(LOCALE_ARABIC)) {
                hasArabicCollator = true;
            } else if (locale[i].equals(Locale.GERMANY)) {
                hasGermanCollator = true;
            } else if (locale[i].equals(LOCALE_SERBIAN)) {
                hasSerbianCollator = true;
            } else if (locale[i].equals(LOCALE_UKRAINIAN)) {
                hasUkrainianCollator = true;
            }
        }
    }

    private String getLabel(String name) {
        ContactLocaleUtils utils = ContactLocaleUtils.getInstance();
        int bucketIndex = utils.getBucketIndex(name);
        return utils.getBucketLabel(bucketIndex);
    }

    private Iterator<String> getNameLookupKeys(String name, int nameStyle) {
        ContactLocaleUtils utils = ContactLocaleUtils.getInstance();
        return utils.getNameLookupKeys(name, nameStyle);
    }

    private ArrayList<String> getLabels() {
        ContactLocaleUtils utils = ContactLocaleUtils.getInstance();
        return utils.getLabels();
    }

    public void testEnglishContactLocaleUtils() throws Exception {
        ContactLocaleUtils.setLocale(Locale.ENGLISH);
        assertEquals("#", getLabel(PHONE_NUMBER_1));
        assertEquals("#", getLabel(PHONE_NUMBER_2));
        assertEquals("J", getLabel(LATIN_NAME));
        assertEquals("\u2026", getLabel(CHINESE_NAME));
        assertEquals("D", getLabel(CHINESE_LATIN_MIX_NAME_1));
        assertEquals("B", getLabel("Bob Smith"));

        if (hasArabicCollator) {
            assertEquals("\u0646", getLabel(ARABIC_NAME));
        }
        if (hasSerbianCollator) {
            assertEquals("\u0408", getLabel(SERBIAN_NAME));
        }
        if (hasUkrainianCollator) {
            // Updated in CLDR 27/ICU 55:
            // http://cldr.unicode.org/index/downloads/cldr-27#TOC-Changes-to-Collation
            assertEquals("\u0406", getLabel(UKRAINIAN_NAME));
        }

        assertNull(getNameLookupKeys(LATIN_NAME, FullNameStyle.UNDEFINED));
        verifyLabels(getLabels(), LABELS_EN_US);
    }

    public void testJapaneseContactLocaleUtils() throws Exception {
        if (!hasJapaneseCollator) {
            Log.w(TAG, "Japanese collator not found; skipping test");
            return;
        }

        ContactLocaleUtils.setLocale(Locale.JAPAN);
        assertEquals("#", getLabel(PHONE_NUMBER_1));
        assertEquals("#", getLabel(PHONE_NUMBER_2));
        assertEquals(JAPANESE_MISC, getLabel(KANJI_NAME));
        assertEquals("J", getLabel(LATIN_NAME));
        assertEquals(JAPANESE_MISC, getLabel(CHINESE_NAME));
        assertEquals("D", getLabel(CHINESE_LATIN_MIX_NAME_1));

        assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CJK));
        assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CHINESE));

        assertEquals("B", getLabel("Bob Smith"));
        verifyLabels(getLabels(), LABELS_JA_JP);
    }

    public void testChineseContactLocaleUtils() throws Exception {
        if (!hasSimplifiedChineseCollator) {
            Log.w(TAG, "Simplified Chinese collator not found; skipping test");
            return;
        }

        ContactLocaleUtils.setLocale(Locale.SIMPLIFIED_CHINESE);
        assertEquals("#", getLabel(PHONE_NUMBER_1));
        assertEquals("#", getLabel(PHONE_NUMBER_2));
        assertEquals("J", getLabel(LATIN_NAME));
        assertEquals("D", getLabel(CHINESE_NAME));
        assertEquals("D", getLabel(CHINESE_LATIN_MIX_NAME_1));
        assertEquals("B", getLabel("Bob Smith"));
        verifyLabels(getLabels(), LABELS_EN_US);

        if (hasTraditionalChineseCollator) {
            ContactLocaleUtils.setLocale(Locale.TRADITIONAL_CHINESE);
            assertEquals("#", getLabel(PHONE_NUMBER_1));
            assertEquals("#", getLabel(PHONE_NUMBER_2));
            assertEquals("J", getLabel(LATIN_NAME));
            assertEquals("7\u5283", getLabel(CHINESE_NAME));
            assertEquals("D", getLabel(CHINESE_LATIN_MIX_NAME_1));
        } else {
            Log.w(TAG, "Traditional Chinese collator not found");
        }

        ContactLocaleUtils.setLocale(Locale.SIMPLIFIED_CHINESE);
        Iterator<String> keys = getNameLookupKeys(CHINESE_NAME,
                FullNameStyle.CHINESE);
        verifyKeys(keys, CHINESE_NAME_KEY);

        keys = getNameLookupKeys(CHINESE_LATIN_MIX_NAME_1, FullNameStyle.CHINESE);
        verifyKeys(keys, CHINESE_LATIN_MIX_NAME_1_KEY);

        keys = getNameLookupKeys(CHINESE_LATIN_MIX_NAME_2, FullNameStyle.CHINESE);
        verifyKeys(keys, CHINESE_LATIN_MIX_NAME_2_KEY);

        if (hasTraditionalChineseCollator) {
            ContactLocaleUtils.setLocale(Locale.TRADITIONAL_CHINESE);
            assertEquals("B", getLabel("Bob Smith"));
            verifyLabels(getLabels(), LABELS_ZH_TW);
        }
    }

    public void testPinyinEnabledSecondaryLocale() throws Exception {
        if (!hasSimplifiedChineseCollator) {
            Log.w(TAG, "Simplified Chinese collator not found; skipping test");
            return;
        }

        ContactLocaleUtils.setLocales(
                new LocaleSet(Locale.ENGLISH, Locale.SIMPLIFIED_CHINESE));
        assertEquals("D", getLabel(CHINESE_NAME));

        Iterator<String> keys = getNameLookupKeys(CHINESE_NAME,
                FullNameStyle.CHINESE);
        verifyKeys(keys, CHINESE_NAME_KEY);
    }

    public void testPinyinDisabledSecondaryLocale() throws Exception {
        if (!hasSimplifiedChineseCollator) {
            Log.w(TAG, "Simplified Chinese collator not found; skipping test");
            return;
        }

        ContactLocaleUtils.setLocales(
                new LocaleSet(Locale.ENGLISH, Locale.JAPAN));
        assertEquals("", getLabel(CHINESE_NAME));

        assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CHINESE));
        assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CJK));
    }

    public void testChineseStyleNameWithDifferentLocale() throws Exception {
        if (!hasSimplifiedChineseCollator) {
            Log.w(TAG, "Simplified Chinese collator not found; skipping test");
            return;
        }

        ContactLocaleUtils.setLocale(Locale.ENGLISH);
        assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CHINESE));
        assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CJK));

        ContactLocaleUtils.setLocale(Locale.SIMPLIFIED_CHINESE);
        Iterator<String> keys = getNameLookupKeys(CHINESE_NAME,
                FullNameStyle.CJK);
        verifyKeys(keys, CHINESE_NAME_KEY);
        keys = getNameLookupKeys(LATIN_NAME, FullNameStyle.WESTERN);
        verifyKeys(keys, LATIN_NAME_KEY);
        keys = getNameLookupKeys(LATIN_NAME_2, FullNameStyle.WESTERN);
        verifyKeys(keys, LATIN_NAME_KEY_2);

        if (hasTraditionalChineseCollator) {
            ContactLocaleUtils.setLocale(Locale.TRADITIONAL_CHINESE);
            assertNull(getNameLookupKeys(CHINESE_NAME, FullNameStyle.CJK));
        }
    }

    public void testKoreanContactLocaleUtils() throws Exception {
        if (!hasKoreanCollator) {
            Log.w(TAG, "Korean collator not found; skipping test");
            return;
        }

        ContactLocaleUtils.setLocale(Locale.KOREA);
        assertEquals("\u3131", getLabel("\u1100"));
        assertEquals("\u3131", getLabel("\u3131"));
        assertEquals("\u3131", getLabel("\u1101"));
        assertEquals("\u314e", getLabel("\u1161"));
        assertEquals("B", getLabel("Bob Smith"));
        verifyLabels(getLabels(), LABELS_KO);
    }

    public void testArabicContactLocaleUtils() throws Exception {
        if (!hasArabicCollator) {
            Log.w(TAG, "Arabic collator not found; skipping test");
            return;
        }

        ContactLocaleUtils.setLocale(LOCALE_ARABIC);
        assertEquals("\u0646", getLabel(ARABIC_NAME));
        assertEquals("B", getLabel("Bob Smith"));
        verifyLabels(getLabels(), LABELS_AR);
    }

    public void testSerbianContactLocaleUtils() throws Exception {
        if (!hasSerbianCollator) {
            Log.w(TAG, "Serbian collator not found; skipping test");
            return;
        }

        ContactLocaleUtils.setLocale(LOCALE_SERBIAN);
        assertEquals("\u0408", getLabel(SERBIAN_NAME));
        assertEquals("B", getLabel("Bob Smith"));
    }

    public void testUkrainianContactLocaleUtils() throws Exception {
        if (!hasUkrainianCollator) {
            Log.w(TAG, "Ukrainian collator not found; skipping test");
            return;
        }

        ContactLocaleUtils.setLocale(LOCALE_UKRAINIAN);
        assertEquals("\u0407", getLabel(UKRAINIAN_NAME));
        assertEquals("\u0490", getLabel(UKRAINIAN_NAME_2));
        assertEquals("B", getLabel("Bob Smith"));
    }

    public void testGermanContactLocaleUtils() throws Exception {
        if (!hasGermanCollator) {
            return;
        }

        ContactLocaleUtils.setLocale(Locale.GERMANY);
        assertEquals("S", getLabel("Sacher"));

        // ICU 51 has labels Sch and St. These were removed in ICU 52
        assertEquals("S", getLabel("Schiller"));
        assertEquals("S", getLabel("Steiff"));
        verifyLabels(getLabels(), LABELS_EN_US);
    }

    private void verifyKeys(final Iterator<String> resultKeys, final String[] expectedKeys)
            throws Exception {
        HashSet<String> allKeys = new HashSet<String>();
        while (resultKeys.hasNext()) {
            allKeys.add(resultKeys.next());
        }
        assertEquals(new HashSet<String>(Arrays.asList(expectedKeys)), allKeys);
    }

    // Verify that the initial set of resultLabels matches the expectedLabels.
    // Ignore the (large) number of secondary locale labels that make up the
    // tail labels in the result set right before the final "#" and "" buckets.
    private void verifyLabels(final ArrayList<String> resultLabels,
            final String[] expectedLabels) throws Exception {
        final List<String> expectedLabelList = Arrays.asList(expectedLabels);
        final int numLabels = expectedLabelList.size() - 2;
        assertEquals(expectedLabelList.subList(0, numLabels),
                resultLabels.subList(0, numLabels));
    }
}
