package org.apache.maven.plugin.docck;

/*
 * 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.model.ReportPlugin;
import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.Parameter;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.docck.reports.DocumentationReporter;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.project.MavenProject;
import org.apache.maven.tools.plugin.extractor.ExtractionException;
import org.apache.maven.tools.plugin.scanner.MojoScanner;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.ReaderFactory;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

/**
 * Checks a plugin's documentation for the standard minimums.
 *
 * @author jdcasey
 */
@Mojo( name = "check", aggregator = true, defaultPhase = LifecyclePhase.VALIDATE, threadSafe = true )
public class CheckPluginDocumentationMojo
    extends AbstractCheckDocumentationMojo
{

    /**
     * Plexus component that searches for Mojos.
     */
    @Component
    protected MojoScanner mojoScanner;

    // TODO: really a description of length 1 isn't all that helpful...
    private static final int MIN_DESCRIPTION_LENGTH = 1;

    protected void checkPackagingSpecificDocumentation( MavenProject project, DocumentationReporter reporter )
    {
        PluginDescriptor descriptor = new PluginDescriptor();

        try
        {
            mojoScanner.populatePluginDescriptor( project, descriptor );
        }
        catch ( InvalidPluginDescriptorException e )
        {
            reporter.error( "Failed to parse mojo descriptors.\nError: " + e.getMessage() );
            descriptor = null;
        }
        catch ( ExtractionException e )
        {
            reporter.error( "Failed to parse mojo descriptors.\nError: " + e.getMessage() );
            descriptor = null;
        }

        if ( descriptor != null )
        {
            @SuppressWarnings( "unchecked" )
            List<MojoDescriptor> mojos = descriptor.getMojos();

            // ensure that all mojo classes are documented
            if ( mojos != null && !mojos.isEmpty() )
            {
                for ( MojoDescriptor mojo : mojos )
                {
                    String mojoDescription = mojo.getDescription();

                    if ( mojoDescription == null || mojoDescription.trim().length() < MIN_DESCRIPTION_LENGTH )
                    {
                        reporter.error( "Mojo: \'" + mojo.getGoal() + "\' is missing a description." );
                    }

                    @SuppressWarnings( "unchecked" )
                    List<Parameter> params = mojo.getParameters();

                    // ensure that all parameters are documented
                    if ( params != null && !params.isEmpty() )
                    {
                        for ( Parameter param : params )
                        {
                            if ( param.getRequirement() == null && param.isEditable() )
                            {
                                String paramDescription = param.getDescription();

                                if ( paramDescription == null
                                    || paramDescription.trim().length() < MIN_DESCRIPTION_LENGTH )
                                {
                                    reporter.error( "Parameter: \'" + param.getName() + "\' in mojo: \'"
                                        + mojo.getGoal() + "\' is missing a description." );
                                }
                            }
                        }
                    }
                }
            }
        }

        checkConfiguredReportPlugins( project, reporter );

        checkProjectSite( project, reporter );
    }

    protected boolean approveProjectPackaging( String packaging )
    {
        return "maven-plugin".equals( packaging );
    }

    private void checkProjectSite( MavenProject project, DocumentationReporter reporter )
    {
        File projectSiteDirectory = new File( project.getBasedir(), siteDirectory );

        // check for site.xml
        File siteXml = new File( projectSiteDirectory, "site.xml" );

        if ( !siteXml.exists() )
        {
            reporter.error( "site.xml is missing." );
        }
        else
        {
            Reader streamReader = null;
            try
            {
                streamReader = ReaderFactory.newXmlReader( siteXml );

                String siteHtml = IOUtil.toString( streamReader );

                streamReader.close();
                streamReader = null;

                if ( !siteHtml.contains( "href=\"index.html\"" ) )
                {
                    reporter.error( "site.xml is missing the link to: index.html \"Introduction\"." );
                }

                if ( !siteHtml.contains( "href=\"usage.html\"" ) )
                {
                    reporter.error( "site.xml is missing the link to: usage.html \"Usage\"." );
                }

                if ( !siteHtml.contains( "href=\"plugin-info.html\"" ) )
                {
                    reporter.error( "site.xml is missing the link to: plugin-info.html \"Goals\"." );
                }

                if ( !siteHtml.contains( "href=\"faq.html\"" ) )
                {
                    reporter.error( "site.xml is missing the link to: faq.html \"FAQ\"." );
                }
            }
            catch ( IOException e )
            {
                reporter.error( "Unable to read site.xml file: \'" + siteXml.getAbsolutePath() + "\'.\nError: "
                    + e.getMessage() );
            }
            finally
            {
                IOUtil.close( streamReader );
            }
        }

        // check for index.(apt|html|xml)[.vm]
        if ( !findFiles( projectSiteDirectory, "index" ) )
        {
            reporter.error( "There is no \'index\' file in your site directory (in apt|html|xml[.vm] format)." );
        }

        // check for usage.(apt|html|xml)[.vm]
        if ( !findFiles( projectSiteDirectory, "usage" ) )
        {
            reporter.error( "There is no \'usage\' file in your site directory (in apt|html|xml[.vm] format)." );
        }

        // check for **/examples/**.(apt|html|xml)[.vm] or **/example*.(apt|html|xml)[.vm]
        if ( !findFiles( projectSiteDirectory, "**/examples/*" ) && !findFiles( projectSiteDirectory, "**/example*" ) )
        {
            reporter.error( "There are no example files in your site directory (in apt|html|xml[.vm] format)."
                + " They should either be called \'example*.(apt|html|xml)[.vm]\'"
                + " or they should be located in the \'examples\' directory." );
        }

        if ( !findFiles( projectSiteDirectory, "faq" ) )
        {
            reporter.error( "There is no \'faq\' file in your site directory (in apt|fml|html|xml[.vm] format)." );
        }
    }

    /**
     * Checks the project configured plugins if the required report plugins are present.
     *
     * @param project MavenProject to check
     * @param reporter listener
     * @todo maybe this should be checked default for all project?
     */
    private void checkConfiguredReportPlugins( MavenProject project, DocumentationReporter reporter )
    {
        List<String> expectedPlugins = getRequiredPlugins();

        @SuppressWarnings( "unchecked" )
        List<ReportPlugin> reportPlugins = project.getReportPlugins();
        if ( reportPlugins != null && reportPlugins.size() > 0 )
        {
            for ( ReportPlugin plugin : reportPlugins )
            {
                expectedPlugins.remove( plugin.getArtifactId() );
            }
        }
        else
        {
            reporter.error( "pom.xml has no report plugins configured." );
        }

        for ( String expectedPlugin : expectedPlugins )
        {
            reporter.error( "pom.xml is missing the report plugin: " + expectedPlugin + "." );
        }
    }

    /**
     * Returns a List of Strings of required report plugins.
     *
     * @return List of report plugin artifactIds
     */
    private List<String> getRequiredPlugins()
    {
        List<String> list = new ArrayList<String>();

        list.add( "maven-javadoc-plugin" );
        list.add( "maven-jxr-plugin" );

        return list;
    }
}
