/*
 * 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.File;
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.JavaFileManager;
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(File.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(File.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 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(StandardLocation.CLASS_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(StandardLocation 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(File.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;
    }
}
