package org.apache.maven.plugins.pmd;

/*
 * 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.
 */

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 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;

import net.sourceforge.pmd.PMDVersion;

/**
 * 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 ( StringUtils.isEmpty( relativePath ) )
            {
                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;
    }
}
