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.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.ResourceBundle;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.reporting.MavenReportException;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.WriterFactory;

import net.sourceforge.pmd.cpd.CPD;
import net.sourceforge.pmd.cpd.CPDConfiguration;
import net.sourceforge.pmd.cpd.CSVRenderer;
import net.sourceforge.pmd.cpd.EcmascriptLanguage;
import net.sourceforge.pmd.cpd.JSPLanguage;
import net.sourceforge.pmd.cpd.JavaLanguage;
import net.sourceforge.pmd.cpd.JavaTokenizer;
import net.sourceforge.pmd.cpd.Language;
import net.sourceforge.pmd.cpd.LanguageFactory;
import net.sourceforge.pmd.cpd.Match;
import net.sourceforge.pmd.cpd.XMLRenderer;
import net.sourceforge.pmd.cpd.renderer.CPDRenderer;

/**
 * Creates a report for PMD's CPD tool. See
 * <a href="https://pmd.github.io/latest/pmd_userdocs_cpd.html">Finding duplicated code</a>
 * for more details.
 *
 * @author Mike Perham
 * @version $Id$
 * @since 2.0
 */
@Mojo( name = "cpd", threadSafe = true )
public class CpdReport
    extends AbstractPmdReport
{
    /**
     * The programming language to be analyzed by CPD. Valid values are currently <code>java</code>,
     * <code>javascript</code> or <code>jsp</code>.
     *
     * @since 3.5
     */
    @Parameter( defaultValue = "java" )
    private String language;

    /**
     * The minimum number of tokens that need to be duplicated before it causes a violation.
     */
    @Parameter( property = "minimumTokens", defaultValue = "100" )
    private int minimumTokens;

    /**
     * Skip the CPD report generation. Most useful on the command line via "-Dcpd.skip=true".
     *
     * @since 2.1
     */
    @Parameter( property = "cpd.skip", defaultValue = "false" )
    private boolean skip;

    /**
     * If true, CPD ignores literal value differences when evaluating a duplicate block. This means that
     * <code>foo=42;</code> and <code>foo=43;</code> will be seen as equivalent. You may want to run PMD with this
     * option off to start with and then switch it on to see what it turns up.
     *
     * @since 2.5
     */
    @Parameter( property = "cpd.ignoreLiterals", defaultValue = "false" )
    private boolean ignoreLiterals;

    /**
     * Similar to <code>ignoreLiterals</code> but for identifiers; i.e., variable names, methods names, and so forth.
     *
     * @since 2.5
     */
    @Parameter( property = "cpd.ignoreIdentifiers", defaultValue = "false" )
    private boolean ignoreIdentifiers;

    /**
     * If true, CPD ignores annotations.
     *
     * @since 3.11.0
     */
    @Parameter( property = "cpd.ignoreAnnotations", defaultValue = "false" )
    private boolean ignoreAnnotations;

    /** The CPD instance used to analyze the files. Will itself collect the duplicated code matches. */
    private CPD cpd;

    /** Helper to exclude duplications from the result. */
    private final ExcludeDuplicationsFromFile excludeDuplicationsFromFile = new ExcludeDuplicationsFromFile();

    /**
     * {@inheritDoc}
     */
    public String getName( Locale locale )
    {
        return getBundle( locale ).getString( "report.cpd.name" );
    }

    /**
     * {@inheritDoc}
     */
    public String getDescription( Locale locale )
    {
        return getBundle( locale ).getString( "report.cpd.description" );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void executeReport( Locale locale )
        throws MavenReportException
    {
        try
        {
            execute( locale );
        }
        finally
        {
            if ( getSink() != null )
            {
                getSink().close();
            }
        }
    }

    private void execute( Locale locale )
        throws MavenReportException
    {
        if ( !skip && canGenerateReport() )
        {
            ClassLoader origLoader = Thread.currentThread().getContextClassLoader();
            try
            {
                Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader() );

                generateMavenSiteReport( locale );
            }
            finally
            {
                Thread.currentThread().setContextClassLoader( origLoader );
            }

        }
    }

    @Override
    public boolean canGenerateReport()
    {
        if ( skip )
        {
            return false;
        }

        boolean result = super.canGenerateReport();
        if ( result )
        {
            try
            {
                executeCpdWithClassloader();
                if ( skipEmptyReport )
                {
                    result = cpd.getMatches().hasNext();
                    if ( result )
                    {
                        getLog().debug( "Skipping report since skipEmptyReport is true and there are no CPD issues." );
                    }
                }
            }
            catch ( MavenReportException e )
            {
                throw new RuntimeException( e );
            }
        }
        return result;
    }

    private void executeCpdWithClassloader()
        throws MavenReportException
    {
        ClassLoader origLoader = Thread.currentThread().getContextClassLoader();
        try
        {
            Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader() );
            executeCpd();
        }
        finally
        {
            Thread.currentThread().setContextClassLoader( origLoader );
        }
    }

    private void executeCpd()
        throws MavenReportException
    {
        if ( cpd != null )
        {
            // CPD has already been run
            getLog().debug( "CPD has already been run - skipping redundant execution." );
            return;
        }

        setupPmdLogging();

        Properties p = new Properties();
        if ( ignoreLiterals )
        {
            p.setProperty( JavaTokenizer.IGNORE_LITERALS, "true" );
        }
        if ( ignoreIdentifiers )
        {
            p.setProperty( JavaTokenizer.IGNORE_IDENTIFIERS, "true" );
        }
        if ( ignoreAnnotations )
        {
            p.setProperty( JavaTokenizer.IGNORE_ANNOTATIONS, "true" );
        }
        try
        {
            if ( filesToProcess == null )
            {
                filesToProcess = getFilesToProcess();
            }

            try
            {
                excludeDuplicationsFromFile.loadExcludeFromFailuresData( excludeFromFailureFile );
            }
            catch ( MojoExecutionException e )
            {
                throw new MavenReportException( "Error loading exclusions", e );
            }

            String encoding = determineEncoding( !filesToProcess.isEmpty() );
            Language cpdLanguage;
            if ( "java".equals ( language ) || null == language )
            {
                cpdLanguage = new JavaLanguage( p );
            }
            else if ( "javascript".equals( language ) )
            {
                cpdLanguage = new EcmascriptLanguage();
            }
            else if ( "jsp".equals( language ) )
            {
                cpdLanguage = new JSPLanguage();
            }
            else
            {
                cpdLanguage = LanguageFactory.createLanguage( language, p );
            }

            CPDConfiguration cpdConfiguration = new CPDConfiguration();
            cpdConfiguration.setMinimumTileSize( minimumTokens );
            cpdConfiguration.setLanguage( cpdLanguage );
            cpdConfiguration.setSourceEncoding( encoding );

            cpd = new CPD( cpdConfiguration );

            for ( File file : filesToProcess.keySet() )
            {
                cpd.add( file );
            }
        }
        catch ( UnsupportedEncodingException e )
        {
            throw new MavenReportException( "Encoding '" + getSourceEncoding() + "' is not supported.", e );
        }
        catch ( IOException e )
        {
            throw new MavenReportException( e.getMessage(), e );
        }
        getLog().debug( "Executing CPD..." );
        cpd.go();
        getLog().debug( "CPD finished." );

        // always create XML format. we need to output it even if the file list is empty or we have no duplications
        // so the "check" goals can check for violations
        writeXmlReport( cpd );

        // html format is handled by maven site report, xml format as already bean rendered
        if ( !isHtml() && !isXml() )
        {
            writeFormattedReport( cpd );
        }
    }

    private Iterator<Match> filterMatches( Iterator<Match> matches )
    {
        getLog().debug( "Filtering duplications. Using " + excludeDuplicationsFromFile.countExclusions()
            + " configured exclusions." );

        List<Match> filteredMatches = new ArrayList<>();
        int excludedDuplications = 0;
        while ( matches.hasNext() )
        {
            Match match = matches.next();
            if ( excludeDuplicationsFromFile.isExcludedFromFailure( match ) )
            {
                excludedDuplications++;
            }
            else
            {
                filteredMatches.add( match );
            }
        }

        getLog().debug( "Excluded " + excludedDuplications + " duplications." );
        return filteredMatches.iterator();
    }

    private void generateMavenSiteReport( Locale locale )
    {
        CpdReportGenerator gen = new CpdReportGenerator( getSink(), filesToProcess, getBundle( locale ), aggregate );
        Iterator<Match> matches = cpd.getMatches();
        gen.generate( filterMatches( matches ) );
    }

    private String determineEncoding( boolean showWarn )
        throws UnsupportedEncodingException
    {
        String encoding = WriterFactory.FILE_ENCODING;
        if ( StringUtils.isNotEmpty( getSourceEncoding() ) )
        {

            encoding = getSourceEncoding();
            // test encoding as CPD will convert exception into a RuntimeException
            WriterFactory.newWriter( new ByteArrayOutputStream(), encoding );

        }
        else if ( showWarn )
        {
            getLog().warn( "File encoding has not been set, using platform encoding " + WriterFactory.FILE_ENCODING
                               + ", i.e. build is platform dependent!" );
            encoding = WriterFactory.FILE_ENCODING;
        }
        return encoding;
    }

    private void writeFormattedReport( CPD cpd )
        throws MavenReportException
    {
        CPDRenderer r = createRenderer();
        writeReport( cpd, r, format );

    }

    void writeXmlReport( CPD cpd ) throws MavenReportException
    {
        File targetFile = writeReport( cpd, new XMLRenderer( getOutputEncoding() ), "xml" );
        if ( includeXmlInSite )
        {
            File siteDir = getReportOutputDirectory();
            siteDir.mkdirs();
            try
            {
                FileUtils.copyFile( targetFile, new File( siteDir, "cpd.xml" ) );
            }
            catch ( IOException e )
            {
                throw new MavenReportException( e.getMessage(), e );
            }
        }
    }

    private File writeReport( CPD cpd, CPDRenderer r, String extension ) throws MavenReportException
    {
        if ( r == null )
        {
            return null;
        }

        File targetFile = new File( targetDirectory, "cpd." + extension );
        targetDirectory.mkdirs();
        try ( Writer writer = new OutputStreamWriter( new FileOutputStream( targetFile ), getOutputEncoding() ) )
        {
            r.render( filterMatches( cpd.getMatches() ), writer );
            writer.flush();
        }
        catch ( IOException ioe )
        {
            throw new MavenReportException( ioe.getMessage(), ioe );
        }
        return targetFile;
    }

    /**
     * {@inheritDoc}
     */
    public String getOutputName()
    {
        return "cpd";
    }

    private static ResourceBundle getBundle( Locale locale )
    {
        return ResourceBundle.getBundle( "cpd-report", locale, CpdReport.class.getClassLoader() );
    }

    /**
     * Create and return the correct renderer for the output type.
     *
     * @return the renderer based on the configured output
     * @throws org.apache.maven.reporting.MavenReportException if no renderer found for the output type
     */
    public CPDRenderer createRenderer()
        throws MavenReportException
    {
        CPDRenderer renderer = null;
        if ( "xml".equals( format ) )
        {
            renderer = new XMLRenderer( getOutputEncoding() );
        }
        else if ( "csv".equals( format ) )
        {
            renderer = new CSVRenderer();
        }
        else if ( !"".equals( format ) && !"none".equals( format ) )
        {
            try
            {
                renderer = (CPDRenderer) Class.forName( format ).getConstructor().newInstance();
            }
            catch ( Exception e )
            {
                throw new MavenReportException( "Can't find CPD custom format " + format + ": "
                    + e.getClass().getName(), e );
            }
        }

        return renderer;
    }
}
