/*
 * Copyright (C) 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.
 */
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import vogar.ExpectationStore;
import vogar.Expectation;

import com.sun.javadoc.AnnotationDesc;
import com.sun.javadoc.AnnotationTypeDoc;
import com.sun.javadoc.AnnotationValue;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.Doclet;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.RootDoc;
import com.sun.javadoc.AnnotationDesc.ElementValuePair;

/**
 * This is only a very simple and brief JavaDoc parser for the CTS.
 *
 * Input: The source files of the test cases. It will be represented
 *          as a list of ClassDoc
 * Output: Generate file description.xml, which defines the TestPackage
 *          TestSuite and TestCases.
 *
 * Note:
 *  1. Since this class has dependencies on com.sun.javadoc package which
 *       is not implemented on Android. So this class can't be compiled.
 *  2. The TestSuite can be embedded, which means:
 *      TestPackage := TestSuite*
 *      TestSuite := TestSuite* | TestCase*
 */
public class DescriptionGenerator extends Doclet {
    static final String HOST_CONTROLLER = "dalvik.annotation.HostController";
    static final String KNOWN_FAILURE = "dalvik.annotation.KnownFailure";
    static final String SUPPRESSED_TEST = "android.test.suitebuilder.annotation.Suppress";
    static final String CTS_EXPECTATION_DIR = "cts/tests/expectations";

    static final String JUNIT_TEST_CASE_CLASS_NAME = "junit.framework.testcase";
    static final String TAG_PACKAGE = "TestPackage";
    static final String TAG_SUITE = "TestSuite";
    static final String TAG_CASE = "TestCase";
    static final String TAG_TEST = "Test";
    static final String TAG_DESCRIPTION = "Description";

    static final String ATTRIBUTE_NAME_VERSION = "version";
    static final String ATTRIBUTE_VALUE_VERSION = "1.0";
    static final String ATTRIBUTE_NAME_FRAMEWORK = "AndroidFramework";
    static final String ATTRIBUTE_VALUE_FRAMEWORK = "Android 1.0";

    static final String ATTRIBUTE_NAME = "name";
    static final String ATTRIBUTE_ABIS = "abis";
    static final String ATTRIBUTE_HOST_CONTROLLER = "HostController";
    static final String ATTRIBUTE_TIMEOUT = "timeout";

    static final String XML_OUTPUT_PATH = "./description.xml";

    static final String OUTPUT_PATH_OPTION = "-o";
    static final String ARCHITECTURE_OPTION = "-a";

    /**
     * Start to parse the classes passed in by javadoc, and generate
     * the xml file needed by CTS packer.
     *
     * @param root The root document passed in by javadoc.
     * @return Whether the document has been processed.
     */
    public static boolean start(RootDoc root) {
        ClassDoc[] classes = root.classes();
        if (classes == null) {
            Log.e("No class found!", null);
            return true;
        }

        String outputPath = XML_OUTPUT_PATH;
        String architecture = null;
        String[][] options = root.options();
        for (String[] option : options) {
            if (option.length == 2) {
                if (option[0].equals(OUTPUT_PATH_OPTION)) {
                    outputPath = option[1];
                } else if (option[0].equals(ARCHITECTURE_OPTION)) {
                    architecture = option[1];
                }
            }
        }
        if (architecture == null || architecture.equals("")) {
            Log.e("Missing architecture!", null);
            return false;
        }

        XMLGenerator xmlGenerator = null;
        try {
            xmlGenerator = new XMLGenerator(outputPath);
        } catch (ParserConfigurationException e) {
            Log.e("Cant initialize XML Generator!", e);
            return true;
        }

        ExpectationStore ctsExpectationStore = null;
        try {
            ctsExpectationStore = VogarUtils.provideExpectationStore("./" + CTS_EXPECTATION_DIR);
        } catch (IOException e) {
            Log.e("Couldn't load expectation store.", e);
            return false;
        }

        for (ClassDoc clazz : classes) {
            if ((!clazz.isAbstract()) && (isValidJUnitTestCase(clazz))) {
                xmlGenerator.addTestClass(new TestClass(clazz, ctsExpectationStore, architecture));
            }
        }

        try {
            xmlGenerator.dump();
        } catch (Exception e) {
            Log.e("Can't dump to XML file!", e);
        }

        return true;
    }

    /**
     * Return the length of any doclet options we recognize
     * @param option The option name
     * @return The number of words this option takes (including the option) or 0 if the option
     * is not recognized.
     */
    public static int optionLength(String option) {
        if (option.equals(OUTPUT_PATH_OPTION)) {
            return 2;
        }
        return 0;
    }

    /**
     * Check if the class is valid test case inherited from JUnit TestCase.
     *
     * @param clazz The class to be checked.
     * @return If the class is valid test case inherited from JUnit TestCase, return true;
     *         else, return false.
     */
    static boolean isValidJUnitTestCase(ClassDoc clazz) {
        while((clazz = clazz.superclass()) != null) {
            if (JUNIT_TEST_CASE_CLASS_NAME.equals(clazz.qualifiedName().toLowerCase())) {
                return true;
            }
        }

        return false;
    }

    /**
     * Log utility.
     */
    static class Log {
        private static boolean TRACE = true;
        private static BufferedWriter mTraceOutput = null;

        /**
         * Log the specified message.
         *
         * @param msg The message to be logged.
         */
        static void e(String msg, Exception e) {
            System.out.println(msg);

            if (e != null) {
                e.printStackTrace();
            }
        }

        /**
         * Add the message to the trace stream.
         *
         * @param msg The message to be added to the trace stream.
         */
        public static void t(String msg) {
            if (TRACE) {
                try {
                    if ((mTraceOutput != null) && (msg != null)) {
                        mTraceOutput.write(msg + "\n");
                        mTraceOutput.flush();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        /**
         * Initialize the trace stream.
         *
         * @param name The class name.
         */
        public static void initTrace(String name) {
            if (TRACE) {
                try {
                    if (mTraceOutput == null) {
                        String fileName = "cts_debug_dg_" + name + ".txt";
                        mTraceOutput = new BufferedWriter(new FileWriter(fileName));
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        /**
         * Close the trace stream.
         */
        public static void closeTrace() {
            if (mTraceOutput != null) {
                try {
                    mTraceOutput.close();
                    mTraceOutput = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    static class XMLGenerator {
        String mOutputPath;

        /**
         * This document is used to represent the description XML file.
         * It is construct by the classes passed in, which contains the
         * information of all the test package, test suite and test cases.
         */
        Document mDoc;

        XMLGenerator(String outputPath) throws ParserConfigurationException {
            mOutputPath = outputPath;

            mDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

            Node testPackageElem = mDoc.appendChild(mDoc.createElement(TAG_PACKAGE));

            setAttribute(testPackageElem, ATTRIBUTE_NAME_VERSION, ATTRIBUTE_VALUE_VERSION);
            setAttribute(testPackageElem, ATTRIBUTE_NAME_FRAMEWORK, ATTRIBUTE_VALUE_FRAMEWORK);
        }

        void addTestClass(TestClass tc) {
            appendSuiteToElement(mDoc.getDocumentElement(), tc);
        }

        void dump() throws TransformerFactoryConfigurationError,
                FileNotFoundException, TransformerException {
            //rebuildDocument();

            Transformer t = TransformerFactory.newInstance().newTransformer();

            // enable indent in result file
            t.setOutputProperty("indent", "yes");
            t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount","4");

            File file = new File(mOutputPath);
            file.getParentFile().mkdirs();

            t.transform(new DOMSource(mDoc),
                    new StreamResult(new FileOutputStream(file)));
        }

        /**
         * Rebuild the document, merging empty suite nodes.
         */
        void rebuildDocument() {
            // merge empty suite nodes
            Collection<Node> suiteElems = getUnmutableChildNodes(mDoc.getDocumentElement());
            Iterator<Node> suiteIterator = suiteElems.iterator();
            while (suiteIterator.hasNext()) {
                Node suiteElem = suiteIterator.next();

                mergeEmptySuites(suiteElem);
            }
        }

        /**
         * Merge the test suite which only has one sub-suite. In this case, unify
         * the name of the two test suites.
         *
         * @param suiteElem The suite element of which to be merged.
         */
        void mergeEmptySuites(Node suiteElem) {
            Collection<Node> suiteChildren = getSuiteChildren(suiteElem);
            if (suiteChildren.size() > 1) {
                for (Node suiteChild : suiteChildren) {
                    mergeEmptySuites(suiteChild);
                }
            } else if (suiteChildren.size() == 1) {
                // do merge
                Node child = suiteChildren.iterator().next();

                // update name
                String newName = getAttribute(suiteElem, ATTRIBUTE_NAME) + "."
                        + getAttribute(child, ATTRIBUTE_NAME);
                setAttribute(child, ATTRIBUTE_NAME, newName);

                // update parent node
                Node parentNode = suiteElem.getParentNode();
                parentNode.removeChild(suiteElem);
                parentNode.appendChild(child);

                mergeEmptySuites(child);
            }
        }

        /**
         * Get the unmuatable child nodes for specified node.
         *
         * @param node The specified node.
         * @return A collection of copied child node.
         */
        private Collection<Node> getUnmutableChildNodes(Node node) {
            ArrayList<Node> nodes = new ArrayList<Node>();
            NodeList nodelist = node.getChildNodes();

            for (int i = 0; i < nodelist.getLength(); i++) {
                nodes.add(nodelist.item(i));
            }

            return nodes;
        }

        /**
         * Append a named test suite to a specified element. Including match with
         * the existing suite nodes and do the real creation and append.
         *
         * @param elem The specified element.
         * @param testSuite The test suite to be appended.
         */
        void appendSuiteToElement(Node elem, TestClass testSuite) {
            String suiteName = testSuite.mName;
            Collection<Node> children = getSuiteChildren(elem);
            int dotIndex = suiteName.indexOf('.');
            String name = dotIndex == -1 ? suiteName : suiteName.substring(0, dotIndex);

            boolean foundMatch = false;
            for (Node child : children) {
                String childName = child.getAttributes().getNamedItem(ATTRIBUTE_NAME)
                        .getNodeValue();

                if (childName.equals(name)) {
                    foundMatch = true;
                    if (dotIndex == -1) {
                        appendTestCases(child, testSuite.mCases);
                    } else {
                        testSuite.mName = suiteName.substring(dotIndex + 1, suiteName.length());
                        appendSuiteToElement(child, testSuite);
                    }
                }

            }

            if (!foundMatch) {
                appendSuiteToElementImpl(elem, testSuite);
            }
        }

        /**
         * Get the test suite child nodes of a specified element.
         *
         * @param elem The specified element node.
         * @return The matched child nodes.
         */
        Collection<Node> getSuiteChildren(Node elem) {
            ArrayList<Node> suites = new ArrayList<Node>();

            NodeList children = elem.getChildNodes();
            for (int i = 0; i < children.getLength(); i++) {
                Node child = children.item(i);

                if (child.getNodeName().equals(DescriptionGenerator.TAG_SUITE)) {
                    suites.add(child);
                }
            }

            return suites;
        }

        /**
         * Create test case node according to the given method names, and append them
         * to the test suite element.
         *
         * @param elem The test suite element.
         * @param cases A collection of test cases included by the test suite class.
         */
        void appendTestCases(Node elem, Collection<TestMethod> cases) {
            if (cases.isEmpty()) {
                // if no method, remove from parent
                elem.getParentNode().removeChild(elem);
            } else {
                for (TestMethod caze : cases) {
                    if (caze.mIsBroken || caze.mIsSuppressed || caze.mKnownFailure != null) {
                        continue;
                    }
                    Node caseNode = elem.appendChild(mDoc.createElement(TAG_TEST));

                    setAttribute(caseNode, ATTRIBUTE_NAME, caze.mName);
                    String abis = caze.mAbis.toString();
                    setAttribute(caseNode, ATTRIBUTE_ABIS, abis.substring(1, abis.length() - 1));
                    if ((caze.mController != null) && (caze.mController.length() != 0)) {
                        setAttribute(caseNode, ATTRIBUTE_HOST_CONTROLLER, caze.mController);
                    }
                    if (caze.mTimeoutInMinutes != 0) {
                        setAttribute(caseNode, ATTRIBUTE_TIMEOUT,
                                     Integer.toString(caze.mTimeoutInMinutes));
                    }

                    if (caze.mDescription != null && !caze.mDescription.equals("")) {
                        caseNode.appendChild(mDoc.createElement(TAG_DESCRIPTION))
                                .setTextContent(caze.mDescription);
                    }
                }
            }
        }

        /**
         * Set the attribute of element.
         *
         * @param elem The element to be set attribute.
         * @param name The attribute name.
         * @param value The attribute value.
         */
        protected void setAttribute(Node elem, String name, String value) {
            Attr attr = mDoc.createAttribute(name);
            attr.setNodeValue(value);

            elem.getAttributes().setNamedItem(attr);
        }

        /**
         * Get the value of a specified attribute of an element.
         *
         * @param elem The element node.
         * @param name The attribute name.
         * @return The value of the specified attribute.
         */
        private String getAttribute(Node elem, String name) {
            return elem.getAttributes().getNamedItem(name).getNodeValue();
        }

        /**
         * Do the append, including creating test suite nodes and test case nodes, and
         * append them to the element.
         *
         * @param elem The specified element node.
         * @param testSuite The test suite to be append.
         */
        void appendSuiteToElementImpl(Node elem, TestClass testSuite) {
            Node parent = elem;
            String suiteName = testSuite.mName;

            int dotIndex;
            while ((dotIndex = suiteName.indexOf('.')) != -1) {
                String name = suiteName.substring(0, dotIndex);

                Node suiteElem = parent.appendChild(mDoc.createElement(TAG_SUITE));
                setAttribute(suiteElem, ATTRIBUTE_NAME, name);

                parent = suiteElem;
                suiteName = suiteName.substring(dotIndex + 1, suiteName.length());
            }

            Node leafSuiteElem = parent.appendChild(mDoc.createElement(TAG_CASE));
            setAttribute(leafSuiteElem, ATTRIBUTE_NAME, suiteName);

            appendTestCases(leafSuiteElem, testSuite.mCases);
        }
    }

    /**
     * Represent the test class.
     */
    static class TestClass {
        String mName;
        Collection<TestMethod> mCases;

        /**
         * Construct an test suite object.
         *
         * @param name Full name of the test suite, such as "com.google.android.Foo"
         * @param cases The test cases included in this test suite.
         */
        TestClass(String name, Collection<TestMethod> cases) {
            mName = name;
            mCases = cases;
        }

        /**
         * Construct a TestClass object using ClassDoc.
         *
         * @param clazz The specified ClassDoc.
         */
        TestClass(ClassDoc clazz, ExpectationStore expectationStore, String architecture) {
            mName = clazz.toString();
            mCases = getTestMethods(expectationStore, architecture, clazz);
        }

        /**
         * Get all the TestMethod from a ClassDoc, including inherited methods.
         *
         * @param clazz The specified ClassDoc.
         * @return A collection of TestMethod.
         */
        Collection<TestMethod> getTestMethods(ExpectationStore expectationStore,
                String architecture, ClassDoc clazz) {
            Collection<MethodDoc> methods = getAllMethods(clazz);

            ArrayList<TestMethod> cases = new ArrayList<TestMethod>();
            Iterator<MethodDoc> iterator = methods.iterator();

            while (iterator.hasNext()) {
                MethodDoc method = iterator.next();

                String name = method.name();

                AnnotationDesc[] annotations = method.annotations();
                String controller = "";
                String knownFailure = null;
                boolean isBroken = false;
                boolean isSuppressed = false;
                for (AnnotationDesc cAnnot : annotations) {

                    AnnotationTypeDoc atype = cAnnot.annotationType();
                    if (atype.toString().equals(HOST_CONTROLLER)) {
                        controller = getAnnotationDescription(cAnnot);
                    } else if (atype.toString().equals(KNOWN_FAILURE)) {
                        knownFailure = getAnnotationDescription(cAnnot);
                    } else if (atype.toString().equals(SUPPRESSED_TEST)) {
                        isSuppressed = true;
                    }
                }

                if (VogarUtils.isVogarKnownFailure(expectationStore, clazz.toString(), name)) {
                    isBroken = true;
                }

                if (name.startsWith("test")) {
                    Expectation expectation = expectationStore.get(
                            VogarUtils.buildFullTestName(clazz.toString(), name));
                    Set<String> supportedAbis =
                            VogarUtils.extractSupportedAbis(architecture, expectation);
                    int timeoutInMinutes = VogarUtils.timeoutInMinutes(expectation);
                    cases.add(new TestMethod(
                            name, method.commentText(), controller, supportedAbis,
                                    knownFailure, isBroken, isSuppressed, timeoutInMinutes));
                }
            }

            return cases;
        }

        /**
         * Get annotation description.
         *
         * @param cAnnot The annotation.
         */
        String getAnnotationDescription(AnnotationDesc cAnnot) {
            ElementValuePair[] cpairs = cAnnot.elementValues();
            ElementValuePair evp = cpairs[0];
            AnnotationValue av = evp.value();
            String description = av.toString();
            // FIXME: need to find out the reason why there are leading and trailing "
            description = description.substring(1, description.length() -1);
            return description;
        }

        /**
         * Get all MethodDoc of a ClassDoc, including inherited methods.
         *
         * @param clazz The specified ClassDoc.
         * @return A collection of MethodDoc.
         */
        Collection<MethodDoc> getAllMethods(ClassDoc clazz) {
            ArrayList<MethodDoc> methods = new ArrayList<MethodDoc>();

            for (MethodDoc method : clazz.methods()) {
                methods.add(method);
            }

            ClassDoc superClass = clazz.superclass();
            while (superClass != null) {
                for (MethodDoc method : superClass.methods()) {
                    methods.add(method);
                }

                superClass = superClass.superclass();
            }

            return methods;
        }

    }

    /**
     * Represent the test method inside the test class.
     */
    static class TestMethod {
        String mName;
        String mDescription;
        String mController;
        Set<String> mAbis;
        String mKnownFailure;
        boolean mIsBroken;
        boolean mIsSuppressed;
        int mTimeoutInMinutes;  // zero to use default timeout.

        /**
         * Construct an test case object.
         *
         * @param name The name of the test case.
         * @param description The description of the test case.
         * @param knownFailure The reason of known failure.
         */
        TestMethod(String name, String description, String controller, Set<String> abis,
                String knownFailure, boolean isBroken, boolean isSuppressed, int timeoutInMinutes) {
            if (timeoutInMinutes < 0) {
                throw new IllegalArgumentException("timeoutInMinutes < 0: " + timeoutInMinutes);
            }
            mName = name;
            mDescription = description;
            mController = controller;
            mAbis = abis;
            mKnownFailure = knownFailure;
            mIsBroken = isBroken;
            mIsSuppressed = isSuppressed;
            mTimeoutInMinutes = timeoutInMinutes;
        }
    }
}
