/*
 *******************************************************************************
 * Copyright (C) 2004, International Business Machines Corporation and         *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 *
 */
/**
 * @author Ram Viswanadha
 */
package org.unicode.cldr.icu;

import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import org.unicode.cldr.util.LDMLUtilities;
import org.unicode.cldr.util.XPathTokenizer;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import com.ibm.icu.dev.tool.UOption;

public class LDMLNodesAdder {
    /**
     * These must be kept in sync with getOptions().
     */
    private static final int HELP1 = 0;
    private static final int HELP2 = 1;
    private static final int MAINFILE = 2;
    private static final int EXTRACTFILE = 3;
    private static final int DESTFILE = 4;
    private static final int ADDONLY = 5;

    private static final UOption[] options = new UOption[] {
        UOption.HELP_H(),
        UOption.HELP_QUESTION_MARK(),
        UOption.create("main", 'm', UOption.REQUIRES_ARG),
        UOption.create("extract", 'e', UOption.REQUIRES_ARG),
        UOption.DESTDIR(),
        UOption.create("add-only", 'a', UOption.NO_ARG),

    };

    private String mainfile = null;
    private String destfile = null;
    private String extractfile = null;
    private boolean addonly = false;

    public static void main(String[] args) {
        LDMLNodesAdder cnv = new LDMLNodesAdder();
        cnv.processArgs(args);
    }

    private void usage() {
        System.out
            .println("\nUsage: LDMLNodesAdder [OPTIONS] [XPATH1] [XPATH2]\n\n"
                +
                "This program is used to extract nodes from extract LDML file and merge \n"
                +
                "the extracted nodes with the main LDML file\n"
                +
                "Please refer to the following options. Options are not case sensitive.\n"
                +
                "Options:\n"
                +
                "-m or --main               The LDML file to which the extracted nodes are merged\n"
                +
                "-o or --extract            The LDML file from which the nodes need to be extracted\n"
                +
                "-d or --destination        destination directory, followed by the path, default is current directory.\n"
                +
                "-a or --add-only           Don't replace existing nodes in the main document.\n"
                +
                "-h or -? or --help         this usage text.\n"
                +
                "example: com.ibm.icu.dev.tool.cldr.LDMLNodesAdder -m locale/common/main/en.xml -o locale/ibmjdk/main/en.xml //ldml/dates/calendars/calendar[@type='chinese'] //ldml/posix");
        System.exit(-1);
    }

    private void processArgs(String[] args) {
        int remainingArgc = 0;
        try {
            remainingArgc = UOption.parseArgs(args, options);
        } catch (Exception e) {
            System.err.println("ERROR: " + e.toString());
            e.printStackTrace();
            usage();
        }
        if (args.length == 0 || options[HELP1].doesOccur || options[HELP2].doesOccur) {
            usage();
        }

        if (options[MAINFILE].doesOccur) {
            mainfile = options[MAINFILE].value;
        }
        if (options[DESTFILE].doesOccur) {
            destfile = options[DESTFILE].value;
        }
        if (options[EXTRACTFILE].doesOccur) {
            extractfile = options[EXTRACTFILE].value;
        }
        if (options[ADDONLY].doesOccur) {
            addonly = true;
        }
        if (destfile == null) {
            throw new RuntimeException("Destination not specified");
        }
        if (remainingArgc < 1) {
            usage();
            System.exit(-1);
        }
        try {
            Document maindoc = LDMLUtilities.parse(mainfile, false);
            Document extractdoc = LDMLUtilities.parse(extractfile, false);

            System.out.println("INFO: Merging nodes and marking them draft");
            mergeNodes(maindoc, extractdoc, args, remainingArgc);
            System.out.println("INFO: Removing specials");
            removeSpecials(maindoc);
            System.out.println("INFO: Fixing eras");
            fixEras(maindoc);
            maindoc.normalize();
            OutputStreamWriter writer = new
                OutputStreamWriter(new FileOutputStream(destfile), "UTF-8");
            PrintWriter pw = new PrintWriter(writer);
            LDMLUtilities.printDOMTree(maindoc, pw, "http://www.unicode.org/cldr/dtd/1.3/ldml.dtd", null);
            writer.flush();
        } catch (Exception e) {
            e.printStackTrace();
            // System.exit(-1);
        }
    }

    // private static final String xmlheader = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
    // private static final String doctype =
    // "<!DOCTYPE ldml SYSTEM \"http://oss.software.ibm.com/cvs/icu/~checkout~/locale/ldml.dtd\">\n";

    private void mergeNodes(Document maindoc, Document extractdoc, String[] args, int argc) {
        for (int i = 0; i < argc; i++) {
            Node extract = LDMLUtilities.getNode(extractdoc, args[i]);
            Node nodeInSource = LDMLUtilities.getNode(maindoc, args[i]);
            Node parentNode = null;
            StringBuffer xpath = new StringBuffer(args[i]);
            if (nodeInSource == null) {
                int j = 0;
                while (parentNode == null) {
                    XPathTokenizer.deleteToken(xpath);
                    parentNode = LDMLUtilities.getNode(maindoc, xpath.toString());
                    if (j > 0) {
                        extract = extract.getParentNode();
                    }
                    j++;
                }
                extract = maindoc.importNode(extract, true);
                parentNode.appendChild(extract);
                Attr draft = maindoc.createAttribute("draft");
                draft.setValue("true");
                ((Element) extract).setAttributeNode(draft);
            } else if (!addonly) {
                parentNode = nodeInSource.getParentNode();
                extract = maindoc.importNode(extract, true);
                parentNode.replaceChild(extract, nodeInSource);
                Attr draft = maindoc.createAttribute("draft");
                draft.setValue("true");
                ((Element) extract).setAttributeNode(draft);
            }
        }
    }

    private void removeSpecials(Document doc) {
        Node[] nodes = LDMLUtilities.getElementsByTagName(doc, LDMLConstants.SPECIAL);
        if (nodes != null) {
            for (int i = 0; i < nodes.length; i++) {
                Node parent = nodes[i].getParentNode();
                parent.removeChild(nodes[i]);
            }
        }
    }

    private void fixEras(Document doc) {
        Node[] nodes = LDMLUtilities.getElementsByTagName(doc, LDMLConstants.ERA);
        if (nodes != null) {
            for (int i = 0; i < nodes.length; i++) {
                NamedNodeMap attr = nodes[i].getAttributes();
                Node type = attr.getNamedItem(LDMLConstants.TYPE);
                if (type != null) {
                    String val = type.getNodeValue();
                    int j = Integer.parseInt(val);
                    if (j > 0) {
                        j--;
                    }
                    type.setNodeValue(Integer.toString(j));
                }
            }
        }
    }
}
