/*
 * Copyright (c) 2016, 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.
 */

package toolbox;

import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.tools.DocumentationTool.DocumentationTask;
import javax.tools.DocumentationTool;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileManager.Location;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;

import jdk.javadoc.internal.api.JavadocTool;

/**
 * A task to configure and run the documentation tool, javadoc.
 */
public class JavadocTask extends AbstractTask<JavadocTask> {
    private boolean includeStandardOptions;
    private List<Path> classpath;
    private List<Path> sourcepath;
    private Path outdir;
    private List<String> options;
    private List<String> classes;
    private List<String> files;
    private List<JavaFileObject> fileObjects;
    private JavaFileManager fileManager;

    private JavadocTool jdtool;
    private StandardJavaFileManager internalFileManager;
    private Class<?> docletClass = null; // use the standard doclet by default

    /**
     * Creates a task to execute {@code javadoc} using API mode.
     * @param toolBox the {@code ToolBox} to use
     */
    public JavadocTask(ToolBox toolBox) {
        super(toolBox, Task.Mode.API);
    }

    /**
     * Creates a task to execute {@code javadoc} in a specified mode.
     * @param toolBox the {@code ToolBox} to use
     * @param mode the mode to be used
     */
    public JavadocTask(ToolBox toolBox, Task.Mode mode) {
        super(toolBox, mode);
    }

    /**
     * Sets the classpath.
     * @param classpath the classpath
     * @return this task object
     */
    public JavadocTask classpath(String classpath) {
        this.classpath = Stream.of(classpath.split(ToolBox.pathSeparator))
                .filter(s -> !s.isEmpty())
                .map(s -> Paths.get(s))
                .collect(Collectors.toList());
        return this;
    }

    /**
     * Sets the classpath.
     * @param classpath the classpath
     * @return this task object
     */
    public JavadocTask classpath(Path... classpath) {
        this.classpath = Arrays.asList(classpath);
        return this;
    }

    /**
     * Sets the classpath.
     * @param classpath the classpath
     * @return this task object
     */
    public JavadocTask classpath(List<Path> classpath) {
        this.classpath = classpath;
        return this;
    }

    /**
     * Sets the sourcepath.
     * @param sourcepath the sourcepath
     * @return this task object
     */
    public JavadocTask sourcepath(String sourcepath) {
        this.sourcepath = Stream.of(sourcepath.split(ToolBox.pathSeparator))
                .filter(s -> !s.isEmpty())
                .map(s -> Paths.get(s))
                .collect(Collectors.toList());
        return this;
    }

    /**
     * Sets the sourcepath.
     * @param sourcepath the sourcepath
     * @return this task object
     */
    public JavadocTask sourcepath(Path... sourcepath) {
        this.sourcepath = Arrays.asList(sourcepath);
        return this;
    }

    /**
     * Sets the sourcepath.
     * @param sourcepath the sourcepath
     * @return this task object
     */
    public JavadocTask sourcepath(List<Path> sourcepath) {
        this.sourcepath = sourcepath;
        return this;
    }

    /**
     * Sets the output directory.
     * @param outdir the output directory
     * @return this task object
     */
    public JavadocTask outdir(String outdir) {
        this.outdir = Paths.get(outdir);
        return this;
    }

    /**
     * Sets the output directory.
     * @param outdir the output directory
     * @return this task object
     */
    public JavadocTask outdir(Path outdir) {
        this.outdir = outdir;
        return this;
    }

    /**
     * Sets the options.
     * @param options the options
     * @return this task object
     */
    public JavadocTask options(String... options) {
        this.options = Arrays.asList(options);
        return this;
    }

    /**
     * Sets the options.
     * @param options the options
     * @return this task object
     */
    public JavadocTask options(List<String> options) {
        this.options = options;
        return this;
    }

    /**
     * Sets the files to be documented.
     * @param files the files
     * @return this task object
     */
    public JavadocTask files(String... files) {
        this.files = Arrays.asList(files);
        return this;
    }

    /**
     * Sets the files to be documented.
     * @param files the files
     * @return this task object
     */
    public JavadocTask files(Path... files) {
        this.files = Stream.of(files)
                .map(Path::toString)
                .collect(Collectors.toList());
        return this;
    }

    /**
     * Sets the files to be documented.
     * @param files the files
     * @return this task object
     */
    public JavadocTask files(List<Path> files) {
        this.files = files.stream()
                .map(Path::toString)
                .collect(Collectors.toList());
        return this;
    }

    /**
     * Sets the sources to be documented.
     * Each source string is converted into an in-memory object that
     * can be passed directly to the tool.
     * @param sources the sources
     * @return this task object
     */
    public JavadocTask sources(String... sources) {
        fileObjects = Stream.of(sources)
                .map(s -> new ToolBox.JavaSource(s))
                .collect(Collectors.toList());
        return this;
    }

    /**
     * Sets the file manager to be used by this task.
     * @param fileManager the file manager
     * @return this task object
     */
    public JavadocTask fileManager(JavaFileManager fileManager) {
        this.fileManager = fileManager;
        return this;
    }

    /**
     * Sets the doclet class to be invoked by javadoc.
     * Note: this is applicable only in API mode.
     * @param docletClass the user specified doclet
     * @return this task object
     */
    public JavadocTask docletClass(Class<?> docletClass) {
        this.docletClass = docletClass;
        return this;
    }

    /**
     * {@inheritDoc}
     * @return the name "javadoc"
     */
    @Override
    public String name() {
        return "javadoc";
    }

    /**
     * Calls the javadoc tool with the arguments as currently configured.
     * @return a Result object indicating the outcome of the execution
     * and the content of any output written to stdout, stderr, or the
     * main stream by the tool.
     */
    @Override
    public Task.Result run() {
        if (mode == Task.Mode.EXEC)
            return runExec();

        AbstractTask.WriterOutput direct = new AbstractTask.WriterOutput();
        // The following are to catch output to System.out and System.err,
        // in case these are used instead of the primary (main) stream
        AbstractTask.StreamOutput sysOut = new AbstractTask.StreamOutput(System.out, System::setOut);
        AbstractTask.StreamOutput sysErr = new AbstractTask.StreamOutput(System.err, System::setErr);
        int rc;
        Map<Task.OutputKind, String> outputMap = new HashMap<>();
        try {
            switch (mode == null ? Task.Mode.API : mode) {
                case API:
                    rc = runAPI(direct.pw);
                    break;
                case CMDLINE:
                    rc = runCommand(direct.pw);
                    break;
                default:
                    throw new IllegalStateException();
            }
        } catch (IOException e) {
            toolBox.out.println("Exception occurred: " + e);
            rc = 99;
        } finally {
            outputMap.put(Task.OutputKind.STDOUT, sysOut.close());
            outputMap.put(Task.OutputKind.STDERR, sysErr.close());
            outputMap.put(Task.OutputKind.DIRECT, direct.close());
        }
        return checkExit(new Task.Result(toolBox, this, rc, outputMap));
    }

    private int runAPI(PrintWriter pw) throws IOException {
        try {
            jdtool = (JavadocTool) ToolProvider.getSystemDocumentationTool();
            jdtool = new JavadocTool();

            if (fileManager == null)
                fileManager = internalFileManager = jdtool.getStandardFileManager(null, null, null);
            if (outdir != null)
                setLocationFromPaths(DocumentationTool.Location.DOCUMENTATION_OUTPUT,
                        Collections.singletonList(outdir));
            if (classpath != null)
                setLocationFromPaths(StandardLocation.CLASS_PATH, classpath);
            if (sourcepath != null)
                setLocationFromPaths(StandardLocation.SOURCE_PATH, sourcepath);
            List<String> allOpts = new ArrayList<>();
            if (options != null)
                allOpts.addAll(options);

            Iterable<? extends JavaFileObject> allFiles = joinFiles(files, fileObjects);
            DocumentationTask task = jdtool.getTask(pw,
                    fileManager,
                    null,  // diagnostic listener; should optionally collect diags
                    docletClass,
                    allOpts,
                    allFiles);
            return ((DocumentationTask) task).call() ? 0 : 1;
        } finally {
            if (internalFileManager != null)
                internalFileManager.close();
        }
    }

    private void setLocationFromPaths(Location location, List<Path> files) throws IOException {
        if (!(fileManager instanceof StandardJavaFileManager))
            throw new IllegalStateException("not a StandardJavaFileManager");
        ((StandardJavaFileManager) fileManager).setLocationFromPaths(location, files);
    }

    private int runCommand(PrintWriter pw) {
        List<String> args = getAllArgs();
        String[] argsArray = args.toArray(new String[args.size()]);
        return jdk.javadoc.internal.tool.Main.execute(argsArray, pw);
    }

    private Task.Result runExec() {
        List<String> args = new ArrayList<>();
        Path javadoc = toolBox.getJDKTool("javadoc");
        args.add(javadoc.toString());
        if (includeStandardOptions) {
            args.addAll(toolBox.split(System.getProperty("test.tool.vm.opts"), " +"));
        }
        args.addAll(getAllArgs());

        String[] argsArray = args.toArray(new String[args.size()]);
        ProcessBuilder pb = getProcessBuilder();
        pb.command(argsArray);
        try {
            return runProcess(toolBox, this, pb.start());
        } catch (IOException | InterruptedException e) {
            throw new Error(e);
        }
    }

    private List<String> getAllArgs() {
        List<String> args = new ArrayList<>();
        if (options != null)
            args.addAll(options);
        if (outdir != null) {
            args.add("-d");
            args.add(outdir.toString());
        }
        if (classpath != null) {
            args.add("-classpath");
            args.add(toSearchPath(classpath));
        }
        if (sourcepath != null) {
            args.add("-sourcepath");
            args.add(toSearchPath(sourcepath));
        }
        if (classes != null)
            args.addAll(classes);
        if (files != null)
            args.addAll(files);

        return args;
    }

    private String toSearchPath(List<Path> files) {
        return files.stream()
            .map(Path::toString)
            .collect(Collectors.joining(ToolBox.pathSeparator));
    }

    private Iterable<? extends JavaFileObject> joinFiles(
            List<String> files, List<JavaFileObject> fileObjects) {
        if (files == null)
            return fileObjects;
        if (internalFileManager == null)
            internalFileManager = jdtool.getStandardFileManager(null, null, null);
        Iterable<? extends JavaFileObject> filesAsFileObjects =
                internalFileManager.getJavaFileObjectsFromStrings(files);
        if (fileObjects == null)
            return filesAsFileObjects;
        List<JavaFileObject> combinedList = new ArrayList<>();
        for (JavaFileObject o : filesAsFileObjects)
            combinedList.add(o);
        combinedList.addAll(fileObjects);
        return combinedList;
    }
}
