package org.apache.maven.plugins.dependency;

/*
 * 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.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecution.Source;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.artifact.filter.resolve.AbstractFilter;
import org.apache.maven.shared.artifact.filter.resolve.AndFilter;
import org.apache.maven.shared.artifact.filter.resolve.Node;
import org.apache.maven.shared.artifact.filter.resolve.PatternExclusionsFilter;
import org.apache.maven.shared.artifact.filter.resolve.PatternInclusionsFilter;
import org.apache.maven.shared.artifact.filter.resolve.ScopeFilter;
import org.apache.maven.shared.artifact.filter.resolve.TransformableFilter;
import org.apache.maven.shared.artifact.filter.resolve.transform.ArtifactIncludeFilterTransformer;
import org.apache.maven.shared.transfer.artifact.DefaultArtifactCoordinate;
import org.apache.maven.shared.transfer.artifact.TransferUtils;
import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolver;
import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolverException;
import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult;
import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver;
import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolverException;
import org.apache.maven.shared.utils.logging.MessageBuilder;
import org.apache.maven.shared.utils.logging.MessageUtils;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.StringUtils;

/**
 * When run on a project, remove the project dependencies from the local repository, and optionally re-resolve them.
 * Outside of a project, remove the manually given dependencies.
 *
 * @author jdcasey
 * @since 2.0
 */
@Mojo( name = "purge-local-repository", threadSafe = true, requiresProject = false )
public class PurgeLocalRepositoryMojo
    extends AbstractMojo
{

    private static final String VERSION_FUZZINESS = "version";

    private static final String ARTIFACT_ID_FUZZINESS = "artifactId";

    private static final String GROUP_ID_FUZZINESS = "groupId";

    /**
     * The Maven projects in the reactor.
     */
    @Parameter( defaultValue = "${reactorProjects}", readonly = true, required = true )
    private List<MavenProject> reactorProjects;

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

    @Parameter( defaultValue = "${session}", readonly = true, required = true )
    private MavenSession session;

    /**
     * This mojo execution, used to determine if it was launched from the lifecycle or the command-line.
     */
    @Parameter( defaultValue = "${mojo}", required = true, readonly = true )
    private MojoExecution mojoExecution;

    /**
     * Artifact handler manager.
     */
    @Component
    private ArtifactHandlerManager artifactHandlerManager;

    /**
     * The list of dependencies in the form of groupId:artifactId which should BE deleted/purged from the local
     * repository. Note that using this parameter will deactivate the normal process for purging the current project
     * dependency tree. If this parameter is used, only the included artifacts will be purged. The manualIncludes
     * parameter should not be used in combination with the includes/excludes parameters.
     *
     * @since 2.6
     */
    @Parameter
    private List<String> manualIncludes;

    /**
     * Comma-separated list of groupId:artifactId entries, which should be used to manually include artifacts for
     * deletion. This is a command-line alternative to the <code>manualIncludes</code> parameter, since List parameters
     * are not currently compatible with CLI specification.
     *
     * @since 2.6
     */
    @Parameter( property = "manualInclude" )
    private String manualInclude;

    /**
     * The list of dependencies in the form of groupId:artifactId which should BE deleted/refreshed.
     *
     * @since 2.6
     */
    @Parameter
    private List<String> includes;

    /**
     * Comma-separated list of groupId:artifactId entries, which should be used to include artifacts for
     * deletion/refresh. This is a command-line alternative to the <code>includes</code> parameter, since List
     * parameters are not currently compatible with CLI specification.
     *
     * @since 2.6
     */
    @Parameter( property = "include" )
    private String include;

    /**
     * The list of dependencies in the form of groupId:artifactId which should NOT be deleted/refreshed.
     */
    @Parameter
    private List<String> excludes;

    /**
     * Comma-separated list of groupId:artifactId entries, which should be used to exclude artifacts from
     * deletion/refresh. This is a command-line alternative to the <code>excludes</code> parameter, since List
     * parameters are not currently compatible with CLI specification.
     */
    @Parameter( property = "exclude" )
    private String exclude;

    /**
     * Whether to re-resolve the artifacts once they have been deleted from the local repository. If you are running
     * this mojo from the command-line, you may want to disable this. By default, artifacts will be re-resolved.
     */
    @Parameter( property = "reResolve", defaultValue = "true" )
    private boolean reResolve;

    /**
     * The local repository, from which to delete artifacts.
     */
    @Parameter( defaultValue = "${localRepository}", readonly = true, required = true )
    private ArtifactRepository localRepository;

    /**
     * The dependency resolver
     */
    @Component
    private DependencyResolver dependencyResolver;

    /**
     * The artifact resolver used to re-resolve dependencies, if that option is enabled.
     */
    @Component
    private ArtifactResolver artifactResolver;

    /**
     * Determines how liberally the plugin will delete an artifact from the local repository. Values are: <br/>
     * <ul>
     * <li><b>file</b> - Eliminate only the artifact's file.</li>
     * <li><b>version</b> <i>(default)</i> - Eliminate all files associated with the version of the artifact.</li>
     * <li><b>artifactId</b> - Eliminate all files associated with the artifact's artifactId.</li>
     * <li><b>groupId</b> - Eliminate all files associated with the artifact's groupId.</li>
     * </ul>
     */
    @Parameter( property = "resolutionFuzziness", defaultValue = "version" )
    private String resolutionFuzziness;

    /**
     * Whether this mojo should act on all transitive dependencies. Default value is true.
     */
    @Parameter( property = "actTransitively", defaultValue = "true" )
    private boolean actTransitively;

    /**
     * Whether this plugin should output verbose messages. Default is false.
     */
    @Parameter( property = "verbose", defaultValue = "false" )
    private boolean verbose;

    /**
     * Whether to purge only snapshot artifacts.
     *
     * @since 2.4
     */
    @Parameter( property = "snapshotsOnly", defaultValue = "false" )
    private boolean snapshotsOnly;

    /**
     * Skip plugin execution completely.
     *
     * @since 2.7
     */
    @Parameter( property = "skip", defaultValue = "false" )
    private boolean skip;

    /**
     * Includes only direct project dependencies.
     */
    private class DirectDependencyFilter
        extends AbstractFilter
    {
        private Artifact projectArtifact;

        private List<Dependency> directDependencies;

        /**
         * Default constructor
         *
         * @param directDependencies Set of dependencies objects which represent the direct dependencies of the project
         */
        DirectDependencyFilter( Artifact projectArtifact, List<Dependency> directDependencies )
        {
            this.projectArtifact = projectArtifact;
            this.directDependencies = directDependencies;
        }

        @Override
        public boolean accept( Node node, List<Node> parents )
        {

            if ( artifactsGAMatch( node, projectArtifact.getGroupId(), projectArtifact.getArtifactId() ) )
            {
                return true;
            }
            for ( Dependency dep : directDependencies )
            {
                if ( this.artifactsGAMatch( node, dep.getGroupId(), dep.getArtifactId() ) )
                {
                    return true;
                }
            }
            return false;
        }

        /*
         * Compare the groupId:artifactId of two artifacts.
         */
        private boolean artifactsGAMatch( Node node, String groupId, String artifactId )
        {
            if ( node.getDependency() == null )
            {
                return false;
            }

            if ( !node.getDependency().getGroupId().equals( groupId ) )
            {
                getLog().debug( "Different groupId: " + node.getDependency() + "  " + groupId );
                return false;
            }
            if ( !node.getDependency().getArtifactId().equals( artifactId ) )
            {
                getLog().debug( "Different artifactId: " + node.getDependency() + "  " + artifactId );
                return false;
            }
            return true;
        }
    }

    /**
     * Includes only snapshot artifacts
     */
    private static class SnapshotsFilter
        extends AbstractFilter
    {
        @Override
        public boolean accept( Node node, List<Node> parents )
        {
            if ( node.getDependency() == null )
            {
                return false;
            }
            else
            {
                return ArtifactUtils.isSnapshot( node.getDependency().getVersion() );
            }
        }
    }

    @Override
    public void execute()
        throws MojoExecutionException, MojoFailureException
    {
        if ( isSkip() )
        {
            getLog().info( "Skipping plugin execution" );
            return;
        }

        if ( !StringUtils.isEmpty( manualInclude ) )
        {
            manualIncludes = this.parseIncludes( manualInclude );
        }
        // If it's a manual purge, the only step is to delete from the local repo
        if ( manualIncludes != null && manualIncludes.size() > 0 )
        {
            manualPurge( manualIncludes );
            return;
        }

        Set<Artifact> purgedArtifacts = new HashSet<>();
        if ( shouldPurgeAllProjectsInReactor() )
        {
            for ( MavenProject reactorProject : reactorProjects )
            {
                purgeLocalRepository( reactorProject, purgedArtifacts );
            }
        }
        else
        {
            purgeLocalRepository( project, purgedArtifacts );
        }
    }

    /**
     * Determines if all projects in the reactor should be purged from their dependencies. When this goal is started on
     * the command-line, it is always the case. When it is bound to a phase in the lifecycle, it is never the case.
     *
     * @return <code>true</code> if all projects in the reactor should be purged, <code>false</code> otherwise.
     */
    private boolean shouldPurgeAllProjectsInReactor()
    {
        Source source = mojoExecution.getSource();
        return reactorProjects.size() > 1 && source == Source.CLI;
    }

    /**
     * Purges the local repository for the dependencies in the given Maven project.
     *
     * @param theProject Maven project.
     * @param purgedArtifacts The artifacts that were already purged.
     * @throws MojoFailureException in case of errors during the purge.
     */
    private void purgeLocalRepository( MavenProject theProject, Set<Artifact> purgedArtifacts )
        throws MojoFailureException
    {
        List<Dependency> dependencies = theProject.getDependencies();

        TransformableFilter dependencyFilter = createPurgeArtifactsFilter( theProject, dependencies, purgedArtifacts );

        Set<Artifact> resolvedArtifactsToPurge =
            getFilteredResolvedArtifacts( theProject, dependencies, dependencyFilter );

        if ( resolvedArtifactsToPurge.isEmpty() )
        {
            getLog().info( "No artifacts included for purge for project: " + getProjectKey( theProject ) );
            return;
        }

        purgeArtifacts( theProject, resolvedArtifactsToPurge );
        purgedArtifacts.addAll( resolvedArtifactsToPurge );

        if ( reResolve )
        {
            getLog().info( "Re-resolving dependencies" );
            ArtifactFilter artifactFilter = dependencyFilter.transform( new ArtifactIncludeFilterTransformer() );
            try
            {
                reResolveArtifacts( theProject, resolvedArtifactsToPurge, artifactFilter );
            }
            catch ( ArtifactResolutionException | ArtifactNotFoundException e )
            {
                String failureMessage = "Failed to refresh project dependencies for: " + theProject.getId();
                throw new MojoFailureException( failureMessage, e );
            }
        }
    }

    /**
     * Purge/Delete artifacts from the local repository according to the given patterns.
     *
     * @param theIncludes The includes.
     * @throws MojoExecutionException in case of an error.
     */
    private void manualPurge( List<String> theIncludes )
        throws MojoExecutionException
    {
        MessageBuilder messageBuilder = MessageUtils.buffer();

        getLog().info( messageBuilder.a( "Deleting " ).strong( theIncludes.size() )
            .a( " manual " )
            .a( theIncludes.size() != 1 ? "dependencies" : "dependency" )
            .a( " from " )
            .strong( localRepository.getBasedir() )
            .toString() );

        for ( String gavPattern : theIncludes )
        {
            if ( StringUtils.isEmpty( gavPattern ) )
            {
                getLog().debug( "Skipping empty gav pattern" );
                continue;
            }

            String relativePath = gavToPath( gavPattern );
            if ( StringUtils.isEmpty( relativePath ) )
            {
                getLog().debug( "Skipping empty relative path for gav pattern: " + gavPattern );
                continue;
            }

            File purgeDir = new File( localRepository.getBasedir(), relativePath );
            if ( purgeDir.exists() )
            {
                getLog().debug( "Deleting directory: " + purgeDir );
                try
                {
                    FileUtils.deleteDirectory( purgeDir );
                }
                catch ( IOException e )
                {
                    throw new MojoExecutionException( "Unable to purge directory: " + purgeDir );
                }
            }
            else
            {
                getLog().debug( "Directory: " + purgeDir + " doesn't exist" );
            }
        }
    }

    /**
     * Convert a groupId:artifactId:version to a file system path
     *
     * @param gav, the groupId:artifactId:version string
     * @return the corresponding path
     */
    private String gavToPath( String gav )
    {
        if ( StringUtils.isEmpty( gav ) )
        {
            return null;
        }

        String[] pathComponents = gav.split( ":" );

        StringBuilder path = new StringBuilder( pathComponents[0].replace( '.', '/' ) );

        for ( int i = 1; i < pathComponents.length; ++i )
        {
            path.append( "/" ).append( pathComponents[i] );
        }

        return path.toString();
    }

    /**
     * Create the includes exclude filter to use when resolving and purging dependencies Also excludes any "system"
     * scope dependencies
     *
     * @param theProject The Maven project.
     * @param dependencies The dependencies to use as a reference if we're excluding transitive dependencies
     * @param purgedArtifacts The artifacts already purged.
     * @return the created filter
     */
    private TransformableFilter createPurgeArtifactsFilter( MavenProject theProject, List<Dependency> dependencies,
                                                            Set<Artifact> purgedArtifacts )
    {
        List<TransformableFilter> subFilters = new ArrayList<>();

        // System dependencies should never be purged
        subFilters.add( ScopeFilter.excluding( Artifact.SCOPE_SYSTEM ) );

        if ( this.snapshotsOnly )
        {
            subFilters.add( new SnapshotsFilter() );
        }

        // The CLI includes/excludes overrides configuration in the pom
        if ( !StringUtils.isEmpty( this.include ) )
        {
            this.includes = parseIncludes( this.include );
        }
        if ( this.includes != null )
        {
            subFilters.add( new PatternInclusionsFilter( includes ) );
        }

        if ( !StringUtils.isEmpty( this.exclude ) )
        {
            this.excludes = parseIncludes( this.exclude );
        }
        if ( this.excludes != null )
        {
            subFilters.add( new PatternExclusionsFilter( excludes ) );
        }

        if ( !actTransitively )
        {
            subFilters.add( new DirectDependencyFilter( theProject.getArtifact(), dependencies ) );
        }

        List<String> exclusions = new ArrayList<>( reactorProjects.size() );
        // It doesn't make sense to include projects from the reactor here since they're likely not able to be resolved
        for ( MavenProject reactorProject : reactorProjects )
        {
            exclusions.add( toPatternExcludes( reactorProject.getArtifact() ) );
        }
        // There is no need to consider a second time artifacts that were already purged (re-resolved or not)
        for ( Artifact purgedArtifact : purgedArtifacts )
        {
            exclusions.add( toPatternExcludes( purgedArtifact ) );
        }
        subFilters.add( new PatternExclusionsFilter( exclusions ) );

        return new AndFilter( subFilters );
    }

    /**
     * Returns a string that represents a pattern for an exclude filter for the given artifact.
     *
     * @param artifact Artifact.
     * @return String representation of a pattern for an exclude filter for the given artifact.
     */
    private String toPatternExcludes( Artifact artifact )
    {
        return artifact.getGroupId() + ":" + artifact.getArtifactId() + ":"
            + artifact.getArtifactHandler().getExtension() + ":" + artifact.getVersion();
    }

    /**
     * Convert comma separated list of includes to List object
     *
     * @param theInclude The list of includes
     * @return the includes list
     */
    private List<String> parseIncludes( String theInclude )
    {
        List<String> theIncludes = new ArrayList<>();

        if ( theInclude != null )
        {
            String[] elements = theInclude.split( "," );
            theIncludes.addAll( Arrays.asList( elements ) );
        }

        return theIncludes;
    }

    private Set<Artifact> getFilteredResolvedArtifacts( MavenProject theProject, List<Dependency> dependencies,
                                                        TransformableFilter filter )
    {
        try
        {
            Iterable<ArtifactResult> results =
                dependencyResolver.resolveDependencies( session.getProjectBuildingRequest(), theProject.getModel(),
                                                        filter );

            Set<Artifact> resolvedArtifacts = new LinkedHashSet<>();

            for ( ArtifactResult artResult : results )
            {
                resolvedArtifacts.add( artResult.getArtifact() );
            }

            return resolvedArtifacts;
        }
        catch ( DependencyResolverException e )
        {
            getLog().info( "Unable to resolve all dependencies for: " + getProjectKey( theProject )
                + ". Falling back to non-transitive mode for initial artifact resolution." );
        }

        Set<Artifact> resolvedArtifacts = new LinkedHashSet<>();

        ArtifactFilter artifactFilter = filter.transform( new ArtifactIncludeFilterTransformer() );

        for ( Dependency dependency : dependencies )
        {
            DefaultArtifactCoordinate coordinate = new DefaultArtifactCoordinate();
            coordinate.setGroupId( dependency.getGroupId() );
            coordinate.setArtifactId( dependency.getArtifactId() );
            coordinate.setVersion( dependency.getVersion() );
            coordinate.setExtension( artifactHandlerManager.getArtifactHandler( dependency.getType() ).getExtension() );
            try
            {
                Artifact artifact =
                    artifactResolver.resolveArtifact( session.getProjectBuildingRequest(), coordinate ).getArtifact();
                if ( artifactFilter.include( artifact ) )
                {
                    resolvedArtifacts.add( artifact );
                }
            }
            catch ( ArtifactResolverException e )
            {
                getLog().debug( "Unable to resolve artifact: " + coordinate );
            }
        }
        return resolvedArtifacts;
    }

    private void purgeArtifacts( MavenProject theProject, Set<Artifact> artifacts )
        throws MojoFailureException
    {
        MessageBuilder messageBuilder = MessageUtils.buffer();

        getLog().info( messageBuilder.a( "Deleting " ).strong( artifacts.size() )
            .a( " " ).strong( actTransitively ? "transitive" : "direct" )
            .a( artifacts.size() != 1 ? " dependencies" : " dependency" )
            .a( " for project " ).strong( getProjectKey( theProject ) )
            .a( " from " ).strong( localRepository.getBasedir() )
            .a( " with artifact " ).strong( resolutionFuzziness ).a( " resolution fuzziness" )
            .toString() );

        for ( Artifact artifact : artifacts )
        {
            verbose( "Purging artifact: " + artifact.getId() );

            File deleteTarget = findDeleteTarget( artifact );

            verbose( "Deleting: " + deleteTarget );

            if ( deleteTarget.isDirectory() )
            {
                try
                {
                    FileUtils.deleteDirectory( deleteTarget );
                }
                catch ( IOException e )
                {
                    getLog().warn( "Unable to purge local repository location: " + deleteTarget, e );
                }
            }
            else
            {
                if ( !deleteTarget.delete() )
                {
                    deleteTarget.deleteOnExit();
                    getLog().warn( "Unable to purge local repository location immediately: " + deleteTarget );
                }
            }
            artifact.setResolved( false );
        }
    }

    private void reResolveArtifacts( MavenProject theProject, Set<Artifact> artifacts, ArtifactFilter filter )
        throws ArtifactResolutionException, ArtifactNotFoundException
    {
        // Always need to re-resolve the poms in case they were purged along with the artifact
        // because Maven 2 will not automatically re-resolve them when resolving the artifact
        for ( Artifact artifact : artifacts )
        {
            verbose( "Resolving artifact: " + artifact.getId() );

            try
            {
                //CHECKSTYLE_OFF: LineLength
                artifactResolver.resolveArtifact( session.getProjectBuildingRequest(),
                                                  TransferUtils.toArtifactCoordinate( artifact ) );
                //CHECKSTYLE_ON: LineLength
            }
            catch ( ArtifactResolverException e )
            {
                verbose( e.getMessage() );
            }
        }

        List<Artifact> missingArtifacts = new ArrayList<>();

        for ( Artifact artifact : artifacts )
        {
            try
            {
                artifactResolver.resolveArtifact( session.getProjectBuildingRequest(), artifact );
            }
            catch ( ArtifactResolverException e )
            {
                verbose( e.getMessage() );
                missingArtifacts.add( artifact );
            }
        }

        if ( missingArtifacts.size() > 0 )
        {
            StringBuilder message = new StringBuilder( "required artifacts missing:" );
            message.append( System.lineSeparator() );
            for ( Artifact missingArtifact : missingArtifacts )
            {
                message.append( "  " ).append( missingArtifact.getId() ).append( System.lineSeparator() );
            }
            message.append( System.lineSeparator() );
            message.append( "for the artifact:" );

            throw new ArtifactResolutionException( message.toString(), theProject.getArtifact(),
                                                   theProject.getRemoteArtifactRepositories() );
        }
    }

    private File findDeleteTarget( Artifact artifact )
    {
        // Use localRepository.pathOf() in case artifact.getFile() is not set
        File deleteTarget = new File( localRepository.getBasedir(), localRepository.pathOf( artifact ) );

        if ( GROUP_ID_FUZZINESS.equals( resolutionFuzziness ) )
        {
            // get the groupId dir.
            deleteTarget = deleteTarget.getParentFile().getParentFile().getParentFile();
        }
        else if ( ARTIFACT_ID_FUZZINESS.equals( resolutionFuzziness ) )
        {
            // get the artifactId dir.
            deleteTarget = deleteTarget.getParentFile().getParentFile();
        }
        else if ( VERSION_FUZZINESS.equals( resolutionFuzziness ) )
        {
            // get the version dir.
            deleteTarget = deleteTarget.getParentFile();
        }
        // else it's file fuzziness.
        return deleteTarget;
    }

    private void verbose( String message )
    {
        if ( verbose || getLog().isDebugEnabled() )
        {
            getLog().info( message );
        }
    }

    private String getProjectKey( MavenProject project )
    {
        return project.getArtifactId();
    }

    /**
     * @return {@link #skip}
     */
    public boolean isSkip()
    {
        return skip;
    }

    /**
     * @param skip {@link #skip}
     */
    public void setSkip( boolean skip )
    {
        this.skip = skip;
    }
}
