package org.apache.netbeans.nbm;

/*
 * 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.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.DefaultArtifactRepository;
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
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.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Copy;
import org.apache.tools.ant.types.FileSet;
import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.archiver.gzip.GZipArchiver;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.context.Context;
import org.codehaus.plexus.context.ContextException;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
import org.netbeans.nbbuild.MakeUpdateDesc;

/**
 * Create the NetBeans auto update site definition.
 *
 * @author Milos Kleint
 *
 */
@Mojo( name = "autoupdate",
        defaultPhase = LifecyclePhase.PACKAGE,
        aggregator = true,
        requiresDependencyResolution = ResolutionScope.RUNTIME )
public class CreateUpdateSiteMojo
        extends AbstractNbmMojo
        implements Contextualizable
{

    /**
     * output directory.
     */
    @Parameter( required = true, defaultValue = "${project.build.directory}" )
    protected File outputDirectory;
    /**
     * autoupdate site xml file name.
     */
    @Parameter( defaultValue = "updates.xml", property = "maven.nbm.updatesitexml" )
    protected String fileName;
    /**
     * A custom distribution base for the nbms in the update site. If NOT defined, the update site will use a simple
     * relative URL, which is generally what you want. Defining it as "auto" will pick up the distribution URL from each
     * NBM, which is generally wrong. See <code>distributionUrl</code> in nbm mojo for what url will be used in that
     * case.
     * <p/>
     * The value is either a direct http protocol based URL that points to the location under which all nbm files are
     * located, or
     * <p/>
     * allows to create an update site based on maven repository content. The resulting autoupdate site document can be
     * uploaded as tar.gz to repository as well as attached artifact to the 'nbm-application' project.
     * <br/>
     * Format: id::layout::url same as in maven-deploy-plugin
     * <br/>
     * with the 'default' and 'legacy' layouts. (maven2 vs maven1 layout)
     * <br/>
     * If the value doesn't contain :: characters, it's assumed to be the flat structure and the value is just the URL.
     *
     * @since 3.0 it's also possible to add remote repository as base
     */
    @Parameter( defaultValue = ".", property = "maven.nbm.customDistBase" )
    private String distBase;

    /**
     * The Maven Project.
     *
     */
    @Parameter( required = true, readonly = true, property = "project" )
    private MavenProject project;

    /**
     * If the executed project is a reactor project, this will contains the full list of projects in the reactor.
     */
    @Parameter( required = true, readonly = true, defaultValue = "${reactorProjects}" )
    private List reactorProjects;

    /**
     * List of Ant style patterns on artifact GA (groupID:artifactID) that should be included in the update site. Eg.
     * org.netbeans.* matches all artifacts with any groupID starting with 'org.netbeans.', org.*:api will match any
     * artifact with artifactId of 'api' and groupId starting with 'org.'
     *
     * @since 3.14
     */
    @Parameter
    private List<String> updateSiteIncludes;

    // <editor-fold defaultstate="collapsed" desc="Component parameters">
    @Component
    private ArtifactFactory artifactFactory;
    /**
     * Contextualized.
     */
    private PlexusContainer container;
    /**
     * Used for attaching the artifact in the project
     *
     */
    @Component
    private MavenProjectHelper projectHelper;

    @Component
    private ArtifactResolver artifactResolver;

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

    // </editor-fold>
    public void execute()
            throws MojoExecutionException, MojoFailureException
    {
        Project antProject = registerNbmAntTasks();
        File nbmBuildDirFile = new File( outputDirectory, "netbeans_site" );
        if ( !nbmBuildDirFile.exists() )
        {
            nbmBuildDirFile.mkdirs();
        }

        boolean isRepository = false;
        if ( "auto".equals( distBase ) )
        {
            distBase = null;
        }
        ArtifactRepository distRepository = getDeploymentRepository( distBase, container, getLog() );
        String oldDistBase = null;
        if ( distRepository != null )
        {
            isRepository = true;
        }
        else
        {
            if ( distBase != null && !distBase.contains( "::" ) )
            {
                oldDistBase = distBase;
            }
        }

        if ( "nbm-application".equals( project.getPackaging() ) )
        {
            @SuppressWarnings( "unchecked" )
            Set<Artifact> artifacts = project.getArtifacts();
            for ( Artifact art : artifacts )
            {
                if ( !matchesIncludes( art ) )
                {
                    continue;
                }
                ArtifactResult res
                        = turnJarToNbmFile( art, artifactFactory, artifactResolver, project, localRepository );
                if ( res.hasConvertedArtifact() )
                {
                    art = res.getConvertedArtifact();
                }

                if ( art.getType().equals( "nbm-file" ) )
                {
                    Copy copyTask = (Copy) antProject.createTask( "copy" );
                    copyTask.setOverwrite( true );
                    copyTask.setFile( art.getFile() );
                    if ( !isRepository )
                    {
                        copyTask.setFlatten( true );
                        copyTask.setTodir( nbmBuildDirFile );
                    }
                    else
                    {
                        String path = distRepository.pathOf( art );
                        File f = new File( nbmBuildDirFile, path.replace( '/', File.separatorChar ) );
                        copyTask.setTofile( f );
                    }
                    try
                    {
                        copyTask.execute();
                    }
                    catch ( BuildException ex )
                    {
                        throw new MojoExecutionException( "Cannot merge nbm files into autoupdate site", ex );
                    }

                }
                if ( res.isOSGiBundle() )
                {
                    // TODO check for bundles
                }
            }
            getLog().info( "Created NetBeans module cluster(s) at " + nbmBuildDirFile.getAbsoluteFile() );

        }
        else if ( reactorProjects != null && reactorProjects.size() > 0 )
        {

            Iterator it = reactorProjects.iterator();
            while ( it.hasNext() )
            {
                MavenProject proj = (MavenProject) it.next();
                File projOutputDirectory = new File( proj.getBuild().getDirectory() );
                if ( projOutputDirectory != null && projOutputDirectory.exists() )
                {
                    Copy copyTask = (Copy) antProject.createTask( "copy" );
                    if ( !isRepository )
                    {
                        FileSet fs = new FileSet();
                        fs.setDir( projOutputDirectory );
                        fs.createInclude().setName( "*.nbm" );
                        copyTask.addFileset( fs );
                        copyTask.setOverwrite( true );
                        copyTask.setFlatten( true );
                        copyTask.setTodir( nbmBuildDirFile );
                    }
                    else
                    {
                        boolean has = false;
                        File[] fls = projOutputDirectory.listFiles();
                        if ( fls != null )
                        {
                            for ( File fl : fls )
                            {
                                if ( fl.getName().endsWith( ".nbm" ) )
                                {
                                    copyTask.setFile( fl );
                                    has = true;
                                    break;
                                }
                            }
                        }
                        if ( !has )
                        {
                            continue;
                        }
                        Artifact art
                                = artifactFactory.createArtifact( proj.getGroupId(), proj.getArtifactId(), proj.
                                        getVersion(),
                                        null, "nbm-file" );
                        String path = distRepository.pathOf( art );
                        File f = new File( nbmBuildDirFile, path.replace( '/', File.separatorChar ) );
                        copyTask.setTofile( f );
                    }
                    try
                    {
                        copyTask.execute();
                    }
                    catch ( BuildException ex )
                    {
                        throw new MojoExecutionException( "Cannot merge nbm files into autoupdate site", ex );
                    }
                }
            }
        }
        else
        {
            throw new MojoExecutionException(
                    "This goal only makes sense on reactor projects or project with 'nbm-application' packaging." );

        }
        MakeUpdateDesc descTask = (MakeUpdateDesc) antProject.createTask( "updatedist" );
        File xmlFile = new File( nbmBuildDirFile, fileName );
        descTask.setDesc( xmlFile );
        if ( oldDistBase != null )
        {
            descTask.setDistBase( oldDistBase );
        }
        if ( distRepository != null )
        {
            descTask.setDistBase( distRepository.getUrl() );
        }
        FileSet fs = new FileSet();
        fs.setDir( nbmBuildDirFile );
        fs.createInclude().setName( "**/*.nbm" );
        descTask.addFileset( fs );
        try
        {
            descTask.execute();
        }
        catch ( BuildException ex )
        {
            throw new MojoExecutionException( "Cannot create autoupdate site xml file", ex );
        }
        getLog().info( "Generated autoupdate site content at " + nbmBuildDirFile.getAbsolutePath() );

        try
        {
            GZipArchiver gz = new GZipArchiver();
            gz.addFile( xmlFile, fileName );
            File gzipped = new File( nbmBuildDirFile, fileName + ".gz" );
            gz.setDestFile( gzipped );
            gz.createArchive();
            if ( "nbm-application".equals( project.getPackaging() ) )
            {
                projectHelper.attachArtifact( project, "xml.gz", "updatesite", gzipped );
            }
        }
        catch ( Exception ex )
        {
            throw new MojoExecutionException( "Cannot create gzipped version of the update site xml file.", ex );
        }

    }

    private static final Pattern ALT_REPO_SYNTAX_PATTERN = Pattern.compile( "(.+)::(.+)::(.+)" );

    static ArtifactRepository getDeploymentRepository( String distBase, PlexusContainer container, Log log )
            throws MojoExecutionException, MojoFailureException
    {

        ArtifactRepository repo = null;

        if ( distBase != null )
        {

            Matcher matcher = ALT_REPO_SYNTAX_PATTERN.matcher( distBase );

            if ( !matcher.matches() )
            {
                if ( !distBase.contains( "::" ) )
                {
                    //backward compatibility gag.
                    return null;
                }
                throw new MojoFailureException( distBase,
                        "Invalid syntax for repository.",
                        "Invalid syntax for alternative repository. Use \"id::layout::url\"." );
            }
            else
            {
                String id = matcher.group( 1 ).trim();
                String layout = matcher.group( 2 ).trim();
                String url = matcher.group( 3 ).trim();

                ArtifactRepositoryLayout repoLayout;
                try
                {
                    repoLayout = (ArtifactRepositoryLayout) container.lookup( ArtifactRepositoryLayout.ROLE, layout );
                }
                catch ( ComponentLookupException e )
                {
                    throw new MojoExecutionException( "Cannot find repository layout: " + layout, e );
                }

                repo = new DefaultArtifactRepository( id, url, repoLayout );
            }
        }
        return repo;
    }

    @Override
    public void contextualize( Context context )
            throws ContextException
    {
        this.container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
    }

    private boolean matchesIncludes( Artifact art )
    {
        if ( updateSiteIncludes != null )
        {
            String s = art.getGroupId() + ":" + art.getArtifactId();
            for ( String p : updateSiteIncludes )
            {
                //TODO optimize and only do once per execution.
                p = p.replace( ".", "\\." ).replace( "*", ".*" );
                Pattern patt = Pattern.compile( p );
                if ( patt.matcher( s ).matches() )
                {
                    return true;
                }
            }
            return false;
        }
        return true;
    }
}
