package org.apache.maven.shared.dependency.graph.internal;

/*
 * 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.factory.ArtifactFactory;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.project.DefaultDependencyResolutionRequest;
import org.apache.maven.project.DependencyResolutionException;
import org.apache.maven.project.DependencyResolutionRequest;
import org.apache.maven.project.DependencyResolutionResult;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.project.ProjectDependenciesResolver;
import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
import org.apache.maven.shared.dependency.graph.DependencyNode;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.sonatype.aether.graph.Dependency;
import org.sonatype.aether.version.VersionConstraint;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Wrapper around Maven 3 dependency resolver.
 *
 * @see ProjectDependenciesResolver
 * @author Hervé Boutemy
 * @since 2.0
 */
@Component( role = DependencyGraphBuilder.class, hint = "maven3" )
public class Maven3DependencyGraphBuilder
    extends AbstractLogEnabled
    implements DependencyGraphBuilder
{
    @Requirement
    private ProjectDependenciesResolver resolver;

    @Requirement
    private ArtifactFactory factory;

    private final Invoker invoker = new Invoker();

    /**
     * Builds the dependency graph for Maven 3.
     *
     * @param project the project
     * @param filter artifact filter (can be <code>null</code>)
     * @return DependencyNode containing the dependency graph.
     * @throws DependencyGraphBuilderException if some of the dependencies could not be resolved.
     */
    public DependencyNode buildDependencyGraph( MavenProject project, ArtifactFilter filter )
        throws DependencyGraphBuilderException
    {
        return buildDependencyGraph( project, filter, Collections.EMPTY_LIST );
    }

    /**
     * Builds the dependency graph for Maven 3 including any dependencies from any projects in the reactor.
     *
     * @param project the project
     * @param filter artifact filter (can be <code>null</code>)
     * @param reactorProjects Collection of those projects contained in the reactor.
     * @return DependencyNode containing the dependency graph.
     * @throws DependencyGraphBuilderException if some of the dependencies could not be resolved.
     */
    public DependencyNode buildDependencyGraph( MavenProject project, ArtifactFilter filter,
                                                Collection<MavenProject> reactorProjects )
        throws DependencyGraphBuilderException
    {
        ProjectBuildingRequest projectBuildingRequest =
            (ProjectBuildingRequest) invoke( project, "getProjectBuildingRequest" );

        DependencyResolutionRequest request =
            new DefaultDependencyResolutionRequest( project, projectBuildingRequest.getRepositorySession() );

        final DependencyResolutionResult result = resolveDependencies( request, reactorProjects );

        return buildDependencyNode( null, result.getDependencyGraph(), project.getArtifact(), filter );
    }

    private DependencyResolutionResult resolveDependencies( DependencyResolutionRequest request,
                                                            Collection<MavenProject> reactorProjects )
        throws DependencyGraphBuilderException
    {
        try
        {
            return resolver.resolve( request );
        }
        catch ( DependencyResolutionException e )
        {
            // Ignore any resolution failure for deps that are part of the reactor but have not yet been built.
            // NB Typing has been removed because DependencyResolutionResult returns Sonatype aether in 3.0.4 and
            // Eclipse aether in 3.1.1 and while dep-tree is a single module we can only compile against one of them.
            //
            // NB While applying this code to Maven3DependencyGraphBuilder is trivial it won't work because
            // in Maven 3, MavenProject.getProjectReferences isn't populated. So we would need to have the reactor
            // modules passed in separately which would change the API for DependencyGraphBuilder. If
            // MavenProject.getProjectReferences were populated (like it should be) then this would work for Maven3 too.
            //
            // NB There doesn't seem to be any way to apply this to Maven2DependencyGraphBuilder as there is no
            // concept of partial resolution like there is is 3 and 3.1
            final DependencyResolutionResult result = e.getResult();
            final List<Dependency> reactorDeps =
                getReactorDependencies( reactorProjects, result.getUnresolvedDependencies() );
            invoker.invoke( result.getUnresolvedDependencies(), "removeAll", Collection.class, reactorDeps );
            invoker.invoke( result.getResolvedDependencies(), "addAll", Collection.class, reactorDeps );

            if ( !result.getUnresolvedDependencies().isEmpty() )
            {
                throw new DependencyGraphBuilderException( "Could not resolve the following dependencies : "
                    + result.getUnresolvedDependencies(), e );
            }
            getLogger().debug( "Resolved dependencies after ignoring reactor dependencies : " + reactorDeps );
            return result;
        }
    }

    private List<org.sonatype.aether.graph.Dependency> getReactorDependencies( Collection<MavenProject> reactorProjects,
                                                                               List<?> dependencies )
    {
        // Create ProjectMap
        final Map<ArtifactKey, MavenProject> projectMap = new HashMap<ArtifactKey, MavenProject>();
        for ( final MavenProject project : reactorProjects )
        {
            projectMap.put( new ArtifactKey( project ), project );
        }

        final List<org.sonatype.aether.graph.Dependency> reactorDeps =
            new ArrayList<org.sonatype.aether.graph.Dependency>();
        for ( final Object untypedDependency : dependencies )
        {
            final org.sonatype.aether.graph.Dependency dependency =
                (org.sonatype.aether.graph.Dependency) untypedDependency;
            final org.sonatype.aether.artifact.Artifact depArtifact = dependency.getArtifact();
            final ArtifactKey key = new ArtifactKey(
                    depArtifact.getGroupId(), depArtifact.getArtifactId(), depArtifact.getVersion()
            );
            if ( projectMap.containsKey( key ) )
            {
                reactorDeps.add( dependency );
            }
        }
        return reactorDeps;
    }

    private Object invoke( Object object, String method )
        throws DependencyGraphBuilderException
    {
        try
        {
            return object.getClass().getMethod( method ).invoke( object );
        }
        catch ( IllegalAccessException e )
        {
            throw new DependencyGraphBuilderException( e.getMessage(), e );
        }
        catch ( InvocationTargetException e )
        {
            throw new DependencyGraphBuilderException( e.getMessage(), e );
        }
        catch ( NoSuchMethodException e )
        {
            throw new DependencyGraphBuilderException( e.getMessage(), e );
        }
    }

    private Artifact getDependencyArtifact( Dependency dep )
    {
        org.sonatype.aether.artifact.Artifact artifact = dep.getArtifact();

        return factory.createDependencyArtifact( artifact.getGroupId(), artifact.getArtifactId(),
                                                 VersionRange.createFromVersion( artifact.getVersion() ),
                                                 artifact.getProperty( "type", artifact.getExtension() ),
                                                 artifact.getClassifier(), dep.getScope(), dep.isOptional() );
    }

    private DependencyNode buildDependencyNode( DependencyNode parent, org.sonatype.aether.graph.DependencyNode node,
                                                Artifact artifact, ArtifactFilter filter )
    {
        DefaultDependencyNode current =
            new DefaultDependencyNode( parent, artifact,
                                       null /* node.getPremanagedVersion() */,
                                       null /* node.getPremanagedScope() */,
                                       getVersionSelectedFromRange( node.getVersionConstraint() ) );

        List<DependencyNode> nodes = new ArrayList<DependencyNode>( node.getChildren().size() );
        for ( org.sonatype.aether.graph.DependencyNode child : node.getChildren() )
        {
            Artifact childArtifact = getDependencyArtifact( child.getDependency() );

            if ( ( filter == null ) || filter.include( childArtifact ) )
            {
                nodes.add( buildDependencyNode( current, child, childArtifact, filter ) );
            }
        }

        current.setChildren( Collections.unmodifiableList( nodes ) );

        return current;
    }

    private String getVersionSelectedFromRange( VersionConstraint constraint )
    {
        if ( ( constraint == null ) || ( constraint.getVersion() != null ) )
        {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        for ( org.sonatype.aether.version.VersionRange range : constraint.getRanges() )
        {
            if ( sb.length() > 0 )
            {
                sb.append( ',' );
            }
            sb.append( range );
        }

        return sb.toString();
    }
}
