package org.unicode.cldr.unittest;

import java.io.File;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.unicode.cldr.util.CLDRFile;
import org.unicode.cldr.util.CLDRFile.DraftStatus;
import org.unicode.cldr.util.CldrUtility;
import org.unicode.cldr.util.Factory;
import org.unicode.cldr.util.SimpleFactory;

import com.ibm.icu.text.UTF16;

public class TestCLDRFile {
    public static void main(String[] args) {
        testExtraPaths();
        TestTimeZonePath();
        testDraftFilter();
        simpleTest();
        resolutionTest();
    }

    public static Factory getAllFactory() {
        File mainDir = new File(CldrUtility.MAIN_DIRECTORY);
        if (!mainDir.isDirectory()) {
            throw new IllegalArgumentException("MAIN_DIRECTORY is not a directory: " + CldrUtility.MAIN_DIRECTORY);
        }
        File seedDir = new File(CldrUtility.SEED_DIRECTORY);
        if (!seedDir.isDirectory()) {
            throw new IllegalArgumentException("SEED_DIRECTORY is not a directory: " + CldrUtility.SEED_DIRECTORY);
        }
        File dirs[] = { mainDir, seedDir };
        return SimpleFactory.make(dirs, ".*", DraftStatus.approved);
    }

    private static void testExtraPaths() {
        Factory cldrFactory = Factory.make(CldrUtility.MAIN_DIRECTORY, ".*", DraftStatus.approved);
        for (String locale : new String[] { "en", "ar", "ja" }) {
            CLDRFile cldrFile = cldrFactory.make(locale, true);
            Set<String> s = (Set<String>) cldrFile.getExtraPaths(new TreeSet<String>());
            System.out.println("Extras for " + locale);
            for (String path : s) {
                System.out.println(path + " => " + cldrFile.getStringValue(path));
            }
            System.out.println("Already in " + locale);
            for (Iterator<String> it = cldrFile.iterator(Pattern.compile(".*\\[@count=.*").matcher("")); it.hasNext();) {
                String path = it.next();
                System.out.println(path + " => " + cldrFile.getStringValue(path));
            }
        }
    }

    private static void testDraftFilter() {
        Factory cldrFactory = Factory.make(CldrUtility.MAIN_DIRECTORY, ".*", DraftStatus.approved);
        checkLocale(cldrFactory.make("root", true));
        checkLocale(cldrFactory.make("ee", true));
    }

    public static void checkLocale(CLDRFile cldr) {
        Matcher m = Pattern.compile("gregorian.*eras").matcher("");
        for (Iterator<String> it = cldr.iterator("", new UTF16.StringComparator()); it.hasNext();) {
            String path = it.next();
            if (m.reset(path).find() && !path.contains("alias")) {
                System.out.println(cldr.getLocaleID() + "\t" + cldr.getStringValue(path) + "\t"
                    + cldr.getFullXPath(path));
            }
            if (path == null) {
                throw new IllegalArgumentException("Null path");
            }
            String fullPath = cldr.getFullXPath(path);
            if (fullPath.contains("@draft")) {
                throw new IllegalArgumentException("File can't contain draft elements");
            }
        }
    }

    public static void TestTimeZonePath() {
        Factory cldrFactory = Factory.make(CldrUtility.MAIN_DIRECTORY, ".*");
        String tz = "Pacific/Midway";
        CLDRFile cldrFile = cldrFactory.make("lv", true);
        String retVal = cldrFile.getStringValue(
            "//ldml/dates/timeZoneNames/zone[@type=\"" + tz + "\"]/exemplarCity"
            , true).trim();
        System.out.println(retVal);
    }

    private static void simpleTest() {
        double deltaTime = System.currentTimeMillis();
        Factory cldrFactory = Factory.make(CldrUtility.MAIN_DIRECTORY, ".*");
        CLDRFile english = cldrFactory.make("en", true);
        deltaTime = System.currentTimeMillis() - deltaTime;
        System.out.println("Creation: Elapsed: " + deltaTime / 1000.0 + " seconds");

        deltaTime = System.currentTimeMillis();
        english.getStringValue("//ldml");
        deltaTime = System.currentTimeMillis() - deltaTime;
        System.out.println("Creation: Elapsed: " + deltaTime / 1000.0 + " seconds");

        deltaTime = System.currentTimeMillis();
        english.getStringValue("//ldml");
        deltaTime = System.currentTimeMillis() - deltaTime;
        System.out.println("Caching: Elapsed: " + deltaTime / 1000.0 + " seconds");

        deltaTime = System.currentTimeMillis();
        for (int j = 0; j < 2; ++j) {
            for (Iterator<String> it = english.iterator(); it.hasNext();) {
                String dpath = it.next();
                String value = english.getStringValue(dpath);
                Set<String> paths = english.getPathsWithValue(value, null, null, null);
                if (!paths.contains(dpath)) {
                    throw new IllegalArgumentException(paths + " don't contain <" + value + ">.");
                }
                if (false && paths.size() > 1) {
                    System.out.println("Value: " + value + "\t\tPaths: " + paths);
                }
            }
        }
        deltaTime = System.currentTimeMillis() - deltaTime;
        System.out.println("Elapsed: " + deltaTime / 1000.0 + " seconds");
    }

    private static void resolutionTest() {
        Factory cldrFactory = Factory.make(CldrUtility.MAIN_DIRECTORY, ".*");
        CLDRFile german = cldrFactory.make("de", true);
        // Test direct lookup.
        String xpath = "//ldml/localeDisplayNames/localeDisplayPattern/localeSeparator";
        String id = german.getSourceLocaleID(xpath, null);
        if (!id.equals("de")) {
            throw new RuntimeException("Expected de but was " + id + " for " + xpath);
        }

        // Test aliasing.
        xpath = "//ldml/dates/calendars/calendar[@type=\"islamic-civil\"]/dateTimeFormats/availableFormats/dateFormatItem[@id=\"yyyyMEd\"]";
        id = german.getSourceLocaleID(xpath, null);
        if (!id.equals("de")) {
            throw new RuntimeException("Expected de but was " + id + " for " + xpath);
        }

        // Test lookup that falls to root.
        xpath = "//ldml/dates/calendars/calendar[@type=\"coptic\"]/months/monthContext[@type=\"stand-alone\"]/monthWidth[@type=\"narrow\"]/month[@type=\"5\"]";
        id = german.getSourceLocaleID(xpath, null);
        if (!id.equals("root")) {
            throw new RuntimeException("Expected root but was " + id + " for " + xpath);
        }
    }
}