/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.maven.plugins.pmd;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import net.sourceforge.pmd.PMDVersion;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.ReportPlugin;
import org.apache.maven.model.Reporting;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.AbstractMavenReport;
import org.apache.maven.reporting.MavenReportException;
import org.apache.maven.toolchain.Toolchain;
import org.apache.maven.toolchain.ToolchainManager;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.PathTool;
import org.codehaus.plexus.util.StringUtils;

/**
 * Base class for the PMD reports.
 *
 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 * @version $Id$
 */
public abstract class AbstractPmdReport extends AbstractMavenReport {
    // ----------------------------------------------------------------------
    // Configurables
    // ----------------------------------------------------------------------

    /**
     * The output directory for the intermediate XML report.
     */
    @Parameter(property = "project.build.directory", required = true)
    protected File targetDirectory;

    /**
     * Set the output format type, in addition to the HTML report. Must be one of: "none", "csv", "xml", "txt" or the
     * full class name of the PMD renderer to use. See the net.sourceforge.pmd.renderers package javadoc for available
     * renderers. XML is produced in any case, since this format is needed
     * for the check goals (pmd:check, pmd:aggregator-check, pmd:cpd-check, pmd:aggregator-cpd-check).
     */
    @Parameter(property = "format", defaultValue = "xml")
    protected String format = "xml";

    /**
     * Link the violation line numbers to the source xref. Links will be created automatically if the jxr plugin is
     * being used.
     */
    @Parameter(property = "linkXRef", defaultValue = "true")
    private boolean linkXRef;

    /**
     * Location of the Xrefs to link to.
     */
    @Parameter(defaultValue = "${project.reporting.outputDirectory}/xref")
    private File xrefLocation;

    /**
     * Location of the Test Xrefs to link to.
     */
    @Parameter(defaultValue = "${project.reporting.outputDirectory}/xref-test")
    private File xrefTestLocation;

    /**
     * A list of files to exclude from checking. Can contain Ant-style wildcards and double wildcards. Note that these
     * exclusion patterns only operate on the path of a source file relative to its source root directory. In other
     * words, files are excluded based on their package and/or class name. If you want to exclude entire source root
     * directories, use the parameter <code>excludeRoots</code> instead.
     *
     * @since 2.2
     */
    @Parameter
    private List<String> excludes;

    /**
     * A list of files to include from checking. Can contain Ant-style wildcards and double wildcards. Defaults to
     * **\/*.java.
     *
     * @since 2.2
     */
    @Parameter
    private List<String> includes;

    /**
     * Specifies the location of the source directories to be used for PMD.
     * Defaults to <code>project.compileSourceRoots</code>.
     * @since 3.7
     */
    @Parameter(defaultValue = "${project.compileSourceRoots}")
    private List<String> compileSourceRoots;

    /**
     * The directories containing the test-sources to be used for PMD.
     * Defaults to <code>project.testCompileSourceRoots</code>
     * @since 3.7
     */
    @Parameter(defaultValue = "${project.testCompileSourceRoots}")
    private List<String> testSourceRoots;

    /**
     * The project source directories that should be excluded.
     *
     * @since 2.2
     */
    @Parameter
    private File[] excludeRoots;

    /**
     * Run PMD on the tests.
     *
     * @since 2.2
     */
    @Parameter(defaultValue = "false")
    protected boolean includeTests;

    /**
     * Whether to build an aggregated report at the root, or build individual reports.
     *
     * @since 2.2
     * @deprecated since 3.15.0 Use the goals <code>pmd:aggregate-pmd</code> and <code>pmd:aggregate-cpd</code>
     * instead.
     */
    @Parameter(property = "aggregate", defaultValue = "false")
    @Deprecated
    protected boolean aggregate;

    /**
     * Whether to include the xml files generated by PMD/CPD in the site.
     *
     * @since 3.0
     */
    @Parameter(defaultValue = "false")
    protected boolean includeXmlInSite;

    /**
     * Skip the PMD/CPD report generation if there are no violations or duplications found. Defaults to
     * <code>false</code>.
     *
     * <p>Note: the default value was changed from <code>true</code> to <code>false</code> with version 3.13.0.
     *
     * @since 3.1
     */
    @Parameter(defaultValue = "false")
    protected boolean skipEmptyReport;

    /**
     * File that lists classes and rules to be excluded from failures.
     * For PMD, this is a properties file. For CPD, this
     * is a text file that contains comma-separated lists of classes
     * that are allowed to duplicate.
     *
     * @since 3.7
     */
    @Parameter(property = "pmd.excludeFromFailureFile", defaultValue = "")
    protected String excludeFromFailureFile;

    /**
     * Redirect PMD log into maven log out.
     * When enabled, the PMD log output is redirected to maven, so that
     * it is visible in the console together with all the other log output.
     * Also, if maven is started with the debug flag (<code>-X</code> or <code>--debug</code>),
     * the PMD logger is also configured for debug.
     *
     * @since 3.9.0
     */
    @Parameter(defaultValue = "true", property = "pmd.showPmdLog")
    protected boolean showPmdLog = true;

    /**
     * <p>
     * Allow for configuration of the jvm used to run PMD via maven toolchains.
     * This permits a configuration where the project is built with one jvm and PMD is executed with another.
     * This overrules the toolchain selected by the maven-toolchain-plugin.
     * </p>
     *
     * <p>Examples:</p>
     * (see <a href="https://maven.apache.org/guides/mini/guide-using-toolchains.html">
     *     Guide to Toolchains</a> for more info)
     *
     * <pre>
     * {@code
     *    <configuration>
     *        ...
     *        <jdkToolchain>
     *            <version>1.11</version>
     *        </jdkToolchain>
     *    </configuration>
     *
     *    <configuration>
     *        ...
     *        <jdkToolchain>
     *            <version>1.8</version>
     *            <vendor>zulu</vendor>
     *        </jdkToolchain>
     *    </configuration>
     *    }
     * </pre>
     *
     * <strong>note:</strong> requires at least Maven 3.3.1
     *
     * @since 3.14.0
     */
    @Parameter
    private Map<String, String> jdkToolchain;

    // ----------------------------------------------------------------------
    // Read-only parameters
    // ----------------------------------------------------------------------

    /**
     * The projects in the reactor for aggregation report.
     */
    @Parameter(property = "reactorProjects", readonly = true)
    protected List<MavenProject> reactorProjects;

    /**
     * The current build session instance. This is used for
     * toolchain manager API calls and for dependency resolver API calls.
     */
    @Parameter(defaultValue = "${session}", required = true, readonly = true)
    protected MavenSession session;

    @Component
    private ToolchainManager toolchainManager;

    /** The files that are being analyzed. */
    protected Map<File, PmdFileInfo> filesToProcess;

    /**
     * {@inheritDoc}
     */
    @Override
    protected MavenProject getProject() {
        return project;
    }

    protected String constructXRefLocation(boolean test) {
        String location = null;
        if (linkXRef) {
            File xrefLoc = test ? xrefTestLocation : xrefLocation;

            String relativePath =
                    PathTool.getRelativePath(outputDirectory.getAbsolutePath(), xrefLoc.getAbsolutePath());
            if (relativePath == null || relativePath.isEmpty()) {
                relativePath = ".";
            }
            relativePath = relativePath + "/" + xrefLoc.getName();
            if (xrefLoc.exists()) {
                // XRef was already generated by manual execution of a lifecycle binding
                location = relativePath;
            } else {
                // Not yet generated - check if the report is on its way
                Reporting reporting = project.getModel().getReporting();
                List<ReportPlugin> reportPlugins =
                        reporting != null ? reporting.getPlugins() : Collections.<ReportPlugin>emptyList();
                for (ReportPlugin plugin : reportPlugins) {
                    String artifactId = plugin.getArtifactId();
                    if ("maven-jxr-plugin".equals(artifactId) || "jxr-maven-plugin".equals(artifactId)) {
                        location = relativePath;
                    }
                }
            }

            if (location == null) {
                getLog().warn("Unable to locate Source XRef to link to - DISABLED");
            }
        }
        return location;
    }

    /**
     * Convenience method to get the list of files where the PMD tool will be executed
     *
     * @return a List of the files where the PMD tool will be executed
     * @throws IOException If an I/O error occurs during construction of the
     *                     canonical pathnames of the files
     */
    protected Map<File, PmdFileInfo> getFilesToProcess() throws IOException {
        if (aggregate && !project.isExecutionRoot()) {
            return Collections.emptyMap();
        }

        if (excludeRoots == null) {
            excludeRoots = new File[0];
        }

        Collection<File> excludeRootFiles = new HashSet<>(excludeRoots.length);

        for (File file : excludeRoots) {
            if (file.isDirectory()) {
                excludeRootFiles.add(file);
            }
        }

        List<PmdFileInfo> directories = new ArrayList<>();

        if (null == compileSourceRoots) {
            compileSourceRoots = project.getCompileSourceRoots();
        }
        if (compileSourceRoots != null) {
            for (String root : compileSourceRoots) {
                File sroot = new File(root);
                if (sroot.exists()) {
                    String sourceXref = constructXRefLocation(false);
                    directories.add(new PmdFileInfo(project, sroot, sourceXref));
                }
            }
        }

        if (null == testSourceRoots) {
            testSourceRoots = project.getTestCompileSourceRoots();
        }
        if (includeTests && testSourceRoots != null) {
            for (String root : testSourceRoots) {
                File sroot = new File(root);
                if (sroot.exists()) {
                    String testXref = constructXRefLocation(true);
                    directories.add(new PmdFileInfo(project, sroot, testXref));
                }
            }
        }
        if (isAggregator()) {
            for (MavenProject localProject : getAggregatedProjects()) {
                List<String> localCompileSourceRoots = localProject.getCompileSourceRoots();
                for (String root : localCompileSourceRoots) {
                    File sroot = new File(root);
                    if (sroot.exists()) {
                        String sourceXref = constructXRefLocation(false);
                        directories.add(new PmdFileInfo(localProject, sroot, sourceXref));
                    }
                }
                if (includeTests) {
                    List<String> localTestCompileSourceRoots = localProject.getTestCompileSourceRoots();
                    for (String root : localTestCompileSourceRoots) {
                        File sroot = new File(root);
                        if (sroot.exists()) {
                            String testXref = constructXRefLocation(true);
                            directories.add(new PmdFileInfo(localProject, sroot, testXref));
                        }
                    }
                }
            }
        }

        String excluding = getExcludes();
        getLog().debug("Exclusions: " + excluding);
        String including = getIncludes();
        getLog().debug("Inclusions: " + including);

        Map<File, PmdFileInfo> files = new TreeMap<>();

        for (PmdFileInfo finfo : directories) {
            getLog().debug("Searching for files in directory "
                    + finfo.getSourceDirectory().toString());
            File sourceDirectory = finfo.getSourceDirectory();
            if (sourceDirectory.isDirectory() && !isDirectoryExcluded(excludeRootFiles, sourceDirectory)) {
                List<File> newfiles = FileUtils.getFiles(sourceDirectory, including, excluding);
                for (File newfile : newfiles) {
                    files.put(newfile.getCanonicalFile(), finfo);
                }
            }
        }

        return files;
    }

    private boolean isDirectoryExcluded(Collection<File> excludeRootFiles, File sourceDirectoryToCheck) {
        boolean returnVal = false;
        for (File excludeDir : excludeRootFiles) {
            try {
                if (sourceDirectoryToCheck
                        .getCanonicalFile()
                        .toPath()
                        .startsWith(excludeDir.getCanonicalFile().toPath())) {
                    getLog().debug("Directory " + sourceDirectoryToCheck.getAbsolutePath()
                            + " has been excluded as it matches excludeRoot "
                            + excludeDir.getAbsolutePath());
                    returnVal = true;
                    break;
                }
            } catch (IOException e) {
                getLog().warn("Error while checking " + sourceDirectoryToCheck + " whether it should be excluded.", e);
            }
        }
        return returnVal;
    }

    /**
     * Gets the comma separated list of effective include patterns.
     *
     * @return The comma separated list of effective include patterns, never <code>null</code>.
     */
    private String getIncludes() {
        Collection<String> patterns = new LinkedHashSet<>();
        if (includes != null) {
            patterns.addAll(includes);
        }
        if (patterns.isEmpty()) {
            patterns.add("**/*.java");
        }
        return StringUtils.join(patterns.iterator(), ",");
    }

    /**
     * Gets the comma separated list of effective exclude patterns.
     *
     * @return The comma separated list of effective exclude patterns, never <code>null</code>.
     */
    private String getExcludes() {
        Collection<String> patterns = new LinkedHashSet<>(FileUtils.getDefaultExcludesAsList());
        if (excludes != null) {
            patterns.addAll(excludes);
        }
        return StringUtils.join(patterns.iterator(), ",");
    }

    protected boolean isXml() {
        return "xml".equals(format);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean canGenerateReport() {
        if (aggregate && !project.isExecutionRoot()) {
            return false;
        }

        if (!isAggregator() && "pom".equalsIgnoreCase(project.getPackaging())) {
            return false;
        }

        // if format is XML, we need to output it even if the file list is empty
        // so the "check" goals can check for failures
        if (isXml()) {
            return true;
        }
        try {
            filesToProcess = getFilesToProcess();
            if (filesToProcess.isEmpty()) {
                return false;
            }
        } catch (IOException e) {
            getLog().error(e);
        }
        return true;
    }

    protected String determineCurrentRootLogLevel() {
        String logLevel = System.getProperty("org.slf4j.simpleLogger.defaultLogLevel");
        if (logLevel == null) {
            logLevel = System.getProperty("maven.logging.root.level");
        }
        if (logLevel == null) {
            // TODO: logback level
            logLevel = "info";
        }
        return logLevel;
    }

    static String getPmdVersion() {
        return PMDVersion.VERSION;
    }

    // TODO remove the part with ToolchainManager lookup once we depend on
    // 3.0.9 (have it as prerequisite). Define as regular component field then.
    protected final Toolchain getToolchain() {
        Toolchain tc = null;

        if (jdkToolchain != null) {
            // Maven 3.3.1 has plugin execution scoped Toolchain Support
            try {
                Method getToolchainsMethod = toolchainManager
                        .getClass()
                        .getMethod("getToolchains", MavenSession.class, String.class, Map.class);

                @SuppressWarnings("unchecked")
                List<Toolchain> tcs =
                        (List<Toolchain>) getToolchainsMethod.invoke(toolchainManager, session, "jdk", jdkToolchain);

                if (tcs != null && !tcs.isEmpty()) {
                    tc = tcs.get(0);
                }
            } catch (NoSuchMethodException
                    | SecurityException
                    | IllegalAccessException
                    | IllegalArgumentException
                    | InvocationTargetException e) {
                // ignore
            }
        }

        if (tc == null) {
            tc = toolchainManager.getToolchainFromBuildContext("jdk", session);
        }

        return tc;
    }

    protected boolean isAggregator() {
        // returning here aggregate for backwards compatibility
        return aggregate;
    }

    // Note: same logic as in m-javadoc-p (MJAVADOC-134)
    protected Collection<MavenProject> getAggregatedProjects() {
        Map<Path, MavenProject> reactorProjectsMap = new HashMap<>();
        for (MavenProject reactorProject : this.reactorProjects) {
            reactorProjectsMap.put(reactorProject.getBasedir().toPath(), reactorProject);
        }

        return modulesForAggregatedProject(project, reactorProjectsMap);
    }

    /**
     * Recursively add the modules of the aggregatedProject to the set of aggregatedModules.
     *
     * @param aggregatedProject the project being aggregated
     * @param reactorProjectsMap map of (still) available reactor projects
     * @throws MavenReportException if any
     */
    private Set<MavenProject> modulesForAggregatedProject(
            MavenProject aggregatedProject, Map<Path, MavenProject> reactorProjectsMap) {
        // Maven does not supply an easy way to get the projects representing
        // the modules of a project. So we will get the paths to the base
        // directories of the modules from the project and compare with the
        // base directories of the projects in the reactor.

        if (aggregatedProject.getModules().isEmpty()) {
            return Collections.singleton(aggregatedProject);
        }

        List<Path> modulePaths = new LinkedList<Path>();
        for (String module : aggregatedProject.getModules()) {
            modulePaths.add(new File(aggregatedProject.getBasedir(), module).toPath());
        }

        Set<MavenProject> aggregatedModules = new LinkedHashSet<>();

        for (Path modulePath : modulePaths) {
            MavenProject module = reactorProjectsMap.remove(modulePath);
            if (module != null) {
                aggregatedModules.addAll(modulesForAggregatedProject(module, reactorProjectsMap));
            }
        }

        return aggregatedModules;
    }
}
