package org.eclipse.aether.internal.impl.collect;

/*
 * 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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.ArtifactProperties;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.collection.CollectRequest;
import org.eclipse.aether.collection.CollectResult;
import org.eclipse.aether.collection.DependencyCollectionContext;
import org.eclipse.aether.collection.DependencyCollectionException;
import org.eclipse.aether.collection.DependencyManagement;
import org.eclipse.aether.collection.DependencyManager;
import org.eclipse.aether.graph.DefaultDependencyNode;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.DependencyCycle;
import org.eclipse.aether.graph.DependencyNode;
import org.eclipse.aether.graph.Exclusion;
import org.eclipse.aether.impl.ArtifactDescriptorReader;
import org.eclipse.aether.internal.impl.IniArtifactDescriptorReader;
import org.eclipse.aether.internal.impl.StubRemoteRepositoryManager;
import org.eclipse.aether.internal.impl.StubVersionRangeResolver;
import org.eclipse.aether.internal.test.util.DependencyGraphParser;
import org.eclipse.aether.internal.test.util.TestUtils;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.ArtifactDescriptorException;
import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
import org.eclipse.aether.resolution.ArtifactDescriptorResult;
import org.eclipse.aether.util.artifact.ArtifactIdUtils;
import org.eclipse.aether.util.graph.manager.ClassicDependencyManager;
import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
import org.eclipse.aether.util.graph.manager.TransitiveDependencyManager;
import org.eclipse.aether.util.graph.selector.ScopeDependencySelector;
import org.eclipse.aether.util.graph.version.HighestVersionFilter;
import org.junit.Before;
import org.junit.Test;

/**
 */
public class DefaultDependencyCollectorTest
{

    private DefaultDependencyCollector collector;

    private DefaultRepositorySystemSession session;

    private DependencyGraphParser parser;

    private RemoteRepository repository;

    private IniArtifactDescriptorReader newReader( String prefix )
    {
        return new IniArtifactDescriptorReader( "artifact-descriptions/" + prefix );
    }

    private Dependency newDep( String coords )
    {
        return newDep( coords, "" );
    }

    private Dependency newDep( String coords, String scope )
    {
        return new Dependency( new DefaultArtifact( coords ), scope );
    }

    @Before
    public void setup()
    {
        session = TestUtils.newSession();

        collector = new DefaultDependencyCollector();
        collector.setArtifactDescriptorReader( newReader( "" ) );
        collector.setVersionRangeResolver( new StubVersionRangeResolver() );
        collector.setRemoteRepositoryManager( new StubRemoteRepositoryManager() );

        parser = new DependencyGraphParser( "artifact-descriptions/" );

        repository = new RemoteRepository.Builder( "id", "default", "file:///" ).build();
    }

    private static void assertEqualSubtree( DependencyNode expected, DependencyNode actual )
    {
        assertEqualSubtree( expected, actual, new LinkedList<DependencyNode>() );
    }

    private static void assertEqualSubtree( DependencyNode expected, DependencyNode actual,
                                            LinkedList<DependencyNode> parents )
    {
        assertEquals( "path: " + parents, expected.getDependency(), actual.getDependency() );

        if ( actual.getDependency() != null )
        {
            Artifact artifact = actual.getDependency().getArtifact();
            for ( DependencyNode parent : parents )
            {
                if ( parent.getDependency() != null && artifact.equals( parent.getDependency().getArtifact() ) )
                {
                    return;
                }
            }
        }

        parents.addLast( expected );

        assertEquals( "path: " + parents + ", expected: " + expected.getChildren() + ", actual: "
                          + actual.getChildren(), expected.getChildren().size(), actual.getChildren().size() );

        Iterator<DependencyNode> iterator1 = expected.getChildren().iterator();
        Iterator<DependencyNode> iterator2 = actual.getChildren().iterator();

        while ( iterator1.hasNext() )
        {
            assertEqualSubtree( iterator1.next(), iterator2.next(), parents );
        }

        parents.removeLast();
    }

    private Dependency dep( DependencyNode root, int... coords )
    {
        return path( root, coords ).getDependency();
    }

    private DependencyNode path( DependencyNode root, int... coords )
    {
        try
        {
            DependencyNode node = root;
            for ( int coord : coords )
            {
                node = node.getChildren().get( coord );
            }

            return node;
        }
        catch ( IndexOutOfBoundsException | NullPointerException e )
        {
            throw new IllegalArgumentException( "illegal coordinates for child", e );
        }
    }

    @Test
    public void testSimpleCollection()
        throws DependencyCollectionException
    {
        Dependency dependency = newDep( "gid:aid:ext:ver", "compile" );
        CollectRequest request = new CollectRequest( dependency, Arrays.asList( repository ) );
        CollectResult result = collector.collectDependencies( session, request );

        assertEquals( 0, result.getExceptions().size() );

        DependencyNode root = result.getRoot();
        Dependency newDependency = root.getDependency();

        assertEquals( dependency, newDependency );
        assertEquals( dependency.getArtifact(), newDependency.getArtifact() );

        assertEquals( 1, root.getChildren().size() );

        Dependency expect = newDep( "gid:aid2:ext:ver", "compile" );
        assertEquals( expect, root.getChildren().get( 0 ).getDependency() );
    }

    @Test
    public void testMissingDependencyDescription()
    {
        CollectRequest request =
            new CollectRequest( newDep( "missing:description:ext:ver" ), Arrays.asList( repository ) );
        try
        {
            collector.collectDependencies( session, request );
            fail( "expected exception" );
        }
        catch ( DependencyCollectionException e )
        {
            CollectResult result = e.getResult();
            assertSame( request, result.getRequest() );
            assertNotNull( result.getExceptions() );
            assertEquals( 1, result.getExceptions().size() );

            assertTrue( result.getExceptions().get( 0 ) instanceof ArtifactDescriptorException );

            assertEquals( request.getRoot(), result.getRoot().getDependency() );
        }
    }

    @Test
    public void testDuplicates()
        throws DependencyCollectionException
    {
        Dependency dependency = newDep( "duplicate:transitive:ext:dependency" );
        CollectRequest request = new CollectRequest( dependency, Arrays.asList( repository ) );

        CollectResult result = collector.collectDependencies( session, request );

        assertEquals( 0, result.getExceptions().size() );

        DependencyNode root = result.getRoot();
        Dependency newDependency = root.getDependency();

        assertEquals( dependency, newDependency );
        assertEquals( dependency.getArtifact(), newDependency.getArtifact() );

        assertEquals( 2, root.getChildren().size() );

        Dependency dep = newDep( "gid:aid:ext:ver", "compile" );
        assertEquals( dep, dep( root, 0 ) );

        dep = newDep( "gid:aid2:ext:ver", "compile" );
        assertEquals( dep, dep( root, 1 ) );
        assertEquals( dep, dep( root, 0, 0 ) );
        assertEquals( dep( root, 1 ), dep( root, 0, 0 ) );
    }

    @Test
    public void testEqualSubtree()
        throws IOException, DependencyCollectionException
    {
        DependencyNode root = parser.parseResource( "expectedSubtreeComparisonResult.txt" );
        Dependency dependency = root.getDependency();
        CollectRequest request = new CollectRequest( dependency, Arrays.asList( repository ) );

        CollectResult result = collector.collectDependencies( session, request );
        assertEqualSubtree( root, result.getRoot() );
    }

    @Test
    public void testCyclicDependencies()
        throws Exception
    {
        DependencyNode root = parser.parseResource( "cycle.txt" );
        CollectRequest request = new CollectRequest( root.getDependency(), Arrays.asList( repository ) );
        CollectResult result = collector.collectDependencies( session, request );
        assertEqualSubtree( root, result.getRoot() );
    }

    @Test
    public void testCyclicDependenciesBig()
        throws Exception
    {
        CollectRequest request = new CollectRequest( newDep( "1:2:pom:5.50-SNAPSHOT" ), Arrays.asList( repository ) );
        collector.setArtifactDescriptorReader( newReader( "cycle-big/" ) );
        CollectResult result = collector.collectDependencies( session, request );
        assertNotNull( result.getRoot() );
        // we only care about the performance here, this test must not hang or run out of mem
    }

    @Test
    public void testCyclicProjects()
        throws Exception
    {
        CollectRequest request = new CollectRequest( newDep( "test:a:2" ), Arrays.asList( repository ) );
        collector.setArtifactDescriptorReader( newReader( "versionless-cycle/" ) );
        CollectResult result = collector.collectDependencies( session, request );
        DependencyNode root = result.getRoot();
        DependencyNode a1 = path( root, 0, 0 );
        assertEquals( "a", a1.getArtifact().getArtifactId() );
        assertEquals( "1", a1.getArtifact().getVersion() );
        for ( DependencyNode child : a1.getChildren() )
        {
            assertFalse( "1".equals( child.getArtifact().getVersion() ) );
        }

        assertEquals( 1, result.getCycles().size() );
        DependencyCycle cycle = result.getCycles().get( 0 );
        assertEquals( Arrays.asList(), cycle.getPrecedingDependencies() );
        assertEquals( Arrays.asList( root.getDependency(), path( root, 0 ).getDependency(), a1.getDependency() ),
                      cycle.getCyclicDependencies() );
    }

    @Test
    public void testCyclicProjects_ConsiderLabelOfRootlessGraph()
        throws Exception
    {
        Dependency dep = newDep( "gid:aid:ver", "compile" );
        CollectRequest request =
            new CollectRequest().addDependency( dep ).addRepository( repository ).setRootArtifact( dep.getArtifact() );
        CollectResult result = collector.collectDependencies( session, request );
        DependencyNode root = result.getRoot();
        DependencyNode a1 = root.getChildren().get( 0 );
        assertEquals( "aid", a1.getArtifact().getArtifactId() );
        assertEquals( "ver", a1.getArtifact().getVersion() );
        DependencyNode a2 = a1.getChildren().get( 0 );
        assertEquals( "aid2", a2.getArtifact().getArtifactId() );
        assertEquals( "ver", a2.getArtifact().getVersion() );

        assertEquals( 1, result.getCycles().size() );
        DependencyCycle cycle = result.getCycles().get( 0 );
        assertEquals( Arrays.asList(), cycle.getPrecedingDependencies() );
        assertEquals( Arrays.asList( new Dependency( dep.getArtifact(), null ), a1.getDependency() ),
                      cycle.getCyclicDependencies() );
    }

    @Test
    public void testPartialResultOnError()
        throws IOException
    {
        DependencyNode root = parser.parseResource( "expectedPartialSubtreeOnError.txt" );

        Dependency dependency = root.getDependency();
        CollectRequest request = new CollectRequest( dependency, Arrays.asList( repository ) );

        CollectResult result;
        try
        {
            result = collector.collectDependencies( session, request );
            fail( "expected exception " );
        }
        catch ( DependencyCollectionException e )
        {
            result = e.getResult();

            assertSame( request, result.getRequest() );
            assertNotNull( result.getExceptions() );
            assertEquals( 1, result.getExceptions().size() );

            assertTrue( result.getExceptions().get( 0 ) instanceof ArtifactDescriptorException );

            assertEqualSubtree( root, result.getRoot() );
        }
    }

    @Test
    public void testCollectMultipleDependencies()
        throws DependencyCollectionException
    {
        Dependency root1 = newDep( "gid:aid:ext:ver", "compile" );
        Dependency root2 = newDep( "gid:aid2:ext:ver", "compile" );
        List<Dependency> dependencies = Arrays.asList( root1, root2 );
        CollectRequest request = new CollectRequest( dependencies, null, Arrays.asList( repository ) );
        CollectResult result = collector.collectDependencies( session, request );

        assertEquals( 0, result.getExceptions().size() );
        assertEquals( 2, result.getRoot().getChildren().size() );
        assertEquals( root1, dep( result.getRoot(), 0 ) );

        assertEquals( 1, path( result.getRoot(), 0 ).getChildren().size() );
        assertEquals( root2, dep( result.getRoot(), 0, 0 ) );

        assertEquals( 0, path( result.getRoot(), 1 ).getChildren().size() );
        assertEquals( root2, dep( result.getRoot(), 1 ) );
    }

    @Test
    public void testArtifactDescriptorResolutionNotRestrictedToRepoHostingSelectedVersion()
        throws Exception
    {
        RemoteRepository repo2 = new RemoteRepository.Builder( "test", "default", "file:///" ).build();

        final List<RemoteRepository> repos = new ArrayList<>();

        collector.setArtifactDescriptorReader( new ArtifactDescriptorReader()
        {
            public ArtifactDescriptorResult readArtifactDescriptor( RepositorySystemSession session,
                                                                    ArtifactDescriptorRequest request )
            {
                repos.addAll( request.getRepositories() );
                return new ArtifactDescriptorResult( request );
            }
        } );

        List<Dependency> dependencies = Arrays.asList( newDep( "verrange:parent:jar:1[1,)", "compile" ) );
        CollectRequest request = new CollectRequest( dependencies, null, Arrays.asList( repository, repo2 ) );
        CollectResult result = collector.collectDependencies( session, request );

        assertEquals( 0, result.getExceptions().size() );
        assertEquals( 2, repos.size() );
        assertEquals( "id", repos.get( 0 ).getId() );
        assertEquals( "test", repos.get( 1 ).getId() );
    }

    @Test
    public void testManagedVersionScope()
        throws DependencyCollectionException
    {
        Dependency dependency = newDep( "managed:aid:ext:ver" );
        CollectRequest request = new CollectRequest( dependency, Arrays.asList( repository ) );

        session.setDependencyManager( new ClassicDependencyManager() );

        CollectResult result = collector.collectDependencies( session, request );

        assertEquals( 0, result.getExceptions().size() );

        DependencyNode root = result.getRoot();

        assertEquals( dependency, dep( root ) );
        assertEquals( dependency.getArtifact(), dep( root ).getArtifact() );

        assertEquals( 1, root.getChildren().size() );
        Dependency expect = newDep( "gid:aid:ext:ver", "compile" );
        assertEquals( expect, dep( root, 0 ) );

        assertEquals( 1, path( root, 0 ).getChildren().size() );
        expect = newDep( "gid:aid2:ext:managedVersion", "managedScope" );
        assertEquals( expect, dep( root, 0, 0 ) );
    }

    @Test
    public void testDependencyManagement()
        throws IOException, DependencyCollectionException
    {
        collector.setArtifactDescriptorReader( newReader( "managed/" ) );

        DependencyNode root = parser.parseResource( "expectedSubtreeComparisonResult.txt" );
        TestDependencyManager depMgmt = new TestDependencyManager();
        depMgmt.add( dep( root, 0 ), "managed", null, null );
        depMgmt.add( dep( root, 0, 1 ), "managed", "managed", null );
        depMgmt.add( dep( root, 1 ), null, null, "managed" );
        session.setDependencyManager( depMgmt );

        // collect result will differ from expectedSubtreeComparisonResult.txt
        // set localPath -> no dependency traversal
        CollectRequest request = new CollectRequest( dep( root ), Arrays.asList( repository ) );
        CollectResult result = collector.collectDependencies( session, request );

        DependencyNode node = result.getRoot();
        assertEquals( "managed", dep( node, 0, 1 ).getArtifact().getVersion() );
        assertEquals( "managed", dep( node, 0, 1 ).getScope() );

        assertEquals( "managed", dep( node, 1 ).getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ) );
        assertEquals( "managed", dep( node, 0, 0 ).getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ) );
    }

    @Test
    public void testDependencyManagement_VerboseMode()
        throws Exception
    {
        String depId = "gid:aid2:ext";
        TestDependencyManager depMgmt = new TestDependencyManager();
        depMgmt.version( depId, "managedVersion" );
        depMgmt.scope( depId, "managedScope" );
        depMgmt.optional( depId, Boolean.TRUE );
        depMgmt.path( depId, "managedPath" );
        depMgmt.exclusions( depId, new Exclusion( "gid", "aid", "*", "*" ) );
        session.setDependencyManager( depMgmt );
        session.setConfigProperty( DependencyManagerUtils.CONFIG_PROP_VERBOSE, Boolean.TRUE );

        CollectRequest request = new CollectRequest().setRoot( newDep( "gid:aid:ver" ) );
        CollectResult result = collector.collectDependencies( session, request );
        DependencyNode node = result.getRoot().getChildren().get( 0 );
        assertEquals( DependencyNode.MANAGED_VERSION | DependencyNode.MANAGED_SCOPE | DependencyNode.MANAGED_OPTIONAL
            | DependencyNode.MANAGED_PROPERTIES | DependencyNode.MANAGED_EXCLUSIONS, node.getManagedBits() );
        assertEquals( "ver", DependencyManagerUtils.getPremanagedVersion( node ) );
        assertEquals( "compile", DependencyManagerUtils.getPremanagedScope( node ) );
        assertEquals( Boolean.FALSE, DependencyManagerUtils.getPremanagedOptional( node ) );
    }

    @Test
    public void testDependencyManagement_TransitiveDependencyManager()
            throws DependencyCollectionException, IOException
    {
        collector.setArtifactDescriptorReader( newReader( "managed/" ) );
        parser = new DependencyGraphParser( "artifact-descriptions/managed/" );
        session.setDependencyManager( new TransitiveDependencyManager() );
        final Dependency root = newDep( "gid:root:ext:ver", "compile" );
        CollectRequest request = new CollectRequest( root, Collections.singletonList( repository ) );
        request.addManagedDependency( newDep( "gid:root:ext:must-retain-core-management" ) );
        CollectResult result = collector.collectDependencies( session, request );

        final DependencyNode expectedTree = parser.parseResource( "management-tree.txt" );
        assertEqualSubtree( expectedTree, result.getRoot() );

        // Same test for root artifact (POM) request.
        final CollectRequest rootArtifactRequest = new CollectRequest();
        rootArtifactRequest.setRepositories( Collections.singletonList( repository ) );
        rootArtifactRequest.setRootArtifact( new DefaultArtifact( "gid:root:ext:ver" ) );
        rootArtifactRequest.addDependency( newDep( "gid:direct:ext:ver", "compile" ) );
        rootArtifactRequest.addManagedDependency( newDep( "gid:root:ext:must-retain-core-management" ) );
        rootArtifactRequest.addManagedDependency( newDep( "gid:direct:ext:must-retain-core-management" ) );
        rootArtifactRequest.addManagedDependency( newDep( "gid:transitive-1:ext:managed-by-root" ) );
        session.setDependencyManager( new TransitiveDependencyManager() );
        result = collector.collectDependencies( session, rootArtifactRequest );
        assertEqualSubtree( expectedTree, toDependencyResult( result.getRoot(), "compile", null ) );
    }

    private DependencyNode toDependencyResult( final DependencyNode root, final String rootScope,
                                               final Boolean optional )
    {
        // Make the root artifact resultion result a dependency resolution result for the subtree check.
        assertNull( "Expected root artifact resolution result.", root.getDependency() );
        final DefaultDependencyNode defaultNode =
                new DefaultDependencyNode( new Dependency( root.getArtifact(), rootScope ) );

        defaultNode.setChildren( root.getChildren() );

        if ( optional != null )
        {
            defaultNode.setOptional( optional );
        }

        return defaultNode;
    }

    @Test
    public void testVersionFilter()
        throws Exception
    {
        session.setVersionFilter( new HighestVersionFilter() );
        CollectRequest request = new CollectRequest().setRoot( newDep( "gid:aid:1" ) );
        CollectResult result = collector.collectDependencies( session, request );
        assertEquals( 1, result.getRoot().getChildren().size() );
    }

    /**
     * Tests that scope based dependency selection happens before dependency management.
     * <p>
     * This is not really correct (see MRESOLVER-9), but there are a number of tests
     * in the Maven and Maven Integration Testing projects that currently rely on this
     * behaviour.
     */
    @Test
    public void testSelectionBeforeManagement()
        throws DependencyCollectionException
    {
        session.setDependencySelector( new ScopeDependencySelector( "provided", "test" ) );
        session.setDependencyManager( new ClassicDependencyManager() );

        Dependency dependency = newDep( "gid3:aid1:ext:1", "compile" );
        CollectRequest request = new CollectRequest( dependency, Arrays.asList( repository ) );
        CollectResult result = collector.collectDependencies( session, request );

        assertEquals( 0, result.getExceptions().size() );

        DependencyNode root = result.getRoot();
        Dependency newDependency = root.getDependency();

        assertEquals( dependency, newDependency );
        assertEquals( dependency.getArtifact(), newDependency.getArtifact() );

        assertEquals( 1, root.getChildren().size() );

        Dependency expect = newDep( "gid3:aid2:ext:1", "compile" );
        DependencyNode childLevel1 = root.getChildren().get( 0 );
        assertEquals( expect, childLevel1.getDependency() );

        // With proper dependency management, the test scope of aid3 would
        // be managed to compile, and we would get another child.
        // Currently, the dependency gets filtered by ScopeDependencyManager.
        assertEquals( 0, childLevel1.getChildren().size() );
    }

    static class TestDependencyManager
        implements DependencyManager
    {

        private Map<String, String> versions = new HashMap<>();

        private Map<String, String> scopes = new HashMap<>();

        private Map<String, Boolean> optionals = new HashMap<>();

        private Map<String, String> paths = new HashMap<>();

        private Map<String, Collection<Exclusion>> exclusions = new HashMap<>();

        public void add( Dependency d, String version, String scope, String localPath )
        {
            String id = toKey( d );
            version( id, version );
            scope( id, scope );
            path( id, localPath );
        }

        public void version( String id, String version )
        {
            versions.put( id, version );
        }

        public void scope( String id, String scope )
        {
            scopes.put( id, scope );
        }

        public void optional( String id, Boolean optional )
        {
            optionals.put( id, optional );
        }

        public void path( String id, String path )
        {
            paths.put( id, path );
        }

        public void exclusions( String id, Exclusion... exclusions )
        {
            this.exclusions.put( id, exclusions != null ? Arrays.asList( exclusions ) : null );
        }

        public DependencyManagement manageDependency( Dependency d )
        {
            String id = toKey( d );
            DependencyManagement mgmt = new DependencyManagement();
            mgmt.setVersion( versions.get( id ) );
            mgmt.setScope( scopes.get( id ) );
            mgmt.setOptional( optionals.get( id ) );
            String path = paths.get( id );
            if ( path != null )
            {
                mgmt.setProperties( Collections.singletonMap( ArtifactProperties.LOCAL_PATH, path ) );
            }
            mgmt.setExclusions( exclusions.get( id ) );
            return mgmt;
        }

        private String toKey( Dependency dependency )
        {
            return ArtifactIdUtils.toVersionlessId( dependency.getArtifact() );
        }

        public DependencyManager deriveChildManager( DependencyCollectionContext context )
        {
            return this;
        }

    }

}
