package org.unicode.cldr.json;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.unicode.cldr.draft.FileUtilities;
import org.unicode.cldr.draft.ScriptMetadata;
import org.unicode.cldr.draft.ScriptMetadata.Info;
import org.unicode.cldr.tool.Option.Options;
import org.unicode.cldr.util.CLDRConfig;
import org.unicode.cldr.util.CLDRFile;
import org.unicode.cldr.util.CLDRFile.DraftStatus;
import org.unicode.cldr.util.CLDRPaths;
import org.unicode.cldr.util.CLDRTool;
import org.unicode.cldr.util.CldrUtility;
import org.unicode.cldr.util.CoverageInfo;
import org.unicode.cldr.util.DtdData;
import org.unicode.cldr.util.DtdType;
import org.unicode.cldr.util.Factory;
import org.unicode.cldr.util.FileProcessor;
import org.unicode.cldr.util.Level;
import org.unicode.cldr.util.LocaleIDParser;
import org.unicode.cldr.util.PatternCache;
import org.unicode.cldr.util.StandardCodes;
import org.unicode.cldr.util.SupplementalDataInfo;
import org.unicode.cldr.util.XPathParts;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.stream.JsonWriter;
import com.ibm.icu.dev.util.CollectionUtilities;

/**
 * Utility methods to extract data from CLDR repository and export it in JSON
 * format.
 *
 * @author shanjian / emmons
 */
@CLDRTool(alias = "ldml2json", description = "Convert CLDR data to JSON")
public class Ldml2JsonConverter {
    private static boolean DEBUG = false;

    private enum RunType {
        main, supplemental, segments, rbnf
    };

    private static final StandardCodes sc = StandardCodes.make();
    private Set<String> defaultContentLocales = SupplementalDataInfo.getInstance().getDefaultContentLocales();
    private Set<String> skippedDefaultContentLocales = new TreeSet<String>();

    private class availableLocales {
        Set<String> modern = new TreeSet<String>();
        Set<String> full = new TreeSet<String>();
    }

    private availableLocales avl = new availableLocales();
    private Gson gson = new GsonBuilder().setPrettyPrinting().create();
    private static final Options options = new Options(
        "Usage: LDML2JsonConverter [OPTIONS] [FILES]\n" +
            "This program converts CLDR data to the JSON format.\n" +
            "Please refer to the following options. \n" +
        "\texample: org.unicode.cldr.json.Ldml2JsonConverter -c xxx -d yyy")
    .add("commondir", 'c', ".*", CLDRPaths.COMMON_DIRECTORY,
        "Common directory for CLDR files, defaults to CldrUtility.COMMON_DIRECTORY")
        .add("destdir", 'd', ".*", CLDRPaths.GEN_DIRECTORY,
            "Destination directory for output files, defaults to CldrUtility.GEN_DIRECTORY")
            .add("match", 'm', ".*", ".*",
                "Regular expression to define only specific locales or files to be generated")
                .add("type", 't', "(main|supplemental|segments|rbnf)", "main",
                    "Type of CLDR data being generated, main, supplemental, or segments.")
                    .add("resolved", 'r', "(true|false)", "false",
                        "Whether the output JSON for the main directory should be based on resolved or unresolved data")
                        .add("draftstatus", 's', "(approved|contributed|provisional|unconfirmed)", "unconfirmed",
                            "The minimum draft status of the output data")
                            .add("coverage", 'l', "(minimal|basic|moderate|modern|comprehensive|optional)", "optional",
                                "The maximum coverage level of the output data")
                                .add("fullnumbers", 'n', "(true|false)", "false",
                                    "Whether the output JSON should output data for all numbering systems, even those not used in the locale")
                                    .add("other", 'o', "(true|false)", "false",
                                        "Whether to write out the 'other' section, which contains any unmatched paths")
                                        .add("packages", 'p', "(true|false)", "false",
                                            "Whether to group data files into installable packages")
                                            .add("identity", 'i', "(true|false)", "true",
                                                "Whether to copy the identity info into all sections containing data")
                                                .add("konfig", 'k', ".*", null, "LDML to JSON configuration file");

    public static void main(String[] args) throws Exception {
        options.parse(args, true);

        Ldml2JsonConverter l2jc = new Ldml2JsonConverter(
            options.get("commondir").getValue(),
            options.get("destdir").getValue(),
            options.get("type").getValue(),
            Boolean.parseBoolean(options.get("fullnumbers").getValue()),
            Boolean.parseBoolean(options.get("resolved").getValue()),
            options.get("coverage").getValue(),
            options.get("match").getValue(),
            Boolean.parseBoolean(options.get("packages").getValue()),
            options.get("konfig").getValue());

        long start = System.currentTimeMillis();
        DraftStatus status = DraftStatus.valueOf(options.get("draftstatus").getValue());
        l2jc.processDirectory(options.get("type").getValue(), status);
        long end = System.currentTimeMillis();
        System.out.println("Finished in " + (end - start) + " ms");
    }

    // The CLDR file directory where those official XML files will be found.
    private String cldrCommonDir;
    // Where the generated JSON files will be stored.
    private String outputDir;
    // Whether data in main should output all numbering systems, even those not in use in the locale.
    private boolean fullNumbers;
    // Whether data in main should be resolved for output.
    private boolean resolve;
    // Used to match specific locales for output
    private String match;
    // Used to filter based on coverage
    private int coverageValue;
    // Whether we should write output files into installable packages
    private boolean writePackages;
    // Type of run for this converter: main, supplemental, or segments
    private RunType type;

    private class JSONSection implements Comparable<JSONSection> {
        public String section;
        public Matcher matcher;
        public String packageName;

        public int compareTo(JSONSection other) {
            return section.compareTo(other.section);
        }

    }

    private Map<JSONSection, List<CldrItem>> sectionItems = new TreeMap<JSONSection, List<CldrItem>>();

    private Map<String, String> dependencies;
    private List<JSONSection> sections;
    private Set<String> packages;

    public Ldml2JsonConverter(String cldrDir, String outputDir, String runType, boolean fullNumbers, boolean resolve, String coverage, String match,
        boolean writePackages, String configFile) {
        this.cldrCommonDir = cldrDir;
        this.outputDir = outputDir;
        this.type = RunType.valueOf(runType);
        this.fullNumbers = fullNumbers;
        this.resolve = resolve;
        this.match = match;
        this.writePackages = writePackages;
        this.coverageValue = Level.get(coverage).getLevel();

        sections = new ArrayList<JSONSection>();
        packages = new TreeSet<String>();
        dependencies = new HashMap<String, String>();

        FileProcessor myReader = new FileProcessor() {
            @Override
            protected boolean handleLine(int lineCount, String line) {
                String[] lineParts = line.trim().split("\\s*;\\s*");
                String key, value, section = null, path = null, packageName = null, dependency = null;
                boolean hasSection = false;
                boolean hasPath = false;
                boolean hasPackage = false;
                boolean hasDependency = false;
                for (String linePart : lineParts) {
                    int pos = linePart.indexOf('=');
                    if (pos < 0) {
                        throw new IllegalArgumentException();
                    }
                    key = linePart.substring(0, pos);
                    value = linePart.substring(pos + 1);
                    if (key.equals("section")) {
                        hasSection = true;
                        section = value;
                    } else if (key.equals("path")) {
                        hasPath = true;
                        path = value;
                    } else if (key.equals("package")) {
                        hasPackage = true;
                        packageName = value;
                    } else if (key.equals("dependency")) {
                        hasDependency = true;
                        dependency = value;
                    }
                }
                if (hasSection && hasPath) {
                    JSONSection j = new JSONSection();
                    j.section = section;
                    j.matcher = PatternCache.get(path).matcher("");
                    if (hasPackage) {
                        j.packageName = packageName;
                    }
                    sections.add(j);
                }
                if (hasDependency && hasPackage) {
                    dependencies.put(packageName, dependency);
                }
                return true;
            }
        };

        if (configFile != null) {
            myReader.process(configFile);
        } else {
            switch (type) {
            case main:
                myReader.process(Ldml2JsonConverter.class, "JSON_config.txt");
                break;
            case supplemental:
                myReader.process(Ldml2JsonConverter.class, "JSON_config_supplemental.txt");
                break;
            case segments:
                myReader.process(Ldml2JsonConverter.class, "JSON_config_segments.txt");
                break;
            case rbnf:
                myReader.process(Ldml2JsonConverter.class, "JSON_config_rbnf.txt");
                break;

            }
        }

        // Add a section at the end of the list that will match anything not already matched.
        JSONSection j = new JSONSection();
        j.section = "other";
        j.matcher = PatternCache.get(".*").matcher("");
        sections.add(j);

    }

    /**
     * Transform the path by applying PATH_TRANSFORMATIONS rules.
     *
     * @param pathStr
     *            The path string being transformed.
     * @return The transformed path.
     */
    private String transformPath(String pathStr, String pathPrefix) {
        String result = pathStr;

        if (DEBUG) {
            System.out.println(" IN pathStr : " + result);
        }
        Matcher m;
        for (int i = 0; i < LdmlConvertRules.PATH_TRANSFORMATIONS.length; i++) {
            m = LdmlConvertRules.PATH_TRANSFORMATIONS[i].pattern.matcher(pathStr);
            if (m.matches()) {
                if (DEBUG) {
                    System.out.println(LdmlConvertRules.PATH_TRANSFORMATIONS[i].pattern);
                }
                result = m.replaceFirst(LdmlConvertRules.PATH_TRANSFORMATIONS[i].replacement);
                break;
            }
        }
        result = result.replaceFirst("/ldml/", pathPrefix);
        result = result.replaceFirst("/supplementalData/", pathPrefix);

        if (result.contains("languages") ||
            result.contains("languageAlias") ||
            result.contains("languageMatches") ||
            result.contains("likelySubtags") ||
            result.contains("parentLocale") ||
            result.contains("locales=")) {
            result = result.replaceAll("_", "-");
        }
        if (DEBUG) {
            System.out.println("OUT pathStr : " + result);
        }

        if (DEBUG) {
            System.out.println("result: " +result);
        }
        return result;
    }

    private void mapPathsToSections(CLDRFile file, String pathPrefix, SupplementalDataInfo sdi)
        throws IOException, ParseException {

        String locID = file.getLocaleID();
        Matcher noNumberingSystemMatcher = LdmlConvertRules.NO_NUMBERING_SYSTEM_PATTERN.matcher("");
        Matcher numberingSystemMatcher = LdmlConvertRules.NUMBERING_SYSTEM_PATTERN.matcher("");
        Matcher rootIdentityMatcher = LdmlConvertRules.ROOT_IDENTITY_PATTERN.matcher("");
        Set<String> activeNumberingSystems = new TreeSet<String>();
        activeNumberingSystems.add("latn"); // Always include latin script numbers
        for (String np : LdmlConvertRules.ACTIVE_NUMBERING_SYSTEM_XPATHS) {
            String ns = file.getWinningValue(np);
            if (ns != null && ns.length() > 0) {
                activeNumberingSystems.add(ns);
            }
        }
        DtdType fileDtdType;
        if (CLDRFile.isSupplementalName(locID)) {
            fileDtdType = DtdType.supplementalData;
        } else {
            fileDtdType = DtdType.ldml;
        }
        CoverageInfo covInfo = CLDRConfig.getInstance().getCoverageInfo();
        for (Iterator<String> it = file.iterator("", DtdData.getInstance(fileDtdType).getDtdComparator(null)); it.hasNext();) {
            int cv = Level.UNDETERMINED.getLevel();
            String path = it.next();
            String fullPath = file.getFullXPath(path);
            String value = file.getWinningValue(path);
            if (path.startsWith("//ldml/localeDisplayNames/languages") &&
                file.getSourceLocaleID(path, null).equals("code-fallback")) {
                value = file.getConstructedBaileyValue(path, null, null);
            }

            if (fullPath == null) {
                fullPath = path;
            }

            if (!CLDRFile.isSupplementalName(locID) && path.startsWith("//ldml/") && !path.contains("/identity")) {
                cv = covInfo.getCoverageValue(path, locID);
            }
            if (cv > coverageValue) {
                continue;
            }
            // Discard root identity element unless the locale is root
            rootIdentityMatcher.reset(fullPath);
            if (rootIdentityMatcher.matches() && !"root".equals(locID)) {
                continue;
            }

            // automatically filter out number symbols and formats without a numbering system
            noNumberingSystemMatcher.reset(fullPath);
            if (noNumberingSystemMatcher.matches()) {
                continue;
            }

            // Filter out non-active numbering systems data unless fullNumbers is specified.
            numberingSystemMatcher.reset(fullPath);
            if (numberingSystemMatcher.matches() && !fullNumbers) {
                XPathParts xpp = new XPathParts();
                xpp.set(fullPath);
                String currentNS = xpp.getAttributeValue(2, "numberSystem");
                if (currentNS != null && !activeNumberingSystems.contains(currentNS)) {
                    continue;
                }
            }

            // Handle the no inheritance marker.
            if (resolve && CldrUtility.NO_INHERITANCE_MARKER.equals(value)) {
                continue;
            }

            String transformedPath = transformPath(path, pathPrefix);
            String transformedFullPath = transformPath(fullPath, pathPrefix);

            for (JSONSection js : sections) {
                js.matcher.reset(transformedPath);
                if (js.matcher.matches()) {
                    CldrItem item = new CldrItem(transformedPath, transformedFullPath, path, fullPath, value);

                    List<CldrItem> cldrItems = sectionItems.get(js);
                    if (cldrItems == null) {
                        cldrItems = new ArrayList<CldrItem>();
                    }
                    cldrItems.add(item);
                    sectionItems.put(js, cldrItems);
                    break;
                }
            }
        }

        Matcher versionInfoMatcher = PatternCache.get(".*/(identity|version).*").matcher("");
        // Automatically copy the version info to any sections that had real data in them.
        JSONSection otherSection = sections.get(sections.size() - 1);
        List<CldrItem> others = sectionItems.get(otherSection);
        if (others == null) {
            return;
        }
        List<CldrItem> otherSectionItems = new ArrayList<CldrItem>(others);
        int addedItemCount = 0;
        boolean copyIdentityInfo = Boolean.parseBoolean(options.get("identity").getValue());

        for (CldrItem item : otherSectionItems) {
            String thisPath = item.getPath();
            versionInfoMatcher.reset(thisPath);
            if (versionInfoMatcher.matches()) {
                for (JSONSection js : sections) {
                    if (sectionItems.get(js) != null && !js.section.equals("other") && copyIdentityInfo) {
                        List<CldrItem> hit = sectionItems.get(js);
                        hit.add(addedItemCount, item);
                        sectionItems.put(js, hit);
                    }
                    if (js.section.equals("other")) {
                        List<CldrItem> hit = sectionItems.get(js);
                        hit.remove(item);
                        sectionItems.put(js, hit);
                    }
                }
                addedItemCount++;
            }
        }
    }

    /**
     * Convert CLDR's XML data to JSON format.
     *
     * @param file
     *            CLDRFile object.
     * @param outFilename
     *            The file name used to save JSON data.
     * @throws IOException
     * @throws ParseException
     */
    private void convertCldrItems(String dirName, String filename, String pathPrefix)
        throws IOException, ParseException {
        // zone and timezone items are queued for sorting first before they are
        // processed.

        for (JSONSection js : sections) {
            String outFilename;
            if(type == RunType.rbnf){
                outFilename = filename.replaceAll("_", "-") + ".json";
            } else {
                outFilename = js.section + ".json";
            }
            String tier = "";
            boolean writeOther = Boolean.parseBoolean(options.get("other").getValue());
            if (js.section.equals("other") && !writeOther) {
                continue;
            } else {
                StringBuilder outputDirname = new StringBuilder(outputDir);
                if (writePackages) {
                    if (type != RunType.supplemental && type != RunType.rbnf) {
                        LocaleIDParser lp = new LocaleIDParser();
                        lp.set(filename);
                        if (defaultContentLocales.contains(filename) &&
                            lp.getRegion().length() > 0) {
                            if (type == RunType.main) {
                                skippedDefaultContentLocales.add(filename.replaceAll("_", "-"));
                            }
                            continue;
                        }
                        Level localeCoverageLevel = sc.getLocaleCoverageLevel("Cldr", filename);
                        if (localeCoverageLevel == Level.MODERN || filename.equals("root")) {
                            tier = "-modern";
                            if (type == RunType.main) {
                                avl.modern.add(filename.replaceAll("_", "-"));
                            }
                        } else {
                            tier = "-full";
                        }
                        if (type == RunType.main) {
                            avl.full.add(filename.replaceAll("_", "-"));
                        }
                    } else if(type == RunType.rbnf){
                        js.packageName = "rbnf";
                        tier = "";
                    }
                    if (js.packageName != null) {
                        String packageName = "cldr-" + js.packageName + tier;                        
                        outputDirname.append("/" + packageName);
                        packages.add(packageName);
                    }
                    outputDirname.append("/" + dirName + "/");
                    if (type != RunType.supplemental && type != RunType.rbnf) {
                        outputDirname.append(filename.replaceAll("_", "-"));
                    }
                    if (DEBUG) {
                        System.out.println("outDir: " + outputDirname);
                        System.out.println("pack: " + js.packageName);
                        System.out.println("dir: " + dirName);
                    }
                }

                File dir = new File(outputDirname.toString());
                if (!dir.exists()) {
                    dir.mkdirs();
                }

                List<String> outputDirs = new ArrayList<String>();
                outputDirs.add(outputDirname.toString());
                if (writePackages && type == RunType.main && tier.equals("-modern")) {
                    outputDirs.add(outputDirname.toString().replaceFirst("-modern", "-full"));
                }

                for (String outputDir : outputDirs) {
                    List<CldrItem> theItems = sectionItems.get(js);
                    if (theItems == null || theItems.size() == 0) {
                        continue;
                    }
                    PrintWriter outf = FileUtilities.openUTF8Writer(outputDir, outFilename);
                    JsonWriter out = new JsonWriter(outf);
                    out.setIndent("  ");

                    ArrayList<CldrItem> sortingItems = new ArrayList<CldrItem>();
                    ArrayList<CldrItem> arrayItems = new ArrayList<CldrItem>();

                    ArrayList<CldrNode> nodesForLastItem = new ArrayList<CldrNode>();
                    String lastLeadingArrayItemPath = null;
                    String leadingArrayItemPath = "";
                    int valueCount = 0;
                    String previousIdentityPath = null;
                    for (CldrItem item : theItems) {

                        if(type == RunType.rbnf){
                            item.setValue(item.getValue().replace('→', '>'));
                            item.setValue(item.getValue().replace('←', '<'));
                            if(item.getFullPath().contains("@value")){
                                int indexStart = item.getFullPath().indexOf("@value") + 8;
                                int indexEnd = item.getFullPath().indexOf("]", indexStart) - 1;
                                if(indexStart >= 0 && indexEnd >= 0 && indexEnd > indexStart){
                                    String sub = item.getFullPath().substring(indexStart, indexEnd);
                                    /* System.out.println("sub: " + sub);
                                    System.out.println("full: " + item.getFullPath());
                                    System.out.println("val: " + item.getValue());*/
                                    item.setFullPath(item.getFullPath().replace(sub, item.getValue()));
                                    item.setFullPath(item.getFullPath().replaceAll("@value", "@" + sub));
                                    //System.out.println("modifyfull: " + item.getFullPath());
                                    item.setValue("");
                                }
                            }

                        }
                     // ADJUST ACCESS=PRIVATE/PUBLIC BASED ON ICU RULE -- START
                        if(type == RunType.rbnf){
                            String fullpath = item.getFullPath();
                            if(fullpath.contains("/ruleset")){
                                int ruleStartIndex = fullpath.indexOf("/ruleset[");
                                String checkString = fullpath.substring(ruleStartIndex);
                                
                                int ruleEndIndex = 0;
                                if(checkString.contains("/")){
                                    ruleEndIndex = fullpath.indexOf("/", ruleStartIndex+1);
                                }
                                if(ruleEndIndex > ruleStartIndex){
                                    String oldRulePath = fullpath.substring(ruleStartIndex, ruleEndIndex);
                                    
                                    String newRulePath = oldRulePath;
                                    if(newRulePath.contains("@type")){
                                        int typeIndexStart = newRulePath.indexOf("\"", newRulePath.indexOf("@type"));
                                        int typeIndexEnd = newRulePath.indexOf("\"",typeIndexStart+1);
                                        String type = newRulePath.substring(typeIndexStart + 1, typeIndexEnd);
                                        
                                        String newType = "";
                                        if(newRulePath.contains("@access"))
                                        {
                                            newType = "%%" + type;
                                        }
                                        else{
                                            newType = "%" + type;                                            
                                        }                                        
                                        newRulePath = newRulePath.replace(type, newType);
                                        item.setPath(item.getPath().replace(type, newType));                                        
                                    }
                                    fullpath = fullpath.replace(oldRulePath, newRulePath);                                    
                                    item.setFullPath(fullpath);
                                    
                                }
                            }
                        }
                        // ADJUST ACCESS=PRIVATE/PUBLIC BASED ON ICU RULE -- END
                        
                        
                        
                        // items in the identity section of a file should only ever contain the lowest level, even if using
                        // resolving source, so if we have duplicates ( caused by attributes used as a value ) then suppress
                        // them here.
                        if (item.getPath().contains("/identity/")) {
                            XPathParts xpp = new XPathParts();
                            String[] parts = item.getPath().split("\\[");
                            if (parts[0].equals(previousIdentityPath)) {
                                continue;
                            } else {
                                xpp.set(item.getPath());
                                String territory = xpp.findAttributeValue("territory", "type");
                                LocaleIDParser lp = new LocaleIDParser().set(filename);
                                if (territory != null && territory.length() > 0 && !territory.equals(lp.getRegion())) {
                                    continue;
                                }
                                previousIdentityPath = parts[0];
                            }
                        }

                        // some items need to be split to multiple item before processing. None
                        // of those items need to be sorted.
                        CldrItem[] items = item.split();
                        if (items == null) {
                            items = new CldrItem[1];
                            items[0] = item;
                        }
                        valueCount += items.length;

                        for (CldrItem newItem : items) {
                            // alias will be dropped in conversion, don't count it.
                            if (newItem.isAliasItem()) {
                                valueCount--;
                            }

                            // Items like zone items need to be sorted first before write them out.
                            if (newItem.needsSort()) {
                                resolveArrayItems(out, nodesForLastItem, arrayItems);
                                sortingItems.add(newItem);
                            } else {
                                Matcher matcher = LdmlConvertRules.ARRAY_ITEM_PATTERN.matcher(
                                    newItem.getPath());
                                if (matcher.matches()) {
                                    resolveSortingItems(out, nodesForLastItem, sortingItems);
                                    leadingArrayItemPath = matcher.group(1);
                                    if (lastLeadingArrayItemPath != null &&
                                        !lastLeadingArrayItemPath.equals(leadingArrayItemPath)) {
                                        resolveArrayItems(out, nodesForLastItem, arrayItems);
                                    }
                                    lastLeadingArrayItemPath = leadingArrayItemPath;
                                    arrayItems.add(newItem);
                                } else {
                                    resolveSortingItems(out, nodesForLastItem, sortingItems);
                                    resolveArrayItems(out, nodesForLastItem, arrayItems);
                                    outputCldrItem(out, nodesForLastItem, newItem);
                                    lastLeadingArrayItemPath = "";
                                }
                            }
                        }
                    }

                    resolveSortingItems(out, nodesForLastItem, sortingItems);
                    resolveArrayItems(out, nodesForLastItem, arrayItems);
                    System.out.println(String.format("  %s = %d values", outFilename, valueCount));
                    closeNodes(out, nodesForLastItem.size() - 2, 0);
                    outf.println();
                    out.close();
                }
            }
        }
    }

    /**
     * Creates the packaging files ( i.e. package.json ) for a particular package
     *
     * @param packageName
     *            The name of the installable package
     */
    public void writePackagingFiles(String outputDir, String packageName) throws IOException {
        writePackageJson(outputDir, packageName);
        writeBowerJson(outputDir, packageName);
    }

    public void writeBasicInfo(JsonObject obj, String packageName, boolean isNPM) {

        obj.addProperty("name", packageName);
        String versionString = CLDRFile.GEN_VERSION;
        while (versionString.split("\\.").length < 3) {
            versionString = versionString + ".0";
        }
        obj.addProperty("version", versionString);

        String[] packageNameParts = packageName.split("-");
        String dependency = dependencies.get(packageNameParts[1]);
        if (dependency != null) {
            String[] dependentPackageNames = new String[1];
            String tier = packageNameParts[packageNameParts.length - 1];
            if (dependency.equals("core")) {
                dependentPackageNames[0] = "cldr-core";
            } else {
                dependentPackageNames[0] = "cldr-" + dependency + "-" + tier;
            }

            JsonObject dependencies = new JsonObject();
            for (String dependentPackageName : dependentPackageNames) {
                if (dependentPackageName != null) {
                    dependencies.addProperty(dependentPackageName, versionString);
                }
            }
            obj.add(isNPM ? "peerDependencies" : "dependencies", dependencies);
        }
    }

    public void writePackageJson(String outputDir, String packageName) throws IOException {
        PrintWriter outf = FileUtilities.openUTF8Writer(outputDir + "/" + packageName, "package.json");
        System.out.println("Creating packaging file => " + outputDir + File.separator + packageName + File.separator + "package.json");
        JsonObject obj = new JsonObject();
        writeBasicInfo(obj, packageName, true);

        JsonArray licenses = new JsonArray();
        JsonArray maintainers = new JsonArray();
        JsonObject UnicodeLicense = new JsonObject();
        JsonObject primaryMaintainer = new JsonObject();

        obj.addProperty("homepage", "http://cldr.unicode.org");
        obj.addProperty("author", "The Unicode Consortium");

        primaryMaintainer.addProperty("name", "John Emmons");
        primaryMaintainer.addProperty("email", "emmo@us.ibm.com");
        primaryMaintainer.addProperty("url", "https://github.com/JCEmmons");
        maintainers.add(primaryMaintainer);
        obj.add("maintainers", maintainers);

        JsonObject repository = new JsonObject();
        repository.addProperty("type", "git");
        repository.addProperty("url", "git://github.com/unicode-cldr/" + packageName + ".git");
        obj.add("repository", repository);

        UnicodeLicense.addProperty("type", "Unicode-TOU");
        UnicodeLicense.addProperty("url", "http://www.unicode.org/copyright.html");
        licenses.add(UnicodeLicense);
        obj.add("licenses", licenses);

        obj.addProperty("bugs", "http://unicode.org/cldr/trac/newticket");

        outf.println(gson.toJson(obj));
        outf.close();
    }

    public void writeBowerJson(String outputDir, String packageName) throws IOException {
        PrintWriter outf = FileUtilities.openUTF8Writer(outputDir + "/" + packageName, "bower.json");
        System.out.println("Creating packaging file => " + outputDir + File.separator + packageName + File.separator + "bower.json");
        JsonObject obj = new JsonObject();
        writeBasicInfo(obj, packageName, false);
        if (type == RunType.supplemental) {
            JsonArray mainPaths = new JsonArray();
            mainPaths.add(new JsonPrimitive("availableLocales.json"));
            mainPaths.add(new JsonPrimitive("defaultContent.json"));
            mainPaths.add(new JsonPrimitive("scriptMetadata.json"));
            mainPaths.add(new JsonPrimitive(type.toString() + "/*.json"));
            obj.add("main", mainPaths);
        } else if (type == RunType.rbnf) {
            obj.addProperty("main", type.toString() + "/*.json");
        } else {
            obj.addProperty("main", type.toString() + "/**/*.json");
        }

        JsonArray ignorePaths = new JsonArray();
        ignorePaths.add(new JsonPrimitive(".gitattributes"));
        ignorePaths.add(new JsonPrimitive("README.md"));
        obj.add("ignore", ignorePaths);

        outf.println(gson.toJson(obj));
        outf.close();
    }

    public void writeDefaultContent(String outputDir) throws IOException {
        PrintWriter outf = FileUtilities.openUTF8Writer(outputDir + "/cldr-core", "defaultContent.json");
        System.out.println("Creating packaging file => " + outputDir + "cldr-core" + File.separator + "defaultContent.json");
        JsonObject obj = new JsonObject();
        obj.add("defaultContent", gson.toJsonTree(skippedDefaultContentLocales));
        outf.println(gson.toJson(obj));
        outf.close();
    }

    public void writeAvailableLocales(String outputDir) throws IOException {
        PrintWriter outf = FileUtilities.openUTF8Writer(outputDir + "/cldr-core", "availableLocales.json");
        System.out.println("Creating packaging file => " + outputDir + "cldr-core" + File.separator + "availableLocales.json");
        JsonObject obj = new JsonObject();
        obj.add("availableLocales", gson.toJsonTree(avl));
        outf.println(gson.toJson(obj));
        outf.close();
    }

    public void writeScriptMetadata(String outputDir) throws IOException {
        PrintWriter outf = FileUtilities.openUTF8Writer(outputDir + "/cldr-core", "scriptMetadata.json");
        System.out.println("Creating script metadata file => " + outputDir + File.separator +"cldr-core" + File.separator + "scriptMetadata.json");
        Map<String,Info> scriptInfo = new TreeMap<String,Info>();
        for (String script : ScriptMetadata.getScripts()) {
            Info i = ScriptMetadata.getInfo(script);
            scriptInfo.put(script,i);
        }
        if (ScriptMetadata.errors.size() > 0) {
            System.err.println(CollectionUtilities.join(ScriptMetadata.errors, "\n\t"));
            //throw new IllegalArgumentException();
        }

        JsonObject obj = new JsonObject();
        obj.add("scriptMetadata", gson.toJsonTree(scriptInfo));
        outf.println(gson.toJson(obj));
        outf.close();
    }

    /**
     * Process the pending sorting items.
     *
     * @param out
     *            The ArrayList to hold all output lines.
     * @param nodesForLastItem
     *            All the nodes from last item.
     * @param sortingItems
     *            The item list that should be sorted before output.
     * @throws IOException
     * @throws ParseException
     */
    private void resolveSortingItems(JsonWriter out,
        ArrayList<CldrNode> nodesForLastItem,
        ArrayList<CldrItem> sortingItems)
            throws IOException, ParseException {
        ArrayList<CldrItem> arrayItems = new ArrayList<CldrItem>();
        String lastLeadingArrayItemPath = null;

        if (!sortingItems.isEmpty()) {
            Collections.sort(sortingItems);
            for (CldrItem item : sortingItems) {
                Matcher matcher = LdmlConvertRules.ARRAY_ITEM_PATTERN.matcher(
                    item.getPath());
                if (matcher.matches()) {
                    String leadingArrayItemPath = matcher.group(1);
                    if (lastLeadingArrayItemPath != null &&
                        !lastLeadingArrayItemPath.equals(leadingArrayItemPath)) {
                        resolveArrayItems(out, nodesForLastItem, arrayItems);
                    }
                    lastLeadingArrayItemPath = leadingArrayItemPath;
                    arrayItems.add(item);
                } else {
                    outputCldrItem(out, nodesForLastItem, item);
                }
            }
            sortingItems.clear();
            resolveArrayItems(out, nodesForLastItem, arrayItems);
        }
    }

    /**
     * Process the pending array items.
     *
     * @param out
     *            The ArrayList to hold all output lines.
     * @param nodesForLastItem
     *            All the nodes from last item.
     * @param arrayItems
     *            The item list that should be output as array.
     * @throws IOException
     * @throws ParseException
     */
    private void resolveArrayItems(JsonWriter out,
        ArrayList<CldrNode> nodesForLastItem,
        ArrayList<CldrItem> arrayItems)
            throws IOException, ParseException {
        boolean rbnfFlag = false;
        if (!arrayItems.isEmpty()) {
            CldrItem firstItem = arrayItems.get(0);
            if (firstItem.needsSort()) {
                Collections.sort(arrayItems);
                firstItem = arrayItems.get(0);
            }         


            int arrayLevel = getArrayIndentLevel(firstItem);

            outputStartArray(out, nodesForLastItem, firstItem, arrayLevel);

            // Previous statement closed for first element, trim nodesForLastItem
            // so that it will not happen again inside.
            int len = nodesForLastItem.size();
            while (len > arrayLevel) {
                nodesForLastItem.remove(len - 1);
                len--;
            }
            if(arrayItems.get(0).getFullPath().contains("rbnfrule")){
                rbnfFlag = true;
                out.beginObject();
            }
            for (CldrItem insideItem : arrayItems) {

                outputArrayItem(out, insideItem, nodesForLastItem, arrayLevel );

            }
            if(rbnfFlag){
                out.endObject();
            }

            arrayItems.clear();

            int lastLevel = nodesForLastItem.size() - 1;
            closeNodes(out, lastLevel, arrayLevel);
            if(!rbnfFlag){
                out.endArray();
            }
            for (int i = arrayLevel - 1; i < lastLevel; i++) {
                nodesForLastItem.remove(i);
            }
        }
    }

    /**
     * Find the indent level on which array should be inserted.
     *
     * @param item
     *            The CldrItem being examined.
     * @return The array indent level.
     * @throws ParseException
     */
    private int getArrayIndentLevel(CldrItem item) throws ParseException {
        Matcher matcher = LdmlConvertRules.ARRAY_ITEM_PATTERN.matcher(
            item.getPath());
        if (!matcher.matches()) {
            System.out.println("No match found for " + item.getPath() + ", this shouldn't happen.");
            return 0;
        }

        String leadingPath = matcher.group(1);
        CldrItem fakeItem = new CldrItem(leadingPath, leadingPath, leadingPath, leadingPath, "");
        return fakeItem.getNodesInPath().size() - 1;
    }

    /**
     * Write the start of an array.
     *
     * @param out
     *            The ArrayList to hold all output lines.
     * @param nodesForLastItem
     *            Nodes in path for last CldrItem.
     * @param item
     *            The CldrItem to be processed.
     * @param arrayLevel
     *            The level on which array is laid out.
     * @throws IOException
     * @throws ParseException
     */
    private void outputStartArray(JsonWriter out,
        ArrayList<CldrNode> nodesForLastItem, CldrItem item, int arrayLevel)
            throws IOException, ParseException {

        ArrayList<CldrNode> nodesInPath = item.getNodesInPath();

        int i = findFirstDiffNodeIndex(nodesForLastItem, nodesInPath);

        // close previous nodes
        closeNodes(out, nodesForLastItem.size() - 2, i);

        for (; i < arrayLevel - 1; i++) {
            startNonleafNode(out, nodesInPath.get(i), i);
        }

        String objName = nodesInPath.get(i).getNodeKeyName();
        out.name(objName);
        if(!item.getFullPath().contains("rbnfrule")){
            out.beginArray();
        }
    }

    /**
     * Write a CLDR item to file.
     *
     * "usesMetazone" will be checked to see if it is current. Those non-current
     * item will be dropped.
     *
     * @param out
     *            The ArrayList to hold all output lines.
     * @param nodesForLastItem
     * @param item
     *            The CldrItem to be processed.
     * @throws IOException
     * @throws ParseException
     */
    private void outputCldrItem(JsonWriter out,
        ArrayList<CldrNode> nodesForLastItem, CldrItem item)
            throws IOException, ParseException {
        // alias has been resolved, no need to keep it.
        if (item.isAliasItem()) {
            return;
        }

        ArrayList<CldrNode> nodesInPath = item.getNodesInPath();
        int arraySize = nodesInPath.size();

        int i = findFirstDiffNodeIndex(nodesForLastItem, nodesInPath);
        if (i == nodesInPath.size() && type != RunType.rbnf) {
            System.err.println("This nodes and last nodes has identical path. ("
                + item.getPath() + ") Some distinguishing attributes wrongly removed?");
            return;
        }

        // close previous nodes
        closeNodes(out, nodesForLastItem.size() - 2, i);

        for (; i < nodesInPath.size() - 1; ++i) {
            startNonleafNode(out, nodesInPath.get(i), i);
        }

        writeLeafNode(out, nodesInPath.get(i), item.getValue(), i);
        nodesForLastItem.clear();
        nodesForLastItem.addAll(nodesInPath);
    }

    /**
     * Close nodes that no longer appears in path.
     *
     * @param out
     *            The JsonWriter to hold all output lines.
     * @param last
     *            The last node index in previous item.
     * @param firstDiff
     *            The first different node in next item.
     * @throws IOException
     */
    private void closeNodes(JsonWriter out, int last, int firstDiff)
        throws IOException {
        for (int i = last; i >= firstDiff; --i) {
            if (i == 0) {
                out.endObject();
                break;
            }
            out.endObject();
        }
    }

    /**
     * Start a non-leaf node, write out its attributes.
     *
     * @param out
     *            The ArrayList to hold all output lines.
     * @param node
     *            The node being written.
     * @param level
     *            indentation level.
     * @throws IOException
     */
    private void startNonleafNode(JsonWriter out, CldrNode node, int level)
        throws IOException {
        String objName = node.getNodeKeyName();
        // Some node should be skipped as indicated by objName being null.
        if (objName == null) {
            return;
        }

        // first level needs no key, it is the container.
        if (level == 0) {
            out.beginObject();
            return;
        }

        Map<String, String> attrAsValueMap = node.getAttrAsValueMap();

        out.name(objName);
        out.beginObject();
        for (String key : attrAsValueMap.keySet()) {
            String value = escapeValue(attrAsValueMap.get(key));
            // attribute is prefixed with "_" when being used as key.
            out.name("_" + key).value(value);
        }
    }

    /**
     * Write a CLDR item to file.
     *
     * "usesMetazone" will be checked to see if it is current. Those non-current
     * item will be dropped.
     *
     * @param out
     *            The ArrayList to hold all output lines.
     * @param item
     *            The CldrItem to be processed.
     * @param nodesForLastItem
     *            Nodes in path for last item.
     * @param arrayLevel
     *            The indentation level in which array exists.
     * @throws IOException
     * @throws ParseException
     */
    private void outputArrayItem(JsonWriter out, CldrItem item,
        ArrayList<CldrNode> nodesForLastItem, int arrayLevel)
            throws IOException, ParseException {

        // This method is more complicated that outputCldrItem because it needs to
        // handle 3 different cases.
        // 1. When difference is found below array item, this item will be of the
        // same array item. Inside the array item, it is about the same as
        // outputCldrItem, just with one more level of indentation because of
        // the array.
        // 2. The array item is the leaf item with no attribute, simplify it as
        // an object with one name/value pair.
        // 3. The array item is the leaf item with attribute, an embedded object
        // will be created inside the array item object.

        ArrayList<CldrNode> nodesInPath = item.getNodesInPath();
        String value = escapeValue(item.getValue());
        int nodesNum = nodesInPath.size();  


        // case 1
        int diff = findFirstDiffNodeIndex(nodesForLastItem, nodesInPath);
        if (diff > arrayLevel) {
            // close previous nodes
            closeNodes(out, nodesForLastItem.size() - 1, diff + 1);

            for (int i = diff; i < nodesNum - 1; i++) {
                startNonleafNode(out, nodesInPath.get(i), i + 1);
            }
            writeLeafNode(out, nodesInPath.get(nodesNum - 1), value, nodesNum);
            return;
        }

        if (arrayLevel == nodesNum - 1) {
            // case 2
            // close previous nodes
            if (nodesForLastItem.size() - 1 - arrayLevel > 0) {
                closeNodes(out, nodesForLastItem.size() - 1, arrayLevel);
            }

            String objName = nodesInPath.get(nodesNum - 1).getNodeKeyName();
            int pos = objName.indexOf('-');
            if (pos > 0) {
                objName = objName.substring(0, pos);
            }

            Map<String, String> attrAsValueMap =
                nodesInPath.get(nodesNum - 1).getAttrAsValueMap();

            // ADJUST RADIX BASED ON ICU RULE -- BEGIN
            if(attrAsValueMap.containsKey("radix"))
            {
                String radixValue = attrAsValueMap.get("radix");
                attrAsValueMap.remove("radix");
                for(Map.Entry<String,String> attributes : attrAsValueMap.entrySet()){
                    String oldKey = attributes.getKey();
                    String newValue = attributes.getValue();
                    String newKey = oldKey + "/" + radixValue;
                    attrAsValueMap.remove(oldKey);
                    attrAsValueMap.put(newKey, newValue);

                }               
            }
            // ADJUST RADIX BASED ON ICU RULE -- END

            if (attrAsValueMap.isEmpty()) {
                out.beginObject();
                out.name(objName).value(value);
                out.endObject();
            } else {
                if(!objName.equals("rbnfrule")){
                    out.beginObject();
                }
                writeLeafNode(out, objName, attrAsValueMap, value, nodesNum);
                if(!objName.equals("rbnfrule")){
                    out.endObject();
                }

            }
            // the last node is closed, remove it.
            nodesInPath.remove(nodesNum - 1);
        } else {
            // case 3
            // close previous nodes
            if (nodesForLastItem.size() - 1 - (arrayLevel) > 0) {
                closeNodes(out, nodesForLastItem.size() - 1, arrayLevel);
            }

            out.beginObject();

            CldrNode node = nodesInPath.get(arrayLevel);
            String objName = node.getNodeKeyName();
            int pos = objName.indexOf('-');
            if (pos > 0) {
                objName = objName.substring(0, pos);
            }
            Map<String, String> attrAsValueMap = node.getAttrAsValueMap();           
            out.name(objName);
            out.beginObject();
            for (String key : attrAsValueMap.keySet()) {
                // attribute is prefixed with "_" when being used as key.
                out.name("_" + key).value(escapeValue(attrAsValueMap.get(key)));
            }

            for (int i = arrayLevel + 1; i < nodesInPath.size() - 1; i++) {
                startNonleafNode(out, nodesInPath.get(i), i + 1);
            }
            writeLeafNode(out, nodesInPath.get(nodesNum - 1), value, nodesNum);
        }

        nodesForLastItem.clear();
        nodesForLastItem.addAll(nodesInPath);
    }

    /**
     * Compare two nodes list, find first index that the two list have different
     * nodes and return it.
     *
     * @param nodesForLastItem
     *            Nodes from last item.
     * @param nodesInPath
     *            Nodes for current item.
     * @return The index of first different node.
     */
    private int findFirstDiffNodeIndex(ArrayList<CldrNode> nodesForLastItem,
        ArrayList<CldrNode> nodesInPath) {
        int i;
        for (i = 0; i < nodesInPath.size(); ++i) {
            if (i >= nodesForLastItem.size() ||
                !nodesInPath.get(i).getNodeDistinguishingName().equals(
                    nodesForLastItem.get(i).getNodeDistinguishingName())) {
                break;
            }
        }
        return i;
    }

    /**
     * Process files in a directory of CLDR file tree.
     *
     * @param dirName
     *            The directory in which xml file will be transformed.
     * @param minimalDraftStatus
     *            The minimumDraftStatus that will be accepted.
     * @throws IOException
     * @throws ParseException
     */
    public void processDirectory(String dirName, DraftStatus minimalDraftStatus)
        throws IOException, ParseException {
        SupplementalDataInfo sdi = SupplementalDataInfo.getInstance(cldrCommonDir + "supplemental");
        Factory cldrFactory = Factory.make(
            cldrCommonDir + dirName + "/", ".*");
        Set<String> files = cldrFactory.getAvailable();
        for (String filename : files) {
            if (LdmlConvertRules.IGNORE_FILE_SET.contains(filename)) {
                continue;
            }
            if (!filename.matches(match)) {
                continue;
            }

            System.out.println("Processing file " + dirName + "/" + filename);
            String pathPrefix;
            CLDRFile file = cldrFactory.make(filename, resolve && type == RunType.main, minimalDraftStatus);

            sectionItems.clear();
            if (type == RunType.main) {
                pathPrefix = "/cldr/" + dirName + "/" + filename.replaceAll("_", "-") + "/";
            } else {
                pathPrefix = "/cldr/" + dirName + "/";
            }
            mapPathsToSections(file, pathPrefix, sdi);

            convertCldrItems(dirName, filename, pathPrefix);

        }


        if (writePackages) {
            for (String currentPackage : packages) {
                writePackagingFiles(outputDir, currentPackage);
            }
            if (type == RunType.main) {
                writeDefaultContent(outputDir);
                writeAvailableLocales(outputDir);
            } else if (type == RunType.supplemental) {
                writeScriptMetadata(outputDir);
            }

        }
    }

    /**
     * Replacement pattern for escaping.
     */
    private static final Pattern escapePattern = PatternCache.get("\\\\(?!u)");

    /**
     * Escape \ and " in value string.
     * \ should be replaced by \\, except in case of \u1234
     * " should be replaced by \"
     * In following code, \\\\ represent one \, because java compiler and
     * regular expression compiler each do one round of escape.
     *
     * @param value
     *            Input string.
     * @return escaped string.
     */
    private String escapeValue(String value) {
        Matcher match = escapePattern.matcher(value);
        String ret = match.replaceAll("\\\\\\\\");
        return ret.replace("\"", "\\\"").replace("\n", " ").replace("\t", " ");
    }

    /**
     * Write the value to output.
     *
     * @param out
     *            The ArrayList to hold all output lines.
     * @param node
     *            The CldrNode being written.
     * @param value
     *            The value part for this element.
     * @param level
     *            Indent level.
     * @throws IOException
     */
    private void writeLeafNode(JsonWriter out, CldrNode node, String value,
        int level) throws IOException {

        String objName = node.getNodeKeyName();
        Map<String, String> attrAsValueMaps = node.getAttrAsValueMap();
        writeLeafNode(out, objName, attrAsValueMaps, value, level);
    }

    /**
     * Write the value to output.
     *
     * @param out
     *            The ArrayList to hold all output lines.
     * @param objName
     *            The node's node.
     * @param attrAsValueMap
     *            Those attributes that will be treated as values.
     * @param value
     *            The value part for this element.
     * @param level
     *            Indent level.
     * @throws IOException
     */
    private void writeLeafNode(JsonWriter out, String objName,
        Map<String, String> attrAsValueMap, String value, int level)
            throws IOException {
        if (objName == null) {
            return;
        }
        value = escapeValue(value);

        if (attrAsValueMap.isEmpty()) {
            if (value.isEmpty()) {
                out.name(objName);
                out.beginObject();
                out.endObject();
            } else {
                out.name(objName).value(value);
            }
            return;
        }

        // If there is no value, but a attribute being treated as value,
        // simplify the output.
        if (value.isEmpty() &&
            attrAsValueMap.containsKey(LdmlConvertRules.ANONYMOUS_KEY)) {
            out.name(objName).value(attrAsValueMap.get(LdmlConvertRules.ANONYMOUS_KEY));
            return;
        }
        if(!objName.equals("rbnfrule")){
            out.name(objName);
            out.beginObject();
        }

        if (!value.isEmpty()) {
            out.name("_value").value(value);
        }

        for (String key : attrAsValueMap.keySet()) {
            String attrValue = escapeValue(attrAsValueMap.get(key));
            // attribute is prefixed with "_" when being used as key.
            if (LdmlConvertRules.ATTRVALUE_AS_ARRAY_SET.contains(key)) {
                String[] strings = attrValue.trim().split("\\s+");
                if(type != RunType.rbnf){
                    out.name("_" + key); 
                }
                else{
                    out.name(key);
                }
                out.beginArray();
                for (String s : strings) {
                    out.value(s);
                }
                out.endArray();
            } else {
                if(type != RunType.rbnf){
                    out.name("_" + key).value(attrValue); 
                }
                else{
                    out.name(key).value(attrValue);
                }

            }
        }
        if(!objName.equals("rbnfrule")){
            out.endObject();
        }
    }
}
