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

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

import java.text.ParsePosition;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.text.DecimalFormat;
import com.ibm.icu.text.DecimalFormatSymbols;
import com.ibm.icu.text.MessageFormat;
import com.ibm.icu.text.NumberFormat;
import com.ibm.icu.text.PluralFormat;
import com.ibm.icu.text.PluralRules;
import com.ibm.icu.text.PluralRules.PluralType;
import com.ibm.icu.text.PluralRules.SampleType;
import com.ibm.icu.util.ULocale;

/**
 * @author tschumann (Tim Schumann)
 *
 */
public class PluralFormatUnitTest extends TestFmwk {
    public static void main(String[] args) throws Exception {
        new PluralFormatUnitTest().run(args);
    }

    public void TestConstructor() {
        // Test correct formatting of numbers.
        PluralFormat plFmts[] = new PluralFormat[8];
        plFmts[0] = new PluralFormat();
        plFmts[0].applyPattern("other{#}");
        plFmts[1] = new PluralFormat(PluralRules.DEFAULT);
        plFmts[1].applyPattern("other{#}");
        plFmts[2] = new PluralFormat(PluralRules.DEFAULT, "other{#}");
        plFmts[3] = new PluralFormat("other{#}");
        plFmts[4] = new PluralFormat(ULocale.getDefault());
        plFmts[4].applyPattern("other{#}");
        plFmts[5] = new PluralFormat(ULocale.getDefault(), PluralRules.DEFAULT);
        plFmts[5].applyPattern("other{#}");
        plFmts[6] = new PluralFormat(ULocale.getDefault(),
                PluralRules.DEFAULT,
                "other{#}");
        plFmts[7] = new PluralFormat(ULocale.getDefault(), "other{#}");

        // These plural formats should produce the same output as a
        // NumberFormat for the default locale.
        NumberFormat numberFmt = NumberFormat.getInstance(ULocale.getDefault());
        for (int n = 1; n < 13; n++) {
            String result = numberFmt.format(n);
            for (int k = 0; k < plFmts.length; ++k) {
                this.assertEquals("PluralFormat's output is not as expected",
                        result, plFmts[k].format(n));
            }
        }
        // Test some bigger numbers.
        for (int n = 100; n < 113; n++) {
            String result = numberFmt.format(n*n);
            for (int k = 0; k < plFmts.length; ++k) {
                this.assertEquals("PluralFormat's output is not as expected",
                        result, plFmts[k].format(n*n));
            }
        }
    }

    public void TestApplyPatternAndFormat() {
        // Create rules for testing.
        PluralRules oddAndEven =  PluralRules.createRules("odd: n mod 2 is 1");
        {
            // Test full specified case for testing RuleSet
            PluralFormat plfOddAndEven = new PluralFormat(oddAndEven);
            plfOddAndEven.applyPattern("odd{# is odd.} other{# is even.}");

            // Test fall back to other.
            PluralFormat plfOddOrEven = new PluralFormat(oddAndEven);
            plfOddOrEven.applyPattern("other{# is odd or even.}");

            NumberFormat numberFormat =
                    NumberFormat.getInstance(ULocale.getDefault());
            for (int i = 0; i < 22; ++i) {
                assertEquals("Fallback to other gave wrong results",
                        numberFormat.format(i) + " is odd or even.",
                        plfOddOrEven.format(i));
                assertEquals("Fully specified PluralFormat gave wrong results",
                        numberFormat.format(i) + ((i%2 == 1) ?  " is odd."
                                :  " is even."),
                                plfOddAndEven.format(i));
            }

            // ICU 4.8 does not check for duplicate keywords any more.
            PluralFormat pf = new PluralFormat(ULocale.ENGLISH, oddAndEven,
                    "odd{foo} odd{bar} other{foobar}");
            assertEquals("should use first occurrence of the 'odd' keyword", "foo", pf.format(1));
            pf.applyPattern("odd{foo} other{bar} other{foobar}");
            assertEquals("should use first occurrence of the 'other' keyword", "bar", pf.format(2));
            // This sees the first "other" before calling the PluralSelector which then selects "other".
            pf.applyPattern("other{foo} odd{bar} other{foobar}");
            assertEquals("should use first occurrence of the 'other' keyword", "foo", pf.format(2));
        }
        // omit other keyword.
        try {
            PluralFormat plFmt = new PluralFormat(oddAndEven);
            plFmt.applyPattern("odd{foo}");
            errln("Not defining plural case other should result in an " +
                    "exception but did not.");
        }catch (IllegalArgumentException e){}

        // ICU 4.8 does not check for unknown keywords any more.
        {
            PluralFormat pf = new PluralFormat(ULocale.ENGLISH, oddAndEven, "otto{foo} other{bar}");
            assertEquals("should ignore unknown keywords", "bar", pf.format(1));
        }

        // Test invalid keyword.
        try {
            PluralFormat plFmt = new PluralFormat(oddAndEven);
            plFmt.applyPattern("*odd{foo} other{bar}");
            errln("Defining a message for an invalid keyword should result in " +
                    "an exception but did not.");
        }catch (IllegalArgumentException e){}

        // Test invalid syntax
        //   -- comma between keyword{message} clauses
        //   -- space in keywords
        //   -- keyword{message1}{message2}
        try {
            PluralFormat plFmt = new PluralFormat(oddAndEven);
            plFmt.applyPattern("odd{foo},other{bar}");
            errln("Separating keyword{message} items with other characters " +
                    "than space should provoke an exception but did not.");
        }catch (IllegalArgumentException e){}
        try {
            PluralFormat plFmt = new PluralFormat(oddAndEven);
            plFmt.applyPattern("od d{foo} other{bar}");
            errln("Spaces inside keywords should provoke an exception but " +
                    "did not.");
        }catch (IllegalArgumentException e){}
        try {
            PluralFormat plFmt = new PluralFormat(oddAndEven);
            plFmt.applyPattern("odd{foo}{foobar}other{foo}");
            errln("Defining multiple messages after a keyword should provoke " +
                    "an exception but did not.");
        }catch (IllegalArgumentException e){}

        // Check that nested format is preserved.
        {
            PluralFormat plFmt = new PluralFormat(oddAndEven);
            plFmt.applyPattern("odd{The number {0, number, #.#0} is odd.}" +
                    "other{The number {0, number, #.#0} is even.}");
            for (int i = 1; i < 3; ++i) {
                assertEquals("format did not preserve a nested format string.",
                        ((i % 2 == 1) ?
                                "The number {0, number, #.#0} is odd."
                                : "The number {0, number, #.#0} is even."),
                                plFmt.format(i));
            }

        }
        // Check that a pound sign in curly braces is preserved.
        {
            PluralFormat plFmt = new PluralFormat(oddAndEven);
            plFmt.applyPattern("odd{The number {1,number,#} is odd.}" +
                    "other{The number {2,number,#} is even.}");
            for (int i = 1; i < 3; ++i) {
                assertEquals("format did not preserve # inside curly braces.",
                        ((i % 2 == 1) ? "The number {1,number,#} is odd."
                                : "The number {2,number,#} is even."),
                                plFmt.format(i));
            }

        }
    }


    public void TestSamples() {
        Map<ULocale,Set<ULocale>> same = new LinkedHashMap();
        for (ULocale locale : PluralRules.getAvailableULocales()) {
            ULocale otherLocale = PluralRules.getFunctionalEquivalent(locale, null);
            Set<ULocale> others = same.get(otherLocale);
            if (others == null) same.put(otherLocale, others = new LinkedHashSet());
            others.add(locale);
            continue;
        }
        for (ULocale locale0 : same.keySet()) {
            PluralRules rules = PluralRules.forLocale(locale0);
            String localeName = locale0.toString().length() == 0 ? "root" : locale0.toString();
            logln(localeName + "\t=\t" + same.get(locale0));
            logln(localeName + "\ttoString\t" + rules.toString());
            Set<String> keywords = rules.getKeywords();
            for (String keyword : keywords) {
                Collection<Double> list = rules.getSamples(keyword);
                if (list.size() == 0) {
                    // if there aren't any integer samples, get the decimal ones.
                    list = rules.getSamples(keyword, SampleType.DECIMAL);
                }

                if (list == null || list.size() == 0) {
                    errln("Empty list for " + localeName + " : " + keyword);
                } else {
                    logln("\t" + localeName + " : " + keyword + " ; " + list);
                }
            }
        }
    }

    public void TestSetLocale() {
        // Create rules for testing.
        PluralRules oddAndEven = PluralRules.createRules("odd__: n mod 2 is 1");

        PluralFormat plFmt = new PluralFormat(oddAndEven);
        plFmt.applyPattern("odd__{odd} other{even}");
        plFmt.setLocale(ULocale.ENGLISH);

        // Check that pattern gets deleted.
        NumberFormat nrFmt = NumberFormat.getInstance(ULocale.ENGLISH);
        assertEquals("pattern was not resetted by setLocale() call.",
                nrFmt.format(5),
                plFmt.format(5));

        // Check that rules got updated.
        plFmt.applyPattern("odd__{odd} other{even}");
        assertEquals("SetLocale should reset rules but did not.", "even", plFmt.format(1));

        plFmt.applyPattern("one{one} other{not one}");
        for (int i = 0; i < 20; ++i) {
            assertEquals("Wrong ruleset loaded by setLocale()",
                    ((i==1) ? "one" : "not one"),
                    plFmt.format(i));
        }
    }

    public void TestParse() {
        PluralFormat plFmt = new PluralFormat("other{test}");
        try {
            plFmt.parse("test", new ParsePosition(0));
            errln("parse() should throw an UnsupportedOperationException but " +
                    "did not");
        } catch (UnsupportedOperationException e) {
        }

        plFmt = new PluralFormat("other{test}");
        try {
            plFmt.parseObject("test", new ParsePosition(0));
            errln("parse() should throw an UnsupportedOperationException but " +
                    "did not");
        } catch (UnsupportedOperationException e) {
        }
    }

    public void TestPattern() {
        Object[] args = { "acme", null };

        {
            // ICU 4.8 PluralFormat does not trim() its pattern any more.
            // None of the other *Format classes do.
            String pat = "  one {one ''widget} other {# widgets}  ";
            PluralFormat pf = new PluralFormat(pat);
            assertEquals("should not trim() the pattern", pat, pf.toPattern());
        }

        MessageFormat pfmt = new MessageFormat("The disk ''{0}'' contains {1, plural,  one {one ''''{1, number, #.0}'''' widget} other {# widgets}}.");
        logln("");
        for (int i = 0; i < 3; ++i) {
            args[1] = new Integer(i);
            logln(pfmt.format(args));
        }
        /* ICU 4.8 returns null instead of a choice/plural/select Format object
         * (because it does not create an object for any "complex" argument).
        PluralFormat pf = (PluralFormat)pfmt.getFormatsByArgumentIndex()[1];
        logln(pf.toPattern());
         */
        logln(pfmt.toPattern());
        MessageFormat pfmt2 = new MessageFormat(pfmt.toPattern());
        assertEquals("message formats are equal", pfmt, pfmt2);
    }

    public void TestExtendedPluralFormat() {
        String[] targets = {
                "There are no widgets.",
                "There is one widget.",
                "There is a bling widget and one other widget.",
                "There is a bling widget and 2 other widgets.",
                "There is a bling widget and 3 other widgets.",
                "Widgets, five (5-1=4) there be.",
                "There is a bling widget and 5 other widgets.",
                "There is a bling widget and 6 other widgets.",
        };
        String pluralStyle =
                "offset:1.0 "
                        + "=0 {There are no widgets.} "
                        + "=1.0 {There is one widget.} "
                        + "=5 {Widgets, five (5-1=#) there be.} "
                        + "one {There is a bling widget and one other widget.} "
                        + "other {There is a bling widget and # other widgets.}";
        PluralFormat pf = new PluralFormat(ULocale.ENGLISH, pluralStyle);
        MessageFormat mf = new MessageFormat("{0,plural," + pluralStyle + "}", ULocale.ENGLISH);
        Integer args[] = new Integer[1];
        for (int i = 0; i <= 7; ++i) {
            String result = pf.format(i);
            assertEquals("PluralFormat.format(value " + i + ")", targets[i], result);
            args[0] = i;
            result = mf.format(args);
            assertEquals("MessageFormat.format(value " + i + ")", targets[i], result);
        }

        // Try explicit values after keywords.
        pf.applyPattern("other{zz}other{yy}one{xx}one{ww}=1{vv}=1{uu}");
        assertEquals("should find first matching *explicit* value", "vv", pf.format(1));
    }

    public void TestExtendedPluralFormatParsing() {
        String[] failures = {
                "offset:1..0 =0 {Foo}",
                "offset:1.0 {Foo}",
                "=0= {Foo}",
                "=0 {Foo} =0.0 {Bar}",
                " = {Foo}",
        };
        for (String fmt : failures) {
            try {
                new PluralFormat(fmt);
                fail("expected exception when parsing '" + fmt + "'");
            } catch (IllegalArgumentException e) {
                // ok
            }
        }
    }

    public void TestOrdinalFormat() {
        String pattern = "one{#st file}two{#nd file}few{#rd file}other{#th file}";
        PluralFormat pf = new PluralFormat(ULocale.ENGLISH, PluralType.ORDINAL, pattern);
        assertEquals("PluralFormat.format(321)", "321st file", pf.format(321));
        assertEquals("PluralFormat.format(22)", "22nd file", pf.format(22));
        assertEquals("PluralFormat.format(3)", "3rd file", pf.format(3));

        // Code coverage: Use the other new-for-PluralType constructor as well.
        pf = new PluralFormat(ULocale.ENGLISH, PluralType.ORDINAL);
        pf.applyPattern(pattern);
        assertEquals("PluralFormat.format(456)", "456th file", pf.format(456));
        assertEquals("PluralFormat.format(111)", "111th file", pf.format(111));
    }

    public void TestDecimals() {
        // Simple number replacement.
        PluralFormat pf = new PluralFormat(ULocale.ENGLISH, "one{one meter}other{# meters}");
        assertEquals("simple format(1)", "one meter", pf.format(1));
        assertEquals("simple format(1.5)", "1.5 meters", pf.format(1.5));
        PluralFormat pf2 = new PluralFormat(ULocale.ENGLISH,
                "offset:1 one{another meter}other{another # meters}");
        pf2.setNumberFormat(new DecimalFormat("0.0", new DecimalFormatSymbols(ULocale.ENGLISH)));
        assertEquals("offset-decimals format(1)", "another 0.0 meters", pf2.format(1));
        assertEquals("offset-decimals format(2)", "another 1.0 meters", pf2.format(2));
        assertEquals("offset-decimals format(2.5)", "another 1.5 meters", pf2.format(2.5));
    }
}
