/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.manifmerger;

import com.android.common.annotations.NonNull;
import com.android.common.annotations.Nullable;
import com.android.manifmerger.IMergerLog.FileAndLine;
import com.android.manifmerger.IMergerLog.Severity;
import com.android.common.utils.ILogger;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

/**
 * A few XML handling utilities.
 */
public class XmlUtils {

    private static final String DATA_ORIGIN_FILE = "manif.merger.file";         //$NON-NLS-1$
    private static final String DATA_FILE_NAME   = "manif.merger.filename";     //$NON-NLS-1$
    private static final String DATA_LINE_NUMBER = "manif.merger.line#";        //$NON-NLS-1$

    /**
     * Parses the given XML file as a DOM document.
     * The parser does not validate the DTD nor any kind of schema.
     * It is namespace aware.
     * <p/>
     * This adds a user tag with the original {@link java.io.File} to the returned document.
     * You can retrieve this file later by using {@link #extractXmlFilename(org.w3c.dom.Node)}.
     *
     * @param xmlFile The XML {@link java.io.File} to parse. Must not be null.
     * @param log An {@link ILogger} for reporting errors. Must not be null.
     * @return A new DOM {@link org.w3c.dom.Document}, or null.
     */
    @Nullable
    static Document parseDocument(@NonNull final File xmlFile, @NonNull final IMergerLog log) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            InputSource is = new InputSource(new FileReader(xmlFile));
            factory.setNamespaceAware(true);
            factory.setValidating(false);
            DocumentBuilder builder = factory.newDocumentBuilder();

            // We don't want the default handler which prints errors to stderr.
            builder.setErrorHandler(new ErrorHandler() {
                @Override
                public void warning(SAXParseException e) {
                    log.error(Severity.WARNING,
                            new FileAndLine(xmlFile.getAbsolutePath(), 0),
                            "Warning when parsing: %1$s",
                            e.toString());
                }
                @Override
                public void fatalError(SAXParseException e) {
                    log.error(Severity.ERROR,
                            new FileAndLine(xmlFile.getAbsolutePath(), 0),
                            "Fatal error when parsing: %1$s",
                            xmlFile.getName(), e.toString());
                }
                @Override
                public void error(SAXParseException e) {
                    log.error(Severity.ERROR,
                            new FileAndLine(xmlFile.getAbsolutePath(), 0),
                            "Error when parsing: %1$s",
                            e.toString());
                }
            });

            Document doc = builder.parse(is);
            doc.setUserData(DATA_ORIGIN_FILE, xmlFile, null /*handler*/);
            findLineNumbers(doc, 1);

            return doc;

        } catch (FileNotFoundException e) {
            log.error(Severity.ERROR,
                    new FileAndLine(xmlFile.getAbsolutePath(), 0),
                    "XML file not found");

        } catch (Exception e) {
            log.error(Severity.ERROR,
                    new FileAndLine(xmlFile.getAbsolutePath(), 0),
                    "Failed to parse XML file: %1$s",
                    e.toString());
        }

        return null;
    }

    /**
     * Parses the given XML string as a DOM document.
     * The parser does not validate the DTD nor any kind of schema.
     * It is namespace aware.
     *
     * @param xml The XML string to parse. Must not be null.
     * @param log An {@link ILogger} for reporting errors. Must not be null.
     * @return A new DOM {@link org.w3c.dom.Document}, or null.
     */
    @Nullable
    static Document parseDocument(@NonNull String xml,
            @NonNull IMergerLog log,
            @NonNull FileAndLine errorContext) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            InputSource is = new InputSource(new StringReader(xml));
            factory.setNamespaceAware(true);
            factory.setValidating(false);
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(is);
            findLineNumbers(doc, 1);
            return doc;
        } catch (Exception e) {
            log.error(Severity.ERROR, errorContext, "Failed to parse XML string");
        }

        return null;
    }

    /**
     * Decorates the document with the specified file name, which can be
     * retrieved later by calling {@link #extractLineNumber(org.w3c.dom.Node)}.
     * <p/>
     * It also tries to add line number information, with the caveat that the
     * current implementation is a gross approximation.
     * <p/>
     * There is no need to call this after calling one of the {@code parseDocument()}
     * methods since they already decorated their own document.
     *
     * @param doc The document to decorate.
     * @param fileName The name to retrieve later for that document.
     */
    static void decorateDocument(@NonNull Document doc, @NonNull String fileName) {
        doc.setUserData(DATA_FILE_NAME, fileName, null /*handler*/);
        findLineNumbers(doc, 1);
    }

    /**
     * Extracts the origin {@link java.io.File} that {@link #parseDocument(java.io.File, com.android.manifmerger.IMergerLog)}
     * added to the XML document or the string added by
     *
     * @param xmlNode Any node from a document returned by {@link #parseDocument(java.io.File, com.android.manifmerger.IMergerLog)}.
     * @return The {@link java.io.File} object used to create the document or null.
     */
    @Nullable
    static String extractXmlFilename(@Nullable Node xmlNode) {
        if (xmlNode != null && xmlNode.getNodeType() != Node.DOCUMENT_NODE) {
            xmlNode = xmlNode.getOwnerDocument();
        }
        if (xmlNode != null) {
            Object data = xmlNode.getUserData(DATA_ORIGIN_FILE);
            if (data instanceof File) {
                return ((File) data).getName();
            }
            data = xmlNode.getUserData(DATA_FILE_NAME);
            if (data instanceof String) {
                return (String) data;
            }
        }

        return null;
    }

    /**
     * This is a CRUDE INEXACT HACK to decorate the DOM with some kind of line number
     * information for elements. It's inexact because by the time we get the DOM we
     * already have lost all the information about whitespace between attributes.
     * <p/>
     * Also we don't even try to deal with \n vs \r vs \r\n insanity. This only counts
     * the \n occurring in text nodes to determine line advances, which is clearly flawed.
     * <p/>
     * However it's good enough for testing, and we'll replace it by a PositionXmlParser
     * once it's moved into com.android.util.
     */
    private static int findLineNumbers(Node node, int line) {
        for (; node != null; node = node.getNextSibling()) {
            node.setUserData(DATA_LINE_NUMBER, Integer.valueOf(line), null /*handler*/);

            if (node.getNodeType() == Node.TEXT_NODE) {
                String text = node.getNodeValue();
                if (text.length() > 0) {
                    for (int pos = 0; (pos = text.indexOf('\n', pos)) != -1; pos++) {
                        ++line;
                    }
                }
            }

            Node child = node.getFirstChild();
            if (child != null) {
                line = findLineNumbers(child, line);
            }
        }
        return line;
    }

    /**
     * Extracts the line number that {@link #findLineNumbers} added to the XML nodes.
     *
     * @param xmlNode Any node from a document returned by {@link #parseDocument(java.io.File, com.android.manifmerger.IMergerLog)}.
     * @return The line number if found or 0.
     */
    static int extractLineNumber(@Nullable Node xmlNode) {
        if (xmlNode != null) {
            Object data = xmlNode.getUserData(DATA_LINE_NUMBER);
            if (data instanceof Integer) {
                return ((Integer) data).intValue();
            }
        }

        return 0;
    }

    /**
     * Find the prefix for the given NS_URI in the document.
     *
     * @param doc The document root.
     * @param nsUri The Namespace URI to look for.
     * @return The namespace prefix if found or null.
     */
    static String lookupNsPrefix(Document doc, String nsUri) {
        return com.android.common.utils.XmlUtils.lookupNamespacePrefix(doc, nsUri);
    }

    /**
     * Outputs the given XML {@link org.w3c.dom.Document} to the file {@code outFile}.
     *
     * TODO right now reformats the document. Needs to output as-is, respecting white-space.
     *
     * @param doc The document to output. Must not be null.
     * @param outFile The {@link java.io.File} where to write the document.
     * @param log A log in case of error.
     * @return True if the file was written, false in case of error.
     */
    static boolean printXmlFile(
            @NonNull Document doc,
            @NonNull File outFile,
            @NonNull IMergerLog log) {
        // Quick thing based on comments from http://stackoverflow.com/questions/139076
        try {
            Transformer tf = TransformerFactory.newInstance().newTransformer();
            tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");         //$NON-NLS-1$
            tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");                   //$NON-NLS-1$
            tf.setOutputProperty(OutputKeys.INDENT, "yes");                       //$NON-NLS-1$
            tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount",     //$NON-NLS-1$
                                 "4");                                            //$NON-NLS-1$
            tf.transform(new DOMSource(doc), new StreamResult(outFile));
            return true;
        } catch (TransformerException e) {
            log.error(Severity.ERROR,
                    new FileAndLine(outFile.getName(), 0),
                    "Failed to write XML file: %1$s",
                    e.toString());
            return false;
        }
    }

    /**
     * Outputs the given XML {@link org.w3c.dom.Document} as a string.
     *
     * TODO right now reformats the document. Needs to output as-is, respecting white-space.
     *
     * @param doc The document to output. Must not be null.
     * @param log A log in case of error.
     * @return A string representation of the XML. Null in case of error.
     */
    static String printXmlString(
            @NonNull Document doc,
            @NonNull IMergerLog log) {
        try {
            Transformer tf = TransformerFactory.newInstance().newTransformer();
            tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");        //$NON-NLS-1$
            tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");                  //$NON-NLS-1$
            tf.setOutputProperty(OutputKeys.INDENT, "yes");                      //$NON-NLS-1$
            tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount",    //$NON-NLS-1$
                                 "4");                                           //$NON-NLS-1$
            StringWriter sw = new StringWriter();
            tf.transform(new DOMSource(doc), new StreamResult(sw));
            return sw.toString();
        } catch (TransformerException e) {
            log.error(Severity.ERROR,
                    new FileAndLine(extractXmlFilename(doc), 0),
                    "Failed to write XML file: %1$s",
                    e.toString());
            return null;
        }
    }

    /**
     * Dumps the structure of the DOM to a simple text string.
     *
     * @param node The first node to dump (recursively). Can be null.
     * @param nextSiblings If true, will also dump the following siblings.
     *   If false, it will just process the given node.
     * @return A string representation of the Node structure, useful for debugging.
     */
    @NonNull
    static String dump(@Nullable Node node, boolean nextSiblings) {
        return dump(node, 0 /*offset*/, nextSiblings, true /*deep*/, null /*keyAttr*/);
    }


    /**
     * Dumps the structure of the DOM to a simple text string.
     * Each line is terminated with a \n separator.
     *
     * @param node The first node to dump. Can be null.
     * @param offsetIndex The offset to add at the begining of each line. Each offset is
     *   converted into 2 space characters.
     * @param nextSiblings If true, will also dump the following siblings.
     *   If false, it will just process the given node.
     * @param deep If true, this will recurse into children.
     * @param keyAttr An optional attribute *local* name to insert when writing an element.
     *   For example when writing an Activity, it helps to always insert "name" attribute.
     * @return A string representation of the Node structure, useful for debugging.
     */
    @NonNull
    static String dump(
            @Nullable Node node,
            int offsetIndex,
            boolean nextSiblings,
            boolean deep,
            @Nullable String keyAttr) {
        StringBuilder sb = new StringBuilder();

        String offset = "";                 //$NON-NLS-1$
        for (int i = 0; i < offsetIndex; i++) {
            offset += "  ";                 //$NON-NLS-1$
        }

        if (node == null) {
            sb.append(offset).append("(end reached)\n");

        } else {
            for (; node != null; node = node.getNextSibling()) {
                String type = null;
                short t = node.getNodeType();
                switch(t) {
                case Node.ELEMENT_NODE:
                    String attr = "";
                    if (keyAttr != null) {
                        NamedNodeMap attrs = node.getAttributes();
                        if (attrs != null) {
                            for (int i = 0; i < attrs.getLength(); i++) {
                                Node a = attrs.item(i);
                                if (a != null && keyAttr.equals(a.getLocalName())) {
                                    attr = String.format(" %1$s=%2$s",
                                            a.getNodeName(), a.getNodeValue());
                                    break;
                                }
                            }
                        }
                    }
                    sb.append(String.format("%1$s<%2$s%3$s>\n",
                            offset, node.getNodeName(), attr));
                    break;
                case Node.COMMENT_NODE:
                    sb.append(String.format("%1$s<!-- %2$s -->\n",
                            offset, node.getNodeValue()));
                    break;
                case Node.TEXT_NODE:
                        String txt = node.getNodeValue().trim();
                         if (txt.length() == 0) {
                             // Keep this for debugging. TODO make it a flag
                             // to dump whitespace on debugging. Otherwise ignore it.
                             // txt = "[whitespace]";
                             break;
                         }
                        sb.append(String.format("%1$s%2$s\n", offset, txt));
                    break;
                case Node.ATTRIBUTE_NODE:
                    sb.append(String.format("%1$s    @%2$s = %3$s\n",
                            offset, node.getNodeName(), node.getNodeValue()));
                    break;
                case Node.CDATA_SECTION_NODE:
                    type = "cdata";                 //$NON-NLS-1$
                    break;
                case Node.DOCUMENT_NODE:
                    type = "document";              //$NON-NLS-1$
                    break;
                case Node.PROCESSING_INSTRUCTION_NODE:
                    type = "PI";                    //$NON-NLS-1$
                    break;
                default:
                    type = Integer.toString(t);
                }

                if (type != null) {
                    sb.append(String.format("%1$s[%2$s] <%3$s> %4$s\n",
                            offset, type, node.getNodeName(), node.getNodeValue()));
                }

                if (deep) {
                    List<Attr> attrs = sortedAttributeList(node.getAttributes());
                    for (Attr attr : attrs) {
                        sb.append(String.format("%1$s    @%2$s = %3$s\n",
                                offset, attr.getNodeName(), attr.getNodeValue()));
                    }

                    Node child = node.getFirstChild();
                    if (child != null) {
                        sb.append(dump(child, offsetIndex+1, true, true, keyAttr));
                    }
                }

                if (!nextSiblings) {
                    break;
                }
            }
        }
        return sb.toString();
    }

    /**
     * Returns a sorted list of attributes.
     * The list is never null and does not contain null items.
     *
     * @param attrMap A Node map as returned by {@link org.w3c.dom.Node#getAttributes()}.
     *   Can be null, in which case an empty list is returned.
     * @return A non-null, possible empty, list of all nodes that are actual {@link org.w3c.dom.Attr},
     *   sorted by increasing attribute name.
     */
    @NonNull
    public static List<Attr> sortedAttributeList(@Nullable NamedNodeMap attrMap) {
        List<Attr> list = new ArrayList<Attr>();

        if (attrMap != null) {
            for (int i = 0; i < attrMap.getLength(); i++) {
                Node attr = attrMap.item(i);
                if (attr instanceof Attr) {
                    list.add((Attr) attr);
                }
            }
        }

        if (list.size() > 1) {
            // Sort it by attribute name
            Collections.sort(list, getAttrComparator());
        }

        return list;
    }

    /**
     * Returns a comparator for {@link org.w3c.dom.Attr}, alphabetically sorted by name.
     * The "name" attribute is special and always sorted to the front.
     */
    @NonNull
    public static Comparator<? super Attr> getAttrComparator() {
        return new Comparator<Attr>() {
            @Override
            public int compare(Attr a1, Attr a2) {
                String s1 = a1 == null ? "" : a1.getNodeName();           //$NON-NLS-1$
                String s2 = a2 == null ? "" : a2.getNodeName();           //$NON-NLS-1$

                int prio1 = s1.equals("name") ? 0 : 1;                    //$NON-NLS-1$
                int prio2 = s2.equals("name") ? 0 : 1;                    //$NON-NLS-1$
                if (prio1 == 0 || prio2 == 0) {
                    return prio1 - prio2;
                }

                return s1.compareTo(s2);
            }
        };
    }
}
