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

// Copyright 2006 Google Inc.  All Rights Reserved.

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

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.impl.duration.BasicPeriodFormatterService;
import com.ibm.icu.impl.duration.Period;
import com.ibm.icu.impl.duration.PeriodBuilder;
import com.ibm.icu.impl.duration.PeriodBuilderFactory;
import com.ibm.icu.impl.duration.PeriodFormatter;
import com.ibm.icu.impl.duration.PeriodFormatterFactory;
import com.ibm.icu.impl.duration.TimeUnit;
import com.ibm.icu.impl.duration.TimeUnitConstants;
import com.ibm.icu.impl.duration.impl.DataRecord.ECountVariant;
import com.ibm.icu.impl.duration.impl.DataRecord.EUnitVariant;

/**
 * Test cases for en
 */
public class LanguageTestRoot extends TestFmwk implements TimeUnitConstants {

    private static final TimeUnit[] units = {
        TimeUnit.YEAR, TimeUnit.MONTH, TimeUnit.WEEK, TimeUnit.DAY, TimeUnit.HOUR, 
        TimeUnit.MINUTE, TimeUnit.SECOND, TimeUnit.MILLISECOND
    };

    protected boolean inheritTargets() {
        return true;
    }

    private static final BasicPeriodFormatterService pfs = BasicPeriodFormatterService
            .getInstance();

    private TestData data;
    private String locale;

    //private DurationFormatterFactory dfFactory;
    private PeriodFormatterFactory pfFactory;
    private PeriodBuilderFactory pbFactory;

    private PrintWriter pw;

    private static final Map datacache = new HashMap(); // String->TestData

    private static final long[] approxDurations = {
        36525L*24*60*60*10, 3045*24*60*60*10L, 7*24*60*60*1000L, 24*60*60*1000L, 
        60*60*1000L, 60*1000L, 1000L, 1L
    };

    private static long approximateDuration(TimeUnit unit) {
        return approxDurations[unit.ordinal()];
    }

    private static TestData getTestData(String locale) {
        // debug
        if (locale.equals("testFullPluralizedForms")) {
            Thread.dumpStack();
        }
        TestData data = (TestData) datacache.get(locale);
        if (data == null) {
            try {
                InputStream is = LanguageTestRoot.class
                        .getResourceAsStream("testdata/testdata_" + locale
                                + ".txt");
                // debug
                if (is == null) {
                    System.out.println("test data for locale '" + locale
                            + "' is null");
                }
                InputStreamReader isr = new InputStreamReader(is, "UTF-8");
                data = new FileTestData(isr);
            } catch (Exception e) {
                System.err.println(e.getMessage());
                // swallow any exception
            }
        }
        return data;
    }

    public LanguageTestRoot(String locale, boolean ignore) {
        this(getTestData(locale), locale);
    }

    public LanguageTestRoot(TestData data, String locale) {
        if (data == null) {
            data = DefaultData.getInstance();
        }
        this.data = data;
        this.locale = locale;
    }

    public static void writeData(PrintWriter pw, String locale)
            throws Exception {
        LanguageTestRoot test = new LanguageTestRoot(DefaultData.getInstance(),
                locale);
        test.writeData(pw);
    }

    private void writeData(PrintWriter writer) throws Exception {
/*
      pw = writer;
      setUp();
      testFullPluralizedForms();
      tearDown();
      setUp();
      testMediumForms();
      tearDown();
      setUp();
      testShortForms();
      tearDown();
      setUp();
      testCustomMinutes();
      tearDown();
      setUp();
      testLimitedUnits();
      tearDown();
      setUp();
      testHalfUnits();
      tearDown();
      setUp();
      testFractionalUnits();
      tearDown();
      setUp();
      testMultipleUnits();
      tearDown();
      pw = null;
      writer.flush();
*/
    }

    protected void xAssertEquals(String msg, String[] expected, int n,
            String actual) {
        if (pw != null) {
            pw.println(actual);
        } else {
            // java doesn't dump enough context to be useful, so do it myself
            if (actual == null) {
                assertEquals(msg, expected[n], actual);
            } else {
                if (!actual.equals(expected[n])) {
                    fail("\n(!!"
                            + msg
                            + ") "
                            + asciify("expected '" + expected[n]
                                    + "' but got '" + actual + "'"));
                }
            }
        }
    }

    protected static String timestring(Period ts) {
        StringBuffer buf = new StringBuffer();
        if (ts.isMoreThan()) {
            buf.append("mt");
        } else if (ts.isLessThan()) {
            buf.append("lt");
        }
        for (int i = 0; i < units.length; ++i) {
            TimeUnit p = units[i];
            if (ts.isSet(p)) {
                buf.append(Float.toString(ts.getCount(p)));
                buf.append(p.toString().charAt(0));
            }
        }
        buf.append(ts.isInPast() ? "p" : "f");
        return buf.toString();
    }

    protected static String asciify(String s) {
        StringBuffer sb = null;
        for (int i = 0, e = s.length(); i < e; ++i) {
            char c = s.charAt(i);
            if (c < 0x20 || c > 0x7e) {
                if (sb == null) {
                    sb = new StringBuffer();
                    sb.append(s.substring(0, i));
                }
                sb.append("\\u");
                if (c < 0x10) {
                    sb.append("000");
                } else if (c < 0x100) {
                    sb.append("00");
                } else if (c < 0x1000) {
                    sb.append("0");
                }
                sb.append(Integer.toHexString(c));
            } else {
                if (sb != null) {
                    sb.append(c);
                }
            }
        }
        if (sb != null) {
            System.out.println("asciify '" + s + "' --> '" + sb.toString()
                    + "'");
        }
        return sb == null ? s : sb.toString();
    }

    private void xAssertEquals(String[] expected, int n, String actual) {
        xAssertEquals(null, expected, n, actual);
    }

    protected void setUp() throws Exception {
        pfFactory = pfs.newPeriodFormatterFactory().setLocale(locale);
        pbFactory = pfs.newPeriodBuilderFactory().setLocale(locale);
    }

    public void testFullPluralizedForms() throws Exception {
        setUp();
        int[] counts = data.getFullPluralizedFormCounts();
        String[] targets = data.getFullPluralizedFormTargets();
        if (pw != null) {
            pw.println("=fullPluralizedFormCounts");
            for (int i = 0; i < counts.length; ++i) {
                int c = counts[i];
                pw.println(String.valueOf(c));
            }
            pw.println("=fullPluralizedFormTargets");
        }

        int n = 0;
        PeriodFormatter pf = pfFactory.getFormatter();
        for (int i = 0; i < units.length; ++i) {
            TimeUnit u = units[i];
            // System.err.print("\nunit: " + u);
            PeriodBuilder pb = pbFactory.getFixedUnitBuilder(u);
            for (int j = 0; j < counts.length; ++j) {
                int c = counts[j];
                // System.err.println("\ncount[" + j + "]: " + c);
                Period p = pb.create(approximateDuration(u) * c);
                String string = pf.format(p);
                xAssertEquals(u.toString() + c, targets, n++, string);
            }
        }
    }

    public void testMediumForms() throws Exception {
        setUp();
        String[] targets = data.getMediumFormTargets();

        if (pw != null) {
            pw.println("=mediumFormTargets");
        }

        pfFactory.setUnitVariant(EUnitVariant.MEDIUM);
        pfFactory.setDisplayPastFuture(false);
        PeriodFormatter pf = pfFactory.getFormatter();
        int n = 0;
        for (int i = 0; i < units.length; ++i) {
            TimeUnit u = units[i];
            PeriodBuilder pb = pbFactory.getFixedUnitBuilder(u);
            Period p = pb.create(approximateDuration(u) * 3);
            String string = pf.format(p);
            xAssertEquals(u.toString(), targets, n++, string);
        }
    }

    public void testShortForms() throws Exception {
        setUp();
        String[] targets = data.getShortFormTargets();

        if (pw != null) {
            pw.println("=shortFormTargets");
        }

        pfFactory.setUnitVariant(EUnitVariant.SHORT);
        pfFactory.setDisplayPastFuture(false);
        PeriodFormatter pf = pfFactory.getFormatter();
        int n = 0;
        for (int i = 0; i < units.length; ++i) {
            TimeUnit u = units[i];
            PeriodBuilder pb = pbFactory.getFixedUnitBuilder(u);
            Period p = pb.create(approximateDuration(u) * 3);
            String string = pf.format(p);
            xAssertEquals(u.toString(), targets, n++, string);
        }
    }

    public void testCustomMinutes() throws Exception {
        setUp();
        String[] targets = data.getCustomMinuteTargets();

        if (pw != null) {
            pw.println("=customMinuteTargets");
        }

        pfFactory.setCountVariant(ECountVariant.INTEGER_CUSTOM);
        pfFactory.setDisplayPastFuture(false);
        PeriodFormatter pf = pfFactory.getFormatter();

        Period p = Period.at(1, HOUR);
        int n = 0;
        for (int i = 1; i < 12; ++i) {
            p = p.and(i * 5, MINUTE).omit(HOUR);
            xAssertEquals(targets, n++, pf.format(p));
            p = p.and(1, HOUR);
            xAssertEquals(targets, n++, pf.format(p));
        }
    }

    public void testLimitedUnits() throws Exception {
        setUp();
        String[] targets = data.getLimitedUnitTargets();

        if (pw != null) {
            pw.println("=limitedPeriodTargets");
        }

        Period p = Period.at(1, MONTH);
        int n = 0;
        for (int i = 0; i < 3; ++i) {
            switch (i) {
            case 0:
                p = p.at();
                break;
            case 1:
                p = p.lessThan();
                break;
            case 2:
                p = p.moreThan();
                break;
            }
            for (int j = 0; j < 3; ++j) {
                pfFactory.setDisplayPastFuture(true);
                switch (j) {
                case 0:
                    pfFactory.setDisplayPastFuture(false);
                    break;
                case 1:
                    p = p.inPast();
                    break;
                case 2:
                    p = p.inFuture();
                    break;
                }

                PeriodFormatter pf = pfFactory.getFormatter();

                p = p.omit(WEEK).omit(DAY);
                xAssertEquals(targets, n++, pf.format(p));

                p = p.and(2, WEEK);
                xAssertEquals(targets, n++, pf.format(p));

                p = p.and(3, DAY);
                xAssertEquals(targets, n++, pf.format(p));
            }
        }

        p = p.omit(MONTH).omit(WEEK).omit(DAY).and(1, HOUR);
        for (int i = 0; i < 3; ++i) {
            switch (i) {
            case 0:
                p = p.at();
                break;
            case 1:
                p = p.lessThan();
                break;
            case 2:
                p = p.moreThan();
                break;
            }
            for (int j = 0; j < 3; ++j) {
                pfFactory.setDisplayPastFuture(true);
                switch (j) {
                case 0:
                    pfFactory.setDisplayPastFuture(false);
                    break;
                case 1:
                    p = p.inPast();
                    break;
                case 2:
                    p = p.inFuture();
                    break;
                }

                PeriodFormatter pf = pfFactory.getFormatter();

                p = p.omit(MINUTE).omit(SECOND);
                xAssertEquals(targets, n++, pf.format(p));

                p = p.and(2, MINUTE);
                xAssertEquals(targets, n++, pf.format(p));

                p = p.and(3, SECOND);
                xAssertEquals(targets, n++, pf.format(p));
            }
        }
    }

    public void testHalfUnits() throws Exception {
        setUp();
        int[] counts = data.getHalfUnitCounts();
        String[] targets = data.getHalfUnitTargets();

        if (pw != null) {
            pw.println("=halfPeriodCounts");
            for (int i = 0; i < counts.length; ++i) {
                int c = counts[i];
                pw.println(String.valueOf(c));
            }
            pw.println("=halfPeriodTargets");
        }

        pfFactory.setCountVariant(ECountVariant.HALF_FRACTION);
        pfFactory.setDisplayPastFuture(false);
        PeriodFormatter pf = pfFactory.getFormatter();

        int n = 0;
        for (int i = 0; i < units.length; ++i) {
            TimeUnit u = units[i];
            for (int j = 0; j < counts.length; ++j) {
                int c = counts[j];
                Period p = Period.at(c + .5f, u);
                String string = pf.format(p);
                xAssertEquals(u.toString(), targets, n++, string);
            }
        }
    }

    public void testFractionalUnits() throws Exception {
        setUp();
        float[] counts = data.getFractionalUnitCounts();
        String[] targets = data.getFractionalUnitTargets();

        if (pw != null) {
            pw.println("=fractionalPeriodCounts");
            for (int i = 0; i < counts.length; ++i) {
                float c = counts[i];
                pw.println(String.valueOf(c));
            }
            pw.println("=fractionalPeriodTargets");
        }

        pfFactory.setCountVariant(ECountVariant.DECIMAL2);
        pfFactory.setDisplayPastFuture(false);
        PeriodFormatter pf = pfFactory.getFormatter();

        int n = 0;
        for (int i = 0; i < units.length; ++i) {
            TimeUnit u = units[i];
            for (int j = 0; j < counts.length; ++j) {
                float c = counts[j];
                Period p = Period.at(c, u);
                String string = pf.format(p);
                xAssertEquals(u.toString(), targets, n++, string);
            }
        }
    }

    public void testMultipleUnits() throws Exception {
        setUp();
        String[] targets = data.getMultipleUnitTargets();

        if (pw != null) {
            pw.println("=multiplePeriodTargets");
        }

        pfFactory.setCountVariant(ECountVariant.INTEGER);
        pfFactory.setDisplayPastFuture(false);
        PeriodFormatter pf = pfFactory.getFormatter();

        int n = 0;
        for (int i = 0; i < units.length - 1; ++i) {
            Period p = Period.at(1, units[i]).and(2, units[i + 1]);
            xAssertEquals(targets, n++, pf.format(p));
            if (i < units.length - 2) {
                p = Period.at(1, units[i]).and(3, units[i + 2]);
                xAssertEquals(targets, n++, pf.format(p));
                p = Period.at(1, units[i]).and(2, units[i + 1]).and(3,
                        units[i + 2]);
                xAssertEquals(targets, n++, pf.format(p));
            }
        }
    }

    public static abstract class TestData {
        abstract int[] getFullPluralizedFormCounts();
        abstract String[] getFullPluralizedFormTargets();
        abstract String[] getMediumFormTargets();
        abstract String[] getShortFormTargets();
        abstract String[] getCustomMinuteTargets();
        abstract String[] getLimitedUnitTargets();
        abstract int[] getHalfUnitCounts();
        abstract String[] getHalfUnitTargets();
        abstract float[] getFractionalUnitCounts();
        abstract String[] getFractionalUnitTargets();
        abstract String[] getMultipleUnitTargets();
    }

}

class FileTestData extends LanguageTestRoot.TestData {
    private int[] fullPluralizedFormCounts;
    private String[] fullPluralizedFormTargets;
    private String[] mediumFormTargets;
    private String[] shortFormTargets;
    private String[] customMinuteTargets;
    private String[] limitedUnitTargets;
    private int[] halfUnitCounts;
    private String[] halfUnitTargets;
    private float[] fractionalUnitCounts;
    private String[] fractionalUnitTargets;
    private String[] multipleUnitTargets;

    int[] getFullPluralizedFormCounts() {
        return fullPluralizedFormCounts;
    }

    String[] getFullPluralizedFormTargets() {
        return fullPluralizedFormTargets;
    }

    String[] getMediumFormTargets() {
        return mediumFormTargets;
    }

    String[] getShortFormTargets() {
        return shortFormTargets;
    }

    String[] getCustomMinuteTargets() {
        return customMinuteTargets;
    }

    String[] getLimitedUnitTargets() {
        return limitedUnitTargets;
    }

    int[] getHalfUnitCounts() {
        return halfUnitCounts;
    }

    String[] getHalfUnitTargets() {
        return halfUnitTargets;
    }

    float[] getFractionalUnitCounts() {
        return fractionalUnitCounts;
    }

    String[] getFractionalUnitTargets() {
        return fractionalUnitTargets;
    }

    String[] getMultipleUnitTargets() {
        return multipleUnitTargets;
    }

    public FileTestData(InputStreamReader isr) throws Exception {
        BufferedReader br = new BufferedReader(isr);

        class Wrapup {
            int[] intArray;

            float[] floatArray;

            String[] stringArray;

            void wrapup(List /* of String */list, Element element) {
                if (list == null)
                    return;

                switch (element.mode) {
                case EMode.mString:
                    stringArray = (String[]) list.toArray(new String[list
                            .size()]);
                    break;

                case EMode.mInt:
                    intArray = new int[list.size()];
                    for (int i = 0, e = intArray.length; i < e; ++i) {
                        intArray[i] = Integer.parseInt((String) list.get(i));
                    }
                    break;

                case EMode.mFloat:
                    floatArray = new float[list.size()];
                    for (int i = 0, e = floatArray.length; i < e; ++i) {
                        floatArray[i] = Float.parseFloat((String) list.get(i));
                    }
                    break;
                }

                switch (element.which) {
                case Element.XfullPluralizedFormCounts:
                    FileTestData.this.fullPluralizedFormCounts = intArray;
                    break;
                case Element.XfullPluralizedFormTargets:
                    FileTestData.this.fullPluralizedFormTargets = stringArray;
                    break;
                case Element.XmediumFormTargets:
                    FileTestData.this.mediumFormTargets = stringArray;
                    break;
                case Element.XshortFormTargets:
                    FileTestData.this.shortFormTargets = stringArray;
                    break;
                case Element.XcustomMinuteTargets:
                    FileTestData.this.customMinuteTargets = stringArray;
                    break;
                case Element.XlimitedUnitTargets:
                    FileTestData.this.limitedUnitTargets = stringArray;
                    break;
                case Element.XhalfUnitCounts:
                    FileTestData.this.halfUnitCounts = intArray;
                    break;
                case Element.XhalfUnitTargets:
                    FileTestData.this.halfUnitTargets = stringArray;
                    break;
                case Element.XfractionalUnitCounts:
                    FileTestData.this.fractionalUnitCounts = floatArray;
                    break;
                case Element.XfractionalUnitTargets:
                    FileTestData.this.fractionalUnitTargets = stringArray;
                    break;
                case Element.XmultipleUnitTargets:
                    FileTestData.this.multipleUnitTargets = stringArray;
                    break;
                }
            }
        }
        Wrapup w = new Wrapup();

        List /* of String */list = null;
        Element element = null;
        String line = null;
        while (null != (line = br.readLine())) {
            line = line.trim();
            if (line.length() == 0 || line.charAt(0) == '#')
                continue;
            if (line.charAt(0) == '=') {
                w.wrapup(list, element);

                list = new ArrayList();
                element = Element.forString(line.substring(1));
            } else if (line.equals("null")) {
                list.add(null);
            } else {
                list.add(line);
            }
        }
        w.wrapup(list, element);
    }
}

class DefaultData extends LanguageTestRoot.TestData {
    private static final int[] fullPluralizedFormCounts = { -3, -2, -1, 0, 1,
            2, 3, 5, 10, 11, 12, 20, 21, 22, 23, 25 };

    private static final int[] halfUnitCounts = { 0, 1, 2, 5, 10, 11, 12, 20,
            21, 22 };

    private static final float[] fractionalUnitCounts = { 0.025f, 1.0f, 1.205f,
            2.125f, 12.05f };

    private static final DefaultData instance = new DefaultData();

    private DefaultData() {
    }

    public static DefaultData getInstance() {
        return instance;
    }

    int[] getFullPluralizedFormCounts() {
        return fullPluralizedFormCounts;
    }

    String[] getFullPluralizedFormTargets() {
        return null;
    }

    String[] getMediumFormTargets() {
        return null;
    }

    String[] getShortFormTargets() {
        return null;
    }

    String[] getCustomMinuteTargets() {
        return null;
    }

    String[] getLimitedUnitTargets() {
        return null;
    }

    int[] getHalfUnitCounts() {
        return halfUnitCounts;
    }

    String[] getHalfUnitTargets() {
        return null;
    }

    float[] getFractionalUnitCounts() {
        return fractionalUnitCounts;
    }

    String[] getFractionalUnitTargets() {
        return null;
    }

    String[] getMultipleUnitTargets() {
        return null;
    }
}

class EMode {
    static final int mString = 0;
    static final int mInt = 1;
    static final int mFloat = 2;
}

class Element {
    final String name;
    final int mode;
    final int which;

    static int counter = 0;
    static Element[] list = new Element[11];

    Element(String name) {
        this.name = name;
        mode = EMode.mString;
        this.which = counter++;
        list[this.which] = this;
    }

    Element(String name, int mode) {
        this.name = name;
        this.mode = mode;
        this.which = counter++;
        list[this.which] = this;
    }

    static final int XfullPluralizedFormCounts = 0;
    static final int XfullPluralizedFormTargets = 1;
    static final int XmediumFormTargets = 2;
    static final int XshortFormTargets = 3;
    static final int XcustomMinuteTargets = 4;
    static final int XlimitedUnitTargets = 5;
    static final int XhalfUnitCounts = 6;
    static final int XhalfUnitTargets = 7;
    static final int XfractionalUnitCounts = 8;
    static final int XfractionalUnitTargets = 9;
    static final int XmultipleUnitTargets = 10;

    static final Element fullPluralizedFormCounts = new Element(
            "fullPluralizedFormCounts", EMode.mInt);

    static final Element fullPluralizedFormTargets = new Element(
            "fullPluralizedFormTargets");

    static final Element mediumFormTargets = new Element("mediumFormTargets");

    static final Element shortFormTargets = new Element("shortFormTargets");

    static final Element customMinuteTargets = new Element(
            "customMinuteTargets");

    static final Element limitedUnitTargets = new Element("limitedUnitTargets");

    static final Element halfUnitCounts = new Element("halfUnitCounts",
            EMode.mInt);

    static final Element halfUnitTargets = new Element("halfUnitTargets");

    static final Element fractionalUnitCounts = new Element(
            "fractionalUnitCounts", EMode.mFloat);

    static final Element fractionalUnitTargets = new Element(
            "fractionalUnitTargets");

    static final Element multipleUnitTargets = new Element(
            "multipleUnitTargets");

    static Element forString(String s) {
        for (int i = 0; i < list.length; ++i) {
            if (list[i].name.equals(s)) {
                return list[i];
            }
        }
        return null;
    }
}
      
