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.nio.file.Path;
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.transfer.artifact.resolve.ArtifactResolver;
import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolverException;
import org.apache.maven.shared.transfer.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<Path>> resolveDependencySourcePaths( final SourceResolverConfig config )
        throws ArtifactResolutionException, ArtifactNotFoundException
    {
        final Map<String, Collection<Path>> 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, Path> 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(), 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, Path> entry : resolveAndUnpack( toResolve, config, RESOURCE_VALID_CLASSIFIERS,
                                                                      false ) )
            {
                dirs.add( entry.getValue().toString() );
            }
        }
        catch ( ArtifactResolutionException | 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(), e );
                    throw error;
                }
            }
            
            result.add( new JavadocBundle( options, resources ) );
        }
        
        return result;
    }

    private Collection<Entry<String, Path>> 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, Path>> 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, Path>> 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<>( a.getDependencyConflictId(), d.toPath().toAbsolutePath() ) );
            }
            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<Path> 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();
                dirs.addAll( srcRoots );
            }

            if ( config.includeTestSources() )
            {
                final List<String> srcRoots = reactorProject.getTestCompileSourceRoots();
                dirs.addAll( srcRoots );
            }
        }

        return JavadocUtil.pruneDirs( reactorProject, dirs );
    }

    private static String key( final String gid, final String aid )
    {
        return gid + ":" + aid;
    }

}
