/*
 *******************************************************************************
 * Copyright (C) 2007-2011, 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.MessageFormat;
import com.ibm.icu.text.NumberFormat;
import com.ibm.icu.text.PluralFormat;
import com.ibm.icu.text.PluralRules;
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 == 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.",
        };
        PluralFormat pf = new PluralFormat(
                ULocale.ENGLISH,
                "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.}");
        for (int i = 0; i < 7; ++i) {
            String result = pf.format(i);
            assertEquals("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
            }
        }
    }
}
