package org.apache.maven.reporting;

/*
 * 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 org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.doxia.sink.SinkFactory;
import org.apache.maven.doxia.site.decoration.DecorationModel;
import org.apache.maven.doxia.site.decoration.Skin;
import org.apache.maven.doxia.siterenderer.Renderer;
import org.apache.maven.doxia.siterenderer.RendererException;
import org.apache.maven.doxia.siterenderer.RenderingContext;
import org.apache.maven.doxia.siterenderer.SiteRenderingContext;
import org.apache.maven.doxia.siterenderer.sink.SiteRendererSink;
import org.apache.maven.doxia.tools.SiteTool;
import org.apache.maven.doxia.tools.SiteToolException;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.utils.WriterFactory;
import org.codehaus.plexus.util.ReaderFactory;

import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * The basis for a Maven report which can be generated both as part of a site generation or
 * as a direct standalone goal invocation.
 * Both invocations are delegated to <code>abstract executeReport( Locale )</code> from:
 * <ul>
 * <li>Mojo's <code>execute()</code> method, see maven-plugin-api</li>
 * <li>MavenMultiPageReport's <code>generate( Sink, SinkFactory, Locale )</code>, see maven-reporting-api</li>
 * </ul>
 *
 * @author <a href="evenisse@apache.org">Emmanuel Venisse</a>
 * @since 2.0
 * @see #execute() <code>Mojo.execute()</code>, from maven-plugin-api
 * @see #generate(Sink, SinkFactory, Locale) <code>MavenMultiPageReport.generate( Sink, SinkFactory, Locale )</code>,
 *  from maven-reporting-api
 * @see #executeReport(Locale) <code>abstract executeReport( Locale )</code>
 */
public abstract class AbstractMavenReport
    extends AbstractMojo
    implements MavenMultiPageReport
{
    /**
     * The output directory for the report. Note that this parameter is only evaluated if the goal is run directly from
     * the command line. If the goal is run indirectly as part of a site generation, the output directory configured in
     * the Maven Site Plugin is used instead.
     */
    @Parameter( defaultValue = "${project.reporting.outputDirectory}", readonly = true, required = true )
    protected File outputDirectory;

    /**
     * The Maven Project.
     */
    @Parameter( defaultValue = "${project}", readonly = true, required = true )
    protected MavenProject project;

    /**
     * Specifies the input encoding.
     */
    @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}", readonly = true )
    private String inputEncoding;

    /**
     * Specifies the output encoding.
     */
    @Parameter( property = "outputEncoding", defaultValue = "${project.reporting.outputEncoding}", readonly = true )
    private String outputEncoding;

    /**
     * The local repository.
     */
    @Parameter( defaultValue = "${localRepository}", readonly = true, required = true )
    protected ArtifactRepository localRepository;

    /**
     * Remote repositories used for the project.
     */
    @Parameter( defaultValue = "${project.remoteArtifactRepositories}", readonly = true, required = true )
    protected List<ArtifactRepository> remoteRepositories;

    /**
     * The skin to use when the report generation is invoked directly as a standalone Mojo.
     * <p>
     * <b>Default value is</b>:
     * <pre>
     * &lt;skin&gt;
     *   &lt;groupId&gt;org.apache.maven.skins&lt;/groupId&gt;
     *   &lt;artifactId&gt;maven-fluido-skin&lt;/artifactId&gt;
     *   &lt;version&gt;1.11.1&lt;/version&gt;
     * &lt;/skin&gt;
     * </pre>
     *
     * @see Skin
     */
    @Parameter
    protected Skin skin;

    /**
     * SiteTool.
     */
    @Component
    protected SiteTool siteTool;

    /**
     * Doxia Site Renderer component.
     */
    @Component
    protected Renderer siteRenderer;

    /** The current sink to use */
    private Sink sink;

    /** The sink factory to use */
    private SinkFactory sinkFactory;

    /** The current report output directory to use */
    private File reportOutputDirectory;

    /**
     * This method is called when the report generation is invoked directly as a standalone Mojo.
     *
     * @throws MojoExecutionException if an error occurs when generating the report
     * @see org.apache.maven.plugin.Mojo#execute()
     */
    @Override
    public void execute()
        throws MojoExecutionException
    {
        if ( !canGenerateReport() )
        {
            return;
        }

        File outputDirectory = new File( getOutputDirectory() );

        String filename = getOutputName() + ".html";

        Locale locale = Locale.getDefault();

        try
        {
            SiteRenderingContext siteContext = createSiteRenderingContext( locale );

            // copy resources
            getSiteRenderer().copyResources( siteContext, outputDirectory );

            // TODO Replace null with real value
            RenderingContext docRenderingContext = new RenderingContext( outputDirectory, filename, null );

            SiteRendererSink sink = new SiteRendererSink( docRenderingContext );

            generate( sink, null, locale );

            if ( !isExternalReport() ) // MSHARED-204: only render Doxia sink if not an external report
            {
                outputDirectory.mkdirs();

                try ( Writer writer =
                      new OutputStreamWriter( new FileOutputStream( new File( outputDirectory, filename ) ),
                                              getOutputEncoding() ) )
                {
                    // render report
                    getSiteRenderer().mergeDocumentIntoSite( writer, sink, siteContext );
                }
            }

            // copy generated resources also
            getSiteRenderer().copyResources( siteContext, outputDirectory );
        }
        catch ( RendererException | IOException | MavenReportException e )
        {
            throw new MojoExecutionException(
                "An error has occurred in " + getName( Locale.ENGLISH ) + " report generation.", e );
        }
    }

    private SiteRenderingContext createSiteRenderingContext( Locale locale )
        throws MavenReportException, IOException
    {
        DecorationModel decorationModel = new DecorationModel();
        decorationModel.setSkin( getSkin() );

        Map<String, Object> templateProperties = new HashMap<>();
        // We tell the skin that we are rendering in standalone mode
        templateProperties.put( "standalone", Boolean.TRUE );
        templateProperties.put( "project", getProject() );
        templateProperties.put( "inputEncoding", getInputEncoding() );
        templateProperties.put( "outputEncoding", getOutputEncoding() );
        // Put any of the properties in directly into the Velocity context
        for ( Map.Entry<Object, Object> entry : getProject().getProperties().entrySet() )
        {
            templateProperties.put( (String) entry.getKey(), entry.getValue() );
        }

        SiteRenderingContext context;
        try
        {
            Artifact skinArtifact =
                siteTool.getSkinArtifactFromRepository( localRepository, remoteRepositories, decorationModel );

            getLog().info( buffer().a( "Rendering content with " ).strong( skinArtifact.getId()
                + " skin" ).a( '.' ).toString() );

            context = siteRenderer.createContextForSkin( skinArtifact, templateProperties, decorationModel,
                                                         project.getName(), locale );
        }
        catch ( SiteToolException e )
        {
            throw new MavenReportException( "Failed to retrieve skin artifact", e );
        }
        catch ( RendererException e )
        {
            throw new MavenReportException( "Failed to create context for skin", e );
        }

        // Generate static site
        context.setRootDirectory( project.getBasedir() );

        return context;
    }

    /**
     * Generate a report.
     *
     * @param sink the sink to use for the generation.
     * @param locale the wanted locale to generate the report, could be null.
     * @throws MavenReportException if any
     * @deprecated use {@link #generate(Sink, SinkFactory, Locale)} instead.
     */
    @Deprecated
    @Override
    public void generate( Sink sink, Locale locale )
        throws MavenReportException
    {
        generate( sink, null, locale );
    }

    /**
     * This method is called when the report generation is invoked by maven-site-plugin.
     *
     * @param sink
     * @param sinkFactory
     * @param locale
     * @throws MavenReportException
     */
    @Override
    public void generate( Sink sink, SinkFactory sinkFactory, Locale locale )
        throws MavenReportException
    {
        if ( !canGenerateReport() )
        {
            getLog().info( "This report cannot be generated as part of the current build. "
                           + "The report name should be referenced in this line of output." );
            return;
        }

        this.sink = sink;

        this.sinkFactory = sinkFactory;

        executeReport( locale );

        closeReport();
    }

    /**
     * @return CATEGORY_PROJECT_REPORTS
     */
    @Override
    public String getCategoryName()
    {
        return CATEGORY_PROJECT_REPORTS;
    }

    @Override
    public File getReportOutputDirectory()
    {
        if ( reportOutputDirectory == null )
        {
            reportOutputDirectory = new File( getOutputDirectory() );
        }

        return reportOutputDirectory;
    }

    @Override
    public void setReportOutputDirectory( File reportOutputDirectory )
    {
        this.reportOutputDirectory = reportOutputDirectory;
        this.outputDirectory = reportOutputDirectory;
    }

    protected String getOutputDirectory()
    {
        return outputDirectory.getAbsolutePath();
    }

    protected MavenProject getProject()
    {
        return project;
    }

    protected Renderer getSiteRenderer()
    {
        return siteRenderer;
    }

    /**
     * Gets the input files encoding.
     *
     * @return The input files encoding, never <code>null</code>.
     */
    protected String getInputEncoding()
    {
        return ( inputEncoding == null ) ? ReaderFactory.FILE_ENCODING : inputEncoding;
    }

    /**
     * Gets the effective reporting output files encoding.
     *
     * @return The effective reporting output file encoding, never <code>null</code>.
     */
    protected String getOutputEncoding()
    {
        return ( outputEncoding == null ) ? WriterFactory.UTF_8 : outputEncoding;
    }

    /**
     * Gets the skin
     *
     * @return the skin for this standalone report
     */
    protected Skin getSkin()
    {
        if ( skin == null )
        {
            Skin skin = new Skin();
            skin.setGroupId( "org.apache.maven.skins" );
            skin.setArtifactId( "maven-fluido-skin" );
            skin.setVersion( "1.11.1" );
            return skin;
        }
        else
        {
            return skin;
        }
    }

    /**
     * Actions when closing the report.
     */
    protected void closeReport()
    {
        getSink().close();
    }

    /**
     * @return the sink used
     */
    public Sink getSink()
    {
        return sink;
    }

    /**
     * @return the sink factory used
     */
    public SinkFactory getSinkFactory()
    {
        return sinkFactory;
    }

    /**
     * @see org.apache.maven.reporting.MavenReport#isExternalReport()
     * @return {@code false} by default.
     */
    @Override
    public boolean isExternalReport()
    {
        return false;
    }

    @Override
    public boolean canGenerateReport()
    {
        return true;
    }

    /**
     * Execute the generation of the report.
     *
     * @param locale the wanted locale to return the report's description, could be <code>null</code>.
     * @throws MavenReportException if any
     */
    protected abstract void executeReport( Locale locale )
        throws MavenReportException;
}
