package org.apache.maven.archiva.repository.project.filters;

/*
 * 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.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.archiva.model.ArchivaModelCloner;
import org.apache.maven.archiva.model.ArchivaProjectModel;
import org.apache.maven.archiva.model.Dependency;
import org.apache.maven.archiva.model.VersionedReference;
import org.apache.maven.archiva.repository.project.ProjectModelException;
import org.apache.maven.archiva.repository.project.ProjectModelFilter;
import org.apache.maven.archiva.repository.project.ProjectModelMerge;
import org.apache.maven.archiva.repository.project.ProjectModelResolverFactory;
import org.codehaus.plexus.cache.Cache;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Builder for the Effective Project Model.  
 *
 * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
 * @version $Id$
 * @plexus.component role="org.apache.maven.archiva.repository.project.ProjectModelFilter" 
 *                   role-hint="effective" 
 */
public class EffectiveProjectModelFilter
    implements ProjectModelFilter
{
    private ProjectModelFilter expressionFilter = new ProjectModelExpressionFilter();

    /**
     * @plexus.requirement
     */
    private ProjectModelResolverFactory resolverFactory;

    /**
     * @plexus.requirement role-hint="effective-project-cache"
     */
    private Cache effectiveProjectCache;

    /**
     * Take the provided {@link ArchivaProjectModel} and build the effective {@link ArchivaProjectModel}.
     * 
     * Steps:
     * 1) Expand any expressions / properties.
     * 2) Walk the parent project references and merge.
     * 3) Apply dependency management settings.
     * 
     * @param project the project to create the effective {@link ArchivaProjectModel} from.
     * @return a the effective {@link ArchivaProjectModel}.
     * @throws ProjectModelException if there was a problem building the effective pom.
     */
    public ArchivaProjectModel filter( final ArchivaProjectModel project )
        throws ProjectModelException
    {
        if ( project == null )
        {
            return null;
        }

        if ( resolverFactory.getCurrentResolverStack().isEmpty() )
        {
            throw new IllegalStateException( "Unable to build effective pom with no project model resolvers defined." );
        }

        ArchivaProjectModel effectiveProject;
        String projectKey = toProjectKey( project );

        synchronized ( effectiveProjectCache )
        {
            if ( effectiveProjectCache.hasKey( projectKey ) )
            {
                DEBUG( "Fetching (from cache/projectKey): " + projectKey );
                effectiveProject = (ArchivaProjectModel) effectiveProjectCache.get( projectKey );
                return effectiveProject;
            }
        }

        // Clone submitted project (so that we don't mess with it) 
        effectiveProject = ArchivaModelCloner.clone( project );

        DEBUG( "Starting build of effective with: " + effectiveProject );

        // Merge in all the parent poms.
        effectiveProject = mergeParent( effectiveProject );

        // Setup Expression Evaluation pieces.
        effectiveProject = expressionFilter.filter( effectiveProject );

        // Resolve dependency versions from dependency management.
        applyDependencyManagement( effectiveProject );

        // groupId or version could be updated by parent or expressions
        projectKey = toProjectKey( effectiveProject );
        
        // Do not add project into cache if it contains no groupId and
        // version information
        if ( effectiveProject.getGroupId() != null && effectiveProject.getVersion() != null )
        {
            synchronized ( effectiveProjectCache )
            {
                DEBUG( "Putting (to cache/projectKey): " + projectKey );
                effectiveProjectCache.put( projectKey, effectiveProject );
            }
        }

        // Return what we got.
        return effectiveProject;
    }

    private void applyDependencyManagement( ArchivaProjectModel pom )
    {
        if ( CollectionUtils.isEmpty( pom.getDependencyManagement() )
            || CollectionUtils.isEmpty( pom.getDependencies() ) )
        {
            // Nothing to do. All done!
            return;
        }

        Map<String, Dependency> managedDependencies = createDependencyMap( pom.getDependencyManagement() );
        Iterator<Dependency> it = pom.getDependencies().iterator();
        while ( it.hasNext() )
        {
            Dependency dep = it.next();
            String key = toVersionlessDependencyKey( dep );

            // Do we need to do anything?
            if ( managedDependencies.containsKey( key ) )
            {
                Dependency mgmtDep = (Dependency) managedDependencies.get( key );

                dep.setVersion( mgmtDep.getVersion() );
                dep.setScope( mgmtDep.getScope() );
                dep.setExclusions( ProjectModelMerge.mergeExclusions( dep.getExclusions(), mgmtDep.getExclusions() ) );
            }
        }
    }

    private ArchivaProjectModel mergeParent( ArchivaProjectModel pom )
        throws ProjectModelException
    {
        ArchivaProjectModel mixedProject;

        DEBUG( "Project: " + toProjectKey( pom ) );

        if ( pom.getParentProject() != null )
        {
            // Use parent reference.
            VersionedReference parentRef = pom.getParentProject();

            String parentKey = VersionedReference.toKey( parentRef );

            DEBUG( "Has parent: " + parentKey );

            ArchivaProjectModel parentProject;

            synchronized ( effectiveProjectCache )
            {
                // is the pre-merged parent in the cache? 
                if ( effectiveProjectCache.hasKey( parentKey ) )
                {
                    DEBUG( "Fetching (from cache/parentKey): " + parentKey );
                    // Use the one from the cache.
                    parentProject = (ArchivaProjectModel) effectiveProjectCache.get( parentKey );
                }
                else
                {
                    // Look it up, using resolvers.
                    parentProject = this.resolverFactory.getCurrentResolverStack().findProject( parentRef );
                }
            }

            if ( parentProject != null )
            {
                // Merge the pom with the parent pom.
                parentProject = mergeParent( parentProject );
                parentProject = expressionFilter.filter( parentProject );

                // Cache the pre-merged parent.
                synchronized ( effectiveProjectCache )
                {
                    DEBUG( "Putting (to cache/parentKey/merged): " + parentKey );
                    // Add the merged parent pom to the cache.
                    effectiveProjectCache.put( parentKey, parentProject );
                }

                // Now merge the parent with the current
                mixedProject = ProjectModelMerge.merge( pom, parentProject );
            }
            else
            {
                // Shortcircuit due to missing parent pom.
                // TODO: Document this via a monitor.
                mixedProject = mixinSuperPom( pom );

                // Cache the non-existant parent.
                synchronized ( effectiveProjectCache )
                {
                    DEBUG( "Putting (to cache/parentKey/basicPom): " + parentKey );
                    // Add the basic pom to cache.
                    effectiveProjectCache.put( parentKey, createBasicPom( parentRef ) );
                }
            }
        }
        else
        {
            DEBUG( "No parent found" );

            /* Mix in the super-pom.
             * 
             * Super POM from maven/components contains many things.
             * However, for purposes of archiva, only the <repositories>
             * and <pluginRepositories> sections are of any value.
             */

            mixedProject = mixinSuperPom( pom );
        }

        return mixedProject;
    }

    private ArchivaProjectModel createBasicPom( VersionedReference ref )
    {
        ArchivaProjectModel model = new ArchivaProjectModel();
        model.setGroupId( ref.getGroupId() );
        model.setArtifactId( ref.getArtifactId() );
        model.setVersion( ref.getVersion() );
        model.setPackaging( "jar" );

        return model;
    }

    /**
     * Super POM from maven/components contains many things.
     * However, for purposes of archiva, only the <repositories>
     * and <pluginRepositories> sections are of any value.
     * 
     * @param pom
     * @return
     */
    private ArchivaProjectModel mixinSuperPom( ArchivaProjectModel pom )
    {
        // TODO: add super pom repositories.
        DEBUG( "Mix in Super POM: " + pom );

        return pom;
    }

    private static Map<String, Dependency> createDependencyMap( List<Dependency> dependencies )
    {
        Map<String, Dependency> ret = new HashMap<String, Dependency>();

        Iterator<Dependency> it = dependencies.iterator();
        while ( it.hasNext() )
        {
            Dependency dep = it.next();
            String key = toVersionlessDependencyKey( dep );
            ret.put( key, dep );
        }

        return ret;
    }

    private static String toVersionlessDependencyKey( Dependency dep )
    {
        StringBuffer key = new StringBuffer();

        key.append( dep.getGroupId() ).append( ":" ).append( dep.getArtifactId() );
        key.append( StringUtils.defaultString( dep.getClassifier() ) ).append( ":" );
        key.append( dep.getType() );

        return key.toString();
    }

    private String toProjectKey( ArchivaProjectModel project )
    {
        StringBuffer key = new StringBuffer();

        key.append( project.getGroupId() ).append( ":" );
        key.append( project.getArtifactId() ).append( ":" );
        key.append( project.getVersion() );

        return key.toString();
    }

    private void DEBUG( String msg )
    {
        // Used in debugging of this object.
        // System.out.println( "[EffectiveProjectModelFilter] " + msg );
    }
}
