/*
 * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import javax.tools.*;

import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.JavacTask;
import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.util.List;

public abstract class AbstractTreeScannerTest {

    /**
     * Run the program. A base directory can be provided for file arguments.
     * In jtreg mode, the -r option can be given to change the default base
     * directory to the test root directory. For other options, see usage().
     * @param baseDir base directory for any file arguments.
     * @param args command line args
     * @return true if successful or in gui mode
     */
    boolean run(File baseDir, String... args) {
        if (args.length == 0) {
            usage(System.out);
            return true;
        }

        ArrayList<File> files = new ArrayList<File>();
        for (int i = 0; i < args.length; i++) {
            String arg = args[i];
            if (arg.equals("-q"))
                quiet = true;
            else if (arg.equals("-v"))
                verbose = true;
            else if (arg.equals("-r")) {
                File d = baseDir;
                while (!new File(d, "TEST.ROOT").exists()) {
                    d = d.getParentFile();
                    if (d == null)
                        throw new Error("cannot find TEST.ROOT");
                }
                baseDir = d;
            }
            else if (arg.startsWith("-"))
                throw new Error("unknown option: " + arg);
            else {
                while (i < args.length)
                    files.add(new File(baseDir, args[i++]));
            }
        }

        for (File file: files) {
            if (file.exists())
                test(file);
            else
                error("File not found: " + file);
        }

        if (fileCount != 1)
            System.err.println(fileCount + " files read");
        System.err.println(treeCount + " tree nodes compared");
        if (errors > 0)
            System.err.println(errors + " errors");

        return (errors == 0);
    }

    /**
     * Print command line help.
     * @param out output stream
     */
    void usage(PrintStream out) {
        out.println("Usage:");
        out.println("  java " + getClass().getName() + " options... files...");
        out.println("");
        out.println("where options include:");
        out.println("-q        Quiet: don't report on inapplicable files");
        out.println("-v        Verbose: report on files as they are being read");
        out.println("");
        out.println("files may be directories or files");
        out.println("directories will be scanned recursively");
        out.println("non java files, or java files which cannot be parsed, will be ignored");
        out.println("");
    }

    /**
     * Test a file. If the file is a directory, it will be recursively scanned
     * for java files.
     * @param file the file or directory to test
     */
    void test(File file) {
        if (file.isDirectory()) {
            for (File f: file.listFiles()) {
                test(f);
            }
            return;
        }

        if (file.isFile() && file.getName().endsWith(".java")) {
            try {
                if (verbose)
                    System.err.println(file);
                fileCount++;
                treeCount += test(read(file));
            } catch (ParseException e) {
                if (!quiet) {
                    error("Error parsing " + file + "\n" + e.getMessage());
                }
            } catch (IOException e) {
                error("Error reading " + file + ": " + e);
            }
            return;
        }

        if (!quiet)
            error("File " + file + " ignored");
    }

    abstract int test(JCCompilationUnit t);

    // See CR:  6982992 Tests CheckAttributedTree.java, JavacTreeScannerTest.java, and SourceTreeeScannerTest.java timeout
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    Reporter r = new Reporter(pw);
    JavacTool tool = JavacTool.create();
    StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null);

    /**
     * Read a file.
     * @param file the file to be read
     * @return the tree for the content of the file
     * @throws IOException if any IO errors occur
     * @throws TreePosTest.ParseException if any errors occur while parsing the file
     */
    JCCompilationUnit read(File file) throws IOException, ParseException {
        JavacTool tool = JavacTool.create();
        r.errors = 0;
        Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(file);
        JavacTask task = tool.getTask(pw, fm, r, Collections.<String>emptyList(), null, files);
        Iterable<? extends CompilationUnitTree> trees = task.parse();
        pw.flush();
        if (r.errors > 0)
            throw new ParseException(sw.toString());
        Iterator<? extends CompilationUnitTree> iter = trees.iterator();
        if (!iter.hasNext())
            throw new Error("no trees found");
        JCCompilationUnit t = (JCCompilationUnit) iter.next();
        if (iter.hasNext())
            throw new Error("too many trees found");
        return t;
    }

    /**
     * Report an error. When the program is complete, the program will either
     * exit or throw an Error if any errors have been reported.
     * @param msg the error message
     */
    void error(String msg) {
        System.err.println(msg);
        errors++;
    }

    /**
     * Report an error. When the program is complete, the program will either
     * exit or throw an Error if any errors have been reported.
     * @param msg the error message
     */
    void error(JavaFileObject file, String msg) {
        System.err.println(file.getName() + ": " + msg);
        errors++;
    }

    /**
     *  Report an error for a specific tree node.
     *  @param file the source file for the tree
     *  @param t    the tree node
     *  @param label an indication of the error
     */
    void error(JavaFileObject file, Tree tree, String msg) {
        JCTree t = (JCTree) tree;
        error(file.getName() + ":" + getLine(file, t) + ": " + msg + " " + trim(t, 64));
    }

    /**
     * Get a trimmed string for a tree node, with normalized white space and limited length.
     */
    String trim(Tree tree, int len) {
        JCTree t = (JCTree) tree;
        String s = t.toString().replaceAll("\\s+", " ");
        return (s.length() < len) ? s : s.substring(0, len);
    }

    /** Number of files that have been analyzed. */
    int fileCount;
    /** Number of trees that have been successfully compared. */
    int treeCount;
    /** Number of errors reported. */
    int errors;
    /** Flag: don't report irrelevant files. */
    boolean quiet;
    /** Flag: report files as they are processed. */
    boolean verbose;


    /**
     * Thrown when errors are found parsing a java file.
     */
    private static class ParseException extends Exception {
        ParseException(String msg) {
            super(msg);
        }
    }

    /**
     * DiagnosticListener to report diagnostics and count any errors that occur.
     */
    private static class Reporter implements DiagnosticListener<JavaFileObject> {
        Reporter(PrintWriter out) {
            this.out = out;
        }

        public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
            out.println(diagnostic);
            switch (diagnostic.getKind()) {
                case ERROR:
                    errors++;
            }
        }
        int errors;
        PrintWriter out;
    }

    /**
     * Get the set of fields for a tree node that may contain child tree nodes.
     * These are the fields that are subtypes of JCTree or List.
     * The results are cached, based on the tree's tag.
     */
    Set<Field> getFields(JCTree tree) {
        Set<Field> fields = map.get(tree.getTag());
        if (fields == null) {
            fields = new HashSet<Field>();
            for (Field f: tree.getClass().getFields()) {
                Class<?> fc = f.getType();
                if (JCTree.class.isAssignableFrom(fc) || List.class.isAssignableFrom(fc))
                    fields.add(f);
            }
            map.put(tree.getTag(), fields);
        }
        return fields;
    }
    // where
    Map<JCTree.Tag, Set<Field>> map = new HashMap<JCTree.Tag,Set<Field>>();

    /** Get the line number for the primary position for a tree.
     * The code is intended to be simple, although not necessarily efficient.
     * However, note that a file manager such as JavacFileManager is likely
     * to cache the results of file.getCharContent, avoiding the need to read
     * the bits from disk each time this method is called.
     */
    int getLine(JavaFileObject file, JCTree tree) {
        try {
            CharSequence cs = file.getCharContent(true);
            int line = 1;
            for (int i = 0; i < tree.pos; i++) {
                if (cs.charAt(i) == '\n') // jtreg tests always use Unix line endings
                    line++;
            }
            return line;
        } catch (IOException e) {
            return -1;
        }
    }
}
