package org.apache.maven.plugins.javadoc.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 static org.codehaus.plexus.util.IOUtil.close;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
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.plugins.javadoc.AbstractJavadocMojo;
import org.apache.maven.plugins.javadoc.JavadocUtil;
import org.apache.maven.plugins.javadoc.ResourcesBundleMojo;
import org.apache.maven.plugins.javadoc.options.JavadocOptions;
import org.apache.maven.plugins.javadoc.options.io.xpp3.JavadocOptionsXpp3Reader;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.artifact.filter.resolve.transform.ArtifactIncludeFilterTransformer;
import org.apache.maven.shared.artifact.resolve.ArtifactResolver;
import org.apache.maven.shared.artifact.resolve.ArtifactResolverException;
import org.apache.maven.shared.dependencies.resolve.DependencyResolver;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.archiver.UnArchiver;
import org.codehaus.plexus.archiver.manager.ArchiverManager;
import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

/**
 * 
 */
@Component( role = ResourceResolver.class )
public final class ResourceResolver extends AbstractLogEnabled
{
    @Requirement
    private ArtifactFactory artifactFactory;
    
    @Requirement
    private ArtifactResolver resolver;
    
    @Requirement
    private DependencyResolver dependencyResolver;

    @Requirement
    private ArtifactMetadataSource artifactMetadataSource;
    
    @Requirement
    private ArchiverManager archiverManager;

    /**
     * The classifier for sources.
     */
    public static final String SOURCES_CLASSIFIER = "sources";

    /**
     * The classifier for test sources 
     */
    public static final String TEST_SOURCES_CLASSIFIER = "test-sources";

    private static final List<String> SOURCE_VALID_CLASSIFIERS = Arrays.asList( SOURCES_CLASSIFIER,
                                                                                TEST_SOURCES_CLASSIFIER );

    private static final List<String> RESOURCE_VALID_CLASSIFIERS =
        Arrays.asList( AbstractJavadocMojo.JAVADOC_RESOURCES_ATTACHMENT_CLASSIFIER,
                       AbstractJavadocMojo.TEST_JAVADOC_RESOURCES_ATTACHMENT_CLASSIFIER );

    /**
     * @param config {@link SourceResolverConfig}
     * @return list of {@link JavadocBundle}.
     * @throws IOException {@link IOException}
     */
    public List<JavadocBundle> resolveDependencyJavadocBundles( final SourceResolverConfig config )
        throws IOException
    {
        final List<JavadocBundle> bundles = new ArrayList<>();

        final Map<String, MavenProject> projectMap = new HashMap<>();
        if ( config.reactorProjects() != null )
        {
            for ( final MavenProject p : config.reactorProjects() )
            {
                projectMap.put( key( p.getGroupId(), p.getArtifactId() ), p );
            }
        }

        final List<Artifact> artifacts = config.project().getTestArtifacts();

        final List<Artifact> forResourceResolution = new ArrayList<>( artifacts.size() );
        for ( final Artifact artifact : artifacts )
        {
            final String key = key( artifact.getGroupId(), artifact.getArtifactId() );
            final MavenProject p = projectMap.get( key );
            if ( p != null )
            {
                bundles.addAll( resolveBundleFromProject( config, p, artifact ) );
            }
            else
            {
                forResourceResolution.add( artifact );
            }
        }

        bundles.addAll( resolveBundlesFromArtifacts( config, forResourceResolution ) );

        return bundles;
    }

    /**
     * @param config {@link SourceResolverConfig}
     * @return The list of resolved dependencies.
     * @throws ArtifactResolutionException {@link ArtifactResolutionException}
     * @throws ArtifactNotFoundException {@link ArtifactNotFoundException}
     */
    public Map<String, Collection<String>> resolveDependencySourcePaths( final SourceResolverConfig config )
        throws ArtifactResolutionException, ArtifactNotFoundException
    {
        final Map<String, Collection<String>> mappedDirs = new LinkedHashMap<>();
        
        final Map<String, MavenProject> projectMap = new HashMap<>();
        if ( config.reactorProjects() != null )
        {
            for ( final MavenProject p : config.reactorProjects() )
            {
                projectMap.put( key( p.getGroupId(), p.getArtifactId() ), p );
            }
        }

        final List<Artifact> artifacts = config.project().getTestArtifacts();

        final List<Artifact> forResourceResolution = new ArrayList<>( artifacts.size() );
        for ( final Artifact artifact : artifacts )
        {
            final String key = key( artifact.getGroupId(), artifact.getArtifactId() );
            final MavenProject p = projectMap.get( key );
            if ( p != null )
            {
                mappedDirs.put( key, resolveFromProject( config, p, artifact ) );
            }
            else
            {
                forResourceResolution.add( artifact );
            }
        }

        for ( Map.Entry<String, String> entry : resolveFromArtifacts( config, forResourceResolution ) )
        {
            mappedDirs.put( entry.getKey(), Collections.singletonList( entry.getValue() ) );
        }

        return mappedDirs;
    }

    private static List<JavadocBundle> resolveBundleFromProject( SourceResolverConfig config, MavenProject project,
                                                           Artifact artifact ) throws IOException
    {
        List<JavadocBundle> bundles = new ArrayList<>();
        
        List<String> classifiers = new ArrayList<>();
        if ( config.includeCompileSources() )
        {
            classifiers.add( AbstractJavadocMojo.JAVADOC_RESOURCES_ATTACHMENT_CLASSIFIER );
        }
        
        if ( config.includeTestSources() )
        {
            classifiers.add( AbstractJavadocMojo.TEST_JAVADOC_RESOURCES_ATTACHMENT_CLASSIFIER );
        }
        
        for ( String classifier : classifiers )
        {
            File optionsFile =
                new File( project.getBuild().getDirectory(), "javadoc-bundle-options/javadoc-options-" + classifier
                    + ".xml" );
            if ( !optionsFile.exists() )
            {
                continue;
            }
            
            FileInputStream stream = null;
            try
            {
                stream = new FileInputStream( optionsFile );
                JavadocOptions options = new JavadocOptionsXpp3Reader().read( stream );
                stream.close();
                stream = null;
                bundles.add( new JavadocBundle( options, new File( project.getBasedir(),
                                                                   options.getJavadocResourcesDirectory() ) ) );
            }
            catch ( XmlPullParserException e )
            {
                IOException error =
                    new IOException( "Failed to read javadoc options from: " + optionsFile + "\nReason: "
                        + e.getMessage() );
                error.initCause( e );
                
                throw error;
            }
            finally
            {
                close( stream );
            }
        }

        return bundles;
    }

    private List<JavadocBundle> resolveBundlesFromArtifacts( final SourceResolverConfig config,
                                                                    final List<Artifact> artifacts )
        throws IOException
    {
        final List<Artifact> toResolve = new ArrayList<>( artifacts.size() );

        for ( final Artifact artifact : artifacts )
        {
            if ( config.filter() != null
                && !new ArtifactIncludeFilterTransformer().transform( config.filter() ).include( artifact ) )
            {
                continue;
            }

            if ( config.includeCompileSources() )
            {
                toResolve.add( createResourceArtifact( artifact,
                                                       AbstractJavadocMojo.JAVADOC_RESOURCES_ATTACHMENT_CLASSIFIER,
                                                       config ) );
            }

            if ( config.includeTestSources() )
            {
                toResolve.add( createResourceArtifact( artifact,
                                                       AbstractJavadocMojo.TEST_JAVADOC_RESOURCES_ATTACHMENT_CLASSIFIER,
                                                       config ) );
            }
        }

        List<String> dirs = new ArrayList<>( toResolve.size() );
        try
        {
            for ( Map.Entry<String, String> entry : resolveAndUnpack( toResolve, config, RESOURCE_VALID_CLASSIFIERS,
                                                                      false ) )
            {
                dirs.add( entry.getValue() );
            }
        }
        catch ( ArtifactResolutionException e )
        {
            if ( getLogger().isDebugEnabled() )
            {
                getLogger().debug( e.getMessage(), e );
            }
        }
        catch ( ArtifactNotFoundException e )
        {
            if ( getLogger().isDebugEnabled() )
            {
                getLogger().debug( e.getMessage(), e );
            }
        }
        
        List<JavadocBundle> result = new ArrayList<>();

        for ( String d : dirs )
        {
            File dir = new File( d );
            File resources = new File( dir, ResourcesBundleMojo.RESOURCES_DIR_PATH );
            JavadocOptions options = null;

            File javadocOptions = new File( dir, ResourcesBundleMojo.BUNDLE_OPTIONS_PATH );
            if ( javadocOptions.exists() )
            {
                try ( FileInputStream reader = new FileInputStream( javadocOptions )  )
                {
                    options = new JavadocOptionsXpp3Reader().read( reader );
                }
                catch ( XmlPullParserException e )
                {
                    IOException error = new IOException( "Failed to parse javadoc options: " + e.getMessage() );
                    error.initCause( e );
                    
                    throw error;
                }
            }
            
            result.add( new JavadocBundle( options, resources ) );
        }
        
        return result;
    }

    private Collection<Entry<String, String>> resolveFromArtifacts( final SourceResolverConfig config,
                                                      final List<Artifact> artifacts )
        throws ArtifactResolutionException, ArtifactNotFoundException
    {
        final List<Artifact> toResolve = new ArrayList<>( artifacts.size() );

        for ( final Artifact artifact : artifacts )
        {
            if ( config.filter() != null
                && !new ArtifactIncludeFilterTransformer().transform( config.filter() ).include( artifact ) )
            {
                continue;
            }

            if ( config.includeCompileSources() )
            {
                toResolve.add( createResourceArtifact( artifact, SOURCES_CLASSIFIER, config ) );
            }

            if ( config.includeTestSources() )
            {
                toResolve.add( createResourceArtifact( artifact, TEST_SOURCES_CLASSIFIER, config ) );
            }
        }

        return resolveAndUnpack( toResolve, config, SOURCE_VALID_CLASSIFIERS, true );
    }

    private Artifact createResourceArtifact( final Artifact artifact, final String classifier,
                                                    final SourceResolverConfig config )
    {
        final DefaultArtifact a =
            (DefaultArtifact) artifactFactory.createArtifactWithClassifier( artifact.getGroupId(),
                                                                                     artifact.getArtifactId(),
                                                                                     artifact.getVersion(), "jar",
                                                                                     classifier );

        a.setRepository( artifact.getRepository() );

        return a;
    }

    /**
     * 
     * @param artifacts the artifacts to resolve
     * @param config the configuration
     * @param validClassifiers 
     * @param propagateErrors
     * @return list of <dependencyConflictId, absolutePath>
     * @throws ArtifactResolutionException if an exception occurs
     * @throws ArtifactNotFoundException if an exception occurs
     */
    private Collection<Map.Entry<String, String>> resolveAndUnpack( final List<Artifact> artifacts,
                                                                    final SourceResolverConfig config,
                                                                    final List<String> validClassifiers,
                                                                    final boolean propagateErrors )
        throws ArtifactResolutionException, ArtifactNotFoundException
    {
        // NOTE: Since these are '-sources' and '-test-sources' artifacts, they won't actually 
        // resolve transitively...this is just used to aggregate resolution failures into a single 
        // exception.
        final Set<Artifact> artifactSet = new LinkedHashSet<>( artifacts );

        final ArtifactFilter filter;
        if ( config.filter() != null )
        {
            filter = new ArtifactIncludeFilterTransformer().transform( config.filter() );
        }
        else
        {
            filter = null;
        }
        
        final List<Map.Entry<String, String>> result = new ArrayList<>( artifacts.size() );
        for ( final Artifact a : artifactSet )
        {
            if ( !validClassifiers.contains( a.getClassifier() ) || ( filter != null && !filter.include( a ) ) )
            {
                continue;
            }
            
            Artifact resolvedArtifact;
            try
            {
                resolvedArtifact = resolver.resolveArtifact( config.getBuildingRequest(), a ).getArtifact();
            }
            catch ( ArtifactResolverException e1 )
            {
                continue;
            }

            final File d =
                new File( config.outputBasedir(), a.getArtifactId() + "-" + a.getVersion() + "-" + a.getClassifier() );

            if ( !d.exists() )
            {
                d.mkdirs();
            }

            try
            {
                final UnArchiver unArchiver = archiverManager.getUnArchiver( a.getType() );

                unArchiver.setDestDirectory( d );
                unArchiver.setSourceFile( resolvedArtifact.getFile() );

                unArchiver.extract();

                result.add( new AbstractMap.SimpleEntry<String, String>( a.getDependencyConflictId(),
                                                                         d.getAbsolutePath() ) );
            }
            catch ( final NoSuchArchiverException e )
            {
                if ( propagateErrors )
                {
                    throw new ArtifactResolutionException( "Failed to retrieve valid un-archiver component: "
                        + a.getType(), a, e );
                }
            }
            catch ( final ArchiverException e )
            {
                if ( propagateErrors )
                {
                    throw new ArtifactResolutionException( "Failed to unpack: " + a.getId(), a, e );
                }
            }
        }

        return result;
    }

    private static Collection<String> resolveFromProject( final SourceResolverConfig config,
                                                    final MavenProject reactorProject, final Artifact artifact )
    {
        final List<String> dirs = new ArrayList<>();

        if ( config.filter() == null
            || new ArtifactIncludeFilterTransformer().transform( config.filter() ).include( artifact ) )
        {
            if ( config.includeCompileSources() )
            {
                final List<String> srcRoots = reactorProject.getCompileSourceRoots();
                for ( final String root : srcRoots )
                {
                    dirs.add( root );
                }
            }

            if ( config.includeTestSources() )
            {
                final List<String> srcRoots = reactorProject.getTestCompileSourceRoots();
                for ( final String root : srcRoots )
                {
                    dirs.add( root );
                }
            }
        }

        return JavadocUtil.pruneDirs( reactorProject, dirs );
    }

    private static String key( final String gid, final String aid )
    {
        return gid + ":" + aid;
    }

}
