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

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