package org.apache.maven.artifact.resolver;

/*
 * 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.metadata.ArtifactMetadataRetrievalException;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.metadata.ResolutionGroup;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.filter.AndArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.ManagedVersionMap;
import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
import org.apache.maven.artifact.versioning.VersionRange;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Default implementation of the artifact collector.
 *
 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 * @version $Id$
 */
public class DefaultArtifactCollector
    implements ArtifactCollector
{
    public ArtifactResolutionResult collect( Set artifacts, Artifact originatingArtifact,
                                             ArtifactRepository localRepository, List remoteRepositories,
                                             ArtifactMetadataSource source, ArtifactFilter filter, List listeners )
        throws ArtifactResolutionException
    {
        return collect( artifacts, originatingArtifact, Collections.EMPTY_MAP, localRepository, remoteRepositories,
                        source, filter, listeners );
    }

    public ArtifactResolutionResult collect( Set artifacts, Artifact originatingArtifact, Map managedVersions,
                                             ArtifactRepository localRepository, List remoteRepositories,
                                             ArtifactMetadataSource source, ArtifactFilter filter, List listeners )
        throws ArtifactResolutionException
    {
        Map resolvedArtifacts = new LinkedHashMap();

        ResolutionNode root = new ResolutionNode( originatingArtifact, remoteRepositories );

        root.addDependencies( artifacts, remoteRepositories, filter );

        ManagedVersionMap versionMap = getManagedVersionsMap( originatingArtifact, managedVersions );

        recurse( originatingArtifact, root, resolvedArtifacts, versionMap, localRepository, remoteRepositories, source, filter,
                 listeners );

        Set set = new LinkedHashSet();

        for ( Iterator i = resolvedArtifacts.values().iterator(); i.hasNext(); )
        {
            List nodes = (List) i.next();
            for ( Iterator j = nodes.iterator(); j.hasNext(); )
            {
                ResolutionNode node = (ResolutionNode) j.next();
                if ( !node.equals( root ) && node.isActive() )
                {
                    Artifact artifact = node.getArtifact();

                    if ( node.filterTrail( filter ) )
                    {
                        // If it was optional and not a direct dependency,
                        // we don't add it or its children, just allow the update of the version and scope
                        if ( node.isChildOfRootNode() || !artifact.isOptional() )
                        {
                            artifact.setDependencyTrail( node.getDependencyTrail() );

                            set.add( node );
                        }
                    }
                }
            }
        }

        ArtifactResolutionResult result = new ArtifactResolutionResult();
        result.setArtifactResolutionNodes( set );
        return result;
    }

    /**
     * Get the map of managed versions, removing the originating artifact if it is also in managed versions
     * @param originatingArtifact artifact we are processing
     * @param managedVersions original managed versions
     */
    private ManagedVersionMap getManagedVersionsMap( Artifact originatingArtifact, Map managedVersions )
    {
        ManagedVersionMap versionMap;
        if ( managedVersions != null && managedVersions instanceof ManagedVersionMap )
        {
            versionMap = (ManagedVersionMap) managedVersions;
        }
        else
        {
            versionMap = new ManagedVersionMap( managedVersions );
        }

        /* remove the originating artifact if it is also in managed versions to avoid being modified during resolution */
        Artifact managedOriginatingArtifact = (Artifact) versionMap.get( originatingArtifact.getDependencyConflictId() );
        if ( managedOriginatingArtifact != null )
        {
            // TODO we probably want to warn the user that he is building an artifact with
            // different values than in dependencyManagement
            if ( managedVersions instanceof ManagedVersionMap )
            {
                /* avoid modifying the managedVersions parameter creating a new map */
                versionMap = new ManagedVersionMap( managedVersions );
            }
            versionMap.remove( originatingArtifact.getDependencyConflictId() );
        }

        return versionMap;
    }

    private void recurse( Artifact originatingArtifact, ResolutionNode node, Map resolvedArtifacts, ManagedVersionMap managedVersions,
                          ArtifactRepository localRepository, List remoteRepositories, ArtifactMetadataSource source,
                          ArtifactFilter filter, List listeners )
        throws CyclicDependencyException, ArtifactResolutionException, OverConstrainedVersionException
    {
        fireEvent( ResolutionListener.TEST_ARTIFACT, listeners, node );

        Object key = node.getKey();

        // TODO: Does this check need to happen here?  Had to add the same call
        // below when we iterate on child nodes -- will that suffice?
        if ( managedVersions.containsKey( key ) )
        {
            manageArtifact( node, managedVersions, listeners );
        }

        List previousNodes = (List) resolvedArtifacts.get( key );
        if ( previousNodes != null )
        {
            for ( Iterator i = previousNodes.iterator(); i.hasNext(); )
            {
                ResolutionNode previous = (ResolutionNode) i.next();

                if ( previous.isActive() )
                {
                    // Version mediation
                    VersionRange previousRange = previous.getArtifact().getVersionRange();
                    VersionRange currentRange = node.getArtifact().getVersionRange();

                    if ( previousRange != null && currentRange != null )
                    {
                        // TODO: shouldn't need to double up on this work, only done for simplicity of handling recommended
                        // version but the restriction is identical
                        VersionRange newRange = previousRange.restrict( currentRange );
                        // TODO: ick. this forces the OCE that should have come from the previous call. It is still correct
                        if ( newRange.isSelectedVersionKnown( previous.getArtifact() ) )
                        {
                            fireEvent( ResolutionListener.RESTRICT_RANGE, listeners, node, previous.getArtifact(),
                                       newRange );
                        }
                        previous.getArtifact().setVersionRange( newRange );
                        node.getArtifact().setVersionRange( currentRange.restrict( previousRange ) );

                        //Select an appropriate available version from the (now restricted) range
                        //Note this version was selected before to get the appropriate POM
                        //But it was reset by the call to setVersionRange on restricting the version
                        ResolutionNode[] resetNodes = {previous, node};
                        for ( int j = 0; j < 2; j++ )
                        {
                            Artifact resetArtifact = resetNodes[j].getArtifact();

                            //MNG-2123: if the previous node was not a range, then it wouldn't have any available
                            //versions. We just clobbered the selected version above. (why? i have no idea.)
                            //So since we are here and this is ranges we must go figure out the version (for a third time...)
                            if ( resetArtifact.getVersion() == null && resetArtifact.getVersionRange() != null )
                            {

                                // go find the version. This is a total hack. See previous comment.
                                List versions = resetArtifact.getAvailableVersions();
                                if ( versions == null )
                                {
                                    try
                                    {
                                        versions =
                                            source.retrieveAvailableVersions( resetArtifact, localRepository,
                                                                              remoteRepositories );
                                        resetArtifact.setAvailableVersions( versions );
                                    }
                                    catch ( ArtifactMetadataRetrievalException e )
                                    {
                                        resetArtifact.setDependencyTrail( node.getDependencyTrail() );
                                        throw new ArtifactResolutionException( "Unable to get dependency information: "
                                            + e.getMessage(), resetArtifact, remoteRepositories, e );
                                    }
                                }
                                //end hack

                                //MNG-2861: match version can return null
                                ArtifactVersion selectedVersion =
                                    resetArtifact.getVersionRange().matchVersion( resetArtifact.getAvailableVersions() );
                                if ( selectedVersion != null )
                                {
                                    resetArtifact.selectVersion( selectedVersion.toString() );
                                }
                                else
                                {
                                    throw new OverConstrainedVersionException( " Unable to find a version in "
                                        + resetArtifact.getAvailableVersions() + " to match the range "
                                        + resetArtifact.getVersionRange(), resetArtifact );
                                }

                                fireEvent( ResolutionListener.SELECT_VERSION_FROM_RANGE, listeners, resetNodes[j] );
                            }
                        }
                    }

                    // Conflict Resolution
                    // TODO: use as conflict resolver(s), chain

                    // TODO: should this be part of mediation?
                    // previous one is more dominant
                    ResolutionNode nearest;
                    ResolutionNode farthest;
                    if ( previous.getDepth() <= node.getDepth() )
                    {
                        nearest = previous;
                        farthest = node;
                    }
                    else
                    {
                        nearest = node;
                        farthest = previous;
                    }

                    if ( checkScopeUpdate( farthest, nearest, listeners ) )
                    {
                        // if we need to update scope of nearest to use farthest scope, use the nearest version, but farthest scope
                        nearest.disable();
                        farthest.getArtifact().setVersion( nearest.getArtifact().getVersion() );
                        fireEvent( ResolutionListener.OMIT_FOR_NEARER, listeners, nearest, farthest.getArtifact() );
                    }
                    else
                    {
                        farthest.disable();
                        fireEvent( ResolutionListener.OMIT_FOR_NEARER, listeners, farthest, nearest.getArtifact() );
                    }
                }
            }
        }
        else
        {
            previousNodes = new ArrayList();
            resolvedArtifacts.put( key, previousNodes );
        }
        previousNodes.add( node );

        if ( node.isActive() )
        {
            fireEvent( ResolutionListener.INCLUDE_ARTIFACT, listeners, node );
        }

        // don't pull in the transitive deps of a system-scoped dependency.
        if ( node.isActive() && !Artifact.SCOPE_SYSTEM.equals( node.getArtifact().getScope() ) )
        {
            fireEvent( ResolutionListener.PROCESS_CHILDREN, listeners, node );

            Artifact parentArtifact = node.getArtifact();

            for ( Iterator i = node.getChildrenIterator(); i.hasNext(); )
            {
                ResolutionNode child = (ResolutionNode) i.next();

                // We leave in optional ones, but don't pick up its dependencies
                if ( !child.isResolved() && ( !child.getArtifact().isOptional() || child.isChildOfRootNode() ) )
                {
                    Artifact artifact = child.getArtifact();
                    artifact.setDependencyTrail( node.getDependencyTrail() );

                    List childRemoteRepositories = child.getRemoteRepositories();
                    try
                    {
                        Object childKey;
                        do
                        {
                            childKey = child.getKey();

                            if ( managedVersions.containsKey( childKey ) )
                            {
                                // If this child node is a managed dependency, ensure
                                // we are using the dependency management version
                                // of this child if applicable b/c we want to use the
                                // managed version's POM, *not* any other version's POM.
                                // We retrieve the POM below in the retrieval step.
                                manageArtifact( child, managedVersions, listeners );

                                // Also, we need to ensure that any exclusions it presents are
                                // added to the artifact before we retrieve the metadata
                                // for the artifact; otherwise we may end up with unwanted
                                // dependencies.
                                Artifact ma = (Artifact) managedVersions.get( childKey );
                                ArtifactFilter managedExclusionFilter = ma.getDependencyFilter();
                                if ( null != managedExclusionFilter )
                                {
                                    if ( null != artifact.getDependencyFilter() )
                                    {
                                        AndArtifactFilter aaf = new AndArtifactFilter();
                                        aaf.add( artifact.getDependencyFilter() );
                                        aaf.add( managedExclusionFilter );
                                        artifact.setDependencyFilter( aaf );
                                    }
                                    else
                                    {
                                        artifact.setDependencyFilter( managedExclusionFilter );
                                    }
                                }
                            }

                            if ( artifact.getVersion() == null )
                            {
                                // set the recommended version
                                // TODO: maybe its better to just pass the range through to retrieval and use a transformation?
                                ArtifactVersion version;
                                if ( artifact.isSelectedVersionKnown() )
                                {
                                    version = artifact.getSelectedVersion();
                                }
                                else
                                {
                                    //go find the version
                                    List versions = artifact.getAvailableVersions();
                                    if ( versions == null )
                                    {
                                        versions = source.retrieveAvailableVersions( artifact, localRepository,
                                                                                     childRemoteRepositories );
                                        artifact.setAvailableVersions( versions );
                                    }

                                    Collections.sort( versions );

                                    VersionRange versionRange = artifact.getVersionRange();

                                    version = versionRange.matchVersion( versions );

                                    if ( version == null )
                                    {
                                        if ( versions.isEmpty() )
                                        {
                                            throw new OverConstrainedVersionException(
                                                "No versions are present in the repository for the artifact with a range "
                                                    + versionRange, artifact, childRemoteRepositories );
                                        }

                                        throw new OverConstrainedVersionException( "Couldn't find a version in "
                                            + versions + " to match range " + versionRange, artifact,
                                            childRemoteRepositories );
                                    }
                                }

                                //this is dangerous because artifact.getSelectedVersion() can
                                //return null. However it is ok here because we first check if the
                                //selected version is known. As currently coded we can't get a null here.
                                artifact.selectVersion( version.toString() );
                                fireEvent( ResolutionListener.SELECT_VERSION_FROM_RANGE, listeners, child );
                            }

                            Artifact relocated = source.retrieveRelocatedArtifact( artifact, localRepository, childRemoteRepositories );
                            if ( relocated != null && !artifact.equals( relocated ) )
                            {
                                relocated.setDependencyFilter( artifact.getDependencyFilter() );
                                artifact = relocated;
                                child.setArtifact( artifact );
                            }
                        }
                        while ( !childKey.equals( child.getKey() ) );

                        if ( parentArtifact != null && parentArtifact.getDependencyFilter() != null
                            && !parentArtifact.getDependencyFilter().include( artifact ) )
                        {
                            // MNG-3769: the [probably relocated] artifact is excluded.
                            // We could process exclusions on relocated artifact details in the
                            // MavenMetadataSource.createArtifacts(..) step, BUT that would
                            // require resolving the POM from the repository very early on in
                            // the build.
                            continue;
                        }

                        ResolutionGroup rGroup = source.retrieve( artifact, localRepository, childRemoteRepositories );

                        //TODO might be better to have source.retrieve() throw a specific exception for this situation
                        //and catch here rather than have it return null
                        if ( rGroup == null )
                        {
                            //relocated dependency artifact is declared excluded, no need to add and recurse further
                            continue;
                        }

                        child.addDependencies( rGroup.getArtifacts(), rGroup.getResolutionRepositories(), filter );

                    }
                    catch ( CyclicDependencyException e )
                    {
                        // would like to throw this, but we have crappy stuff in the repo

                        fireEvent( ResolutionListener.OMIT_FOR_CYCLE, listeners,
                                   new ResolutionNode( e.getArtifact(), childRemoteRepositories, child ) );
                    }
                    catch ( ArtifactMetadataRetrievalException e )
                    {
                        artifact.setDependencyTrail( node.getDependencyTrail() );
                        throw new ArtifactResolutionException(
                            "Unable to get dependency information: " + e.getMessage(), artifact, childRemoteRepositories,
                            e );
                    }

                    recurse( originatingArtifact, child, resolvedArtifacts, managedVersions, localRepository, childRemoteRepositories, source,
                             filter, listeners );
                }
            }

            fireEvent( ResolutionListener.FINISH_PROCESSING_CHILDREN, listeners, node );
        }
    }

    private void manageArtifact( ResolutionNode node, ManagedVersionMap managedVersions, List listeners )
    {
        Artifact artifact = (Artifact) managedVersions.get( node.getKey() );

        // Before we update the version of the artifact, we need to know
        // whether we are working on a transitive dependency or not.  This
        // allows depMgmt to always override transitive dependencies, while
        // explicit child override depMgmt (viz. depMgmt should only
        // provide defaults to children, but should override transitives).
        // We can do this by calling isChildOfRootNode on the current node.

        if ( artifact.getVersion() != null
                        && ( node.isChildOfRootNode() ? node.getArtifact().getVersion() == null : true ) )
        {
            fireEvent( ResolutionListener.MANAGE_ARTIFACT_VERSION, listeners, node, artifact );
            node.getArtifact().setVersion( artifact.getVersion() );
        }

        if ( artifact.getScope() != null
                        && ( node.isChildOfRootNode() ? node.getArtifact().getScope() == null : true ) )
        {
            fireEvent( ResolutionListener.MANAGE_ARTIFACT_SCOPE, listeners, node, artifact );
            node.getArtifact().setScope( artifact.getScope() );
        }
    }

    /**
     * Check if the scope needs to be updated.
     * <a href="http://docs.codehaus.org/x/IGU#DependencyMediationandConflictResolution-Scoperesolution">More info</a>.
     *
     * @param farthest  farthest resolution node
     * @param nearest   nearest resolution node
     * @param listeners
     */
    boolean checkScopeUpdate( ResolutionNode farthest, ResolutionNode nearest, List listeners )
    {
        boolean updateScope = false;
        Artifact farthestArtifact = farthest.getArtifact();
        Artifact nearestArtifact = nearest.getArtifact();

        /* farthest is runtime and nearest has lower priority, change to runtime */
        if ( Artifact.SCOPE_RUNTIME.equals( farthestArtifact.getScope() )
            && ( Artifact.SCOPE_TEST.equals( nearestArtifact.getScope() ) || Artifact.SCOPE_PROVIDED.equals( nearestArtifact.getScope() ) ) )
        {
            updateScope = true;
        }

        /* farthest is compile and nearest is not (has lower priority), change to compile */
        if ( Artifact.SCOPE_COMPILE.equals( farthestArtifact.getScope() )
            && !Artifact.SCOPE_COMPILE.equals( nearestArtifact.getScope() ) )
        {
            updateScope = true;
        }

        /* current POM rules all, if nearest is in current pom, do not update its scope */
        if ( nearest.getDepth() < 2 && updateScope )
        {
            updateScope = false;

            fireEvent( ResolutionListener.UPDATE_SCOPE_CURRENT_POM, listeners, nearest, farthestArtifact );
        }

        if ( updateScope )
        {
            fireEvent( ResolutionListener.UPDATE_SCOPE, listeners, nearest, farthestArtifact );

            // previously we cloned the artifact, but it is more effecient to just update the scope
            // if problems are later discovered that the original object needs its original scope value, cloning may
            // again be appropriate
            nearestArtifact.setScope( farthestArtifact.getScope() );
        }

        return updateScope;
    }

    private void fireEvent( int event, List listeners, ResolutionNode node )
    {
        fireEvent( event, listeners, node, null );
    }

    private void fireEvent( int event, List listeners, ResolutionNode node, Artifact replacement )
    {
        fireEvent( event, listeners, node, replacement, null );
    }

    private void fireEvent( int event, List listeners, ResolutionNode node, Artifact replacement,
                            VersionRange newRange )
    {
        for ( Iterator i = listeners.iterator(); i.hasNext(); )
        {
            ResolutionListener listener = (ResolutionListener) i.next();

            switch ( event )
            {
                case ResolutionListener.TEST_ARTIFACT:
                    listener.testArtifact( node.getArtifact() );
                    break;
                case ResolutionListener.PROCESS_CHILDREN:
                    listener.startProcessChildren( node.getArtifact() );
                    break;
                case ResolutionListener.FINISH_PROCESSING_CHILDREN:
                    listener.endProcessChildren( node.getArtifact() );
                    break;
                case ResolutionListener.INCLUDE_ARTIFACT:
                    listener.includeArtifact( node.getArtifact() );
                    break;
                case ResolutionListener.OMIT_FOR_NEARER:
                    listener.omitForNearer( node.getArtifact(), replacement );
                    break;
                case ResolutionListener.OMIT_FOR_CYCLE:
                    listener.omitForCycle( node.getArtifact() );
                    break;
                case ResolutionListener.UPDATE_SCOPE:
                    listener.updateScope( node.getArtifact(), replacement.getScope() );
                    break;
                case ResolutionListener.UPDATE_SCOPE_CURRENT_POM:
                    listener.updateScopeCurrentPom( node.getArtifact(), replacement.getScope() );
                    break;
                case ResolutionListener.MANAGE_ARTIFACT_VERSION:
                    if ( listener instanceof ResolutionListenerForDepMgmt )
                    {
                        ResolutionListenerForDepMgmt asImpl = (ResolutionListenerForDepMgmt) listener;
                        asImpl.manageArtifactVersion( node.getArtifact(), replacement );
                    }
                    else
                    {
                        listener.manageArtifact( node.getArtifact(), replacement );
                    }
                    break;
                case ResolutionListener.MANAGE_ARTIFACT_SCOPE:
                    if ( listener instanceof ResolutionListenerForDepMgmt )
                    {
                        ResolutionListenerForDepMgmt asImpl = (ResolutionListenerForDepMgmt) listener;
                        asImpl.manageArtifactScope( node.getArtifact(), replacement );
                    }
                    else
                    {
                        listener.manageArtifact( node.getArtifact(), replacement );
                    }
                    break;
                case ResolutionListener.SELECT_VERSION_FROM_RANGE:
                    listener.selectVersionFromRange( node.getArtifact() );
                    break;
                case ResolutionListener.RESTRICT_RANGE:
                    if ( node.getArtifact().getVersionRange().hasRestrictions()
                        || replacement.getVersionRange().hasRestrictions() )
                    {
                        listener.restrictRange( node.getArtifact(), replacement, newRange );
                    }
                    break;
                default:
                    throw new IllegalStateException( "Unknown event: " + event );
            }
        }
    }

}
