package org.apache.maven.plugins.dependency.fromDependencies;

/*
 * 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 java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ArtifactMetadata;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
import org.apache.maven.artifact.repository.MavenArtifactRepository;
import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
import org.apache.maven.artifact.repository.metadata.RepositoryMetadata;
import org.apache.maven.artifact.repository.metadata.Snapshot;
import org.apache.maven.artifact.repository.metadata.SnapshotArtifactRepositoryMetadata;
import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.LegacySupport;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.dependency.AbstractDependencyMojoTestCase;
import org.apache.maven.plugins.dependency.utils.DependencyUtil;
import org.apache.maven.plugins.dependency.utils.markers.DefaultFileMarkerHandler;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.StringUtils;
import org.sonatype.aether.impl.internal.SimpleLocalRepositoryManager;
import org.sonatype.aether.util.DefaultRepositorySystemSession;

public class TestCopyDependenciesMojo2
    extends AbstractDependencyMojoTestCase
{

    CopyDependenciesMojo mojo;

    protected void setUp()
        throws Exception
    {
        // required for mojo lookups to work
        super.setUp( "copy-dependencies", true );

        File testPom = new File( getBasedir(), "target/test-classes/unit/copy-dependencies-test/plugin-config.xml" );
        mojo = (CopyDependenciesMojo) lookupMojo( "copy-dependencies", testPom );
        mojo.outputDirectory = new File( this.testDir, "outputDirectory" );
        // mojo.silent = true;

        assertNotNull( mojo );
        assertNotNull( mojo.getProject() );
        MavenProject project = mojo.getProject();

        Set<Artifact> artifacts = this.stubFactory.getScopedArtifacts();
        Set<Artifact> directArtifacts = this.stubFactory.getReleaseAndSnapshotArtifacts();
        artifacts.addAll( directArtifacts );

        project.setArtifacts( artifacts );
        project.setDependencyArtifacts( directArtifacts );
        mojo.markersDirectory = new File( this.testDir, "markers" );

        LegacySupport legacySupport = lookup( LegacySupport.class );
        MavenSession session = newMavenSession( project );
        setVariableValueToObject( mojo, "session", session );

        legacySupport.setSession( session );
        DefaultRepositorySystemSession repoSession =
            (DefaultRepositorySystemSession) legacySupport.getRepositorySession();
        repoSession.setLocalRepositoryManager( new SimpleLocalRepositoryManager( testDir.getAbsolutePath() ) );
    }

    public void assertNoMarkerFile( Artifact artifact )
    {
        DefaultFileMarkerHandler handle = new DefaultFileMarkerHandler( artifact, mojo.markersDirectory );
        try
        {
            assertFalse( handle.isMarkerSet() );
        }
        catch ( MojoExecutionException e )
        {
            fail( e.getLongMessage() );
        }

    }

    public void testCopyDependenciesMojoIncludeCompileScope()
        throws Exception
    {
        mojo.getProject().setArtifacts( stubFactory.getScopedArtifacts() );
        mojo.getProject().setDependencyArtifacts( new HashSet<Artifact>() );
        mojo.includeScope = "compile";

        mojo.execute();

        ScopeArtifactFilter saf = new ScopeArtifactFilter( mojo.includeScope );

        Set<Artifact> artifacts = mojo.getProject().getArtifacts();
        for ( Artifact artifact : artifacts )
        {
            String fileName = DependencyUtil.getFormattedFileName( artifact, false );
            File file = new File( mojo.outputDirectory, fileName );

            assertEquals( saf.include( artifact ), file.exists() );
        }
    }

    public void testCopyDependenciesMojoIncludeTestScope()
        throws Exception
    {
        mojo.getProject().setArtifacts( stubFactory.getScopedArtifacts() );
        mojo.getProject().setDependencyArtifacts( new HashSet<Artifact>() );
        mojo.includeScope = "test";

        mojo.execute();

        ScopeArtifactFilter saf = new ScopeArtifactFilter( mojo.includeScope );

        Set<Artifact> artifacts = mojo.getProject().getArtifacts();
        for ( Artifact artifact : artifacts )
        {
            String fileName = DependencyUtil.getFormattedFileName( artifact, false );
            File file = new File( mojo.outputDirectory, fileName );

            assertEquals( saf.include( artifact ), file.exists() );
        }
    }

    public void testCopyDependenciesMojoIncludeRuntimeScope()
        throws Exception
    {
        mojo.getProject().setArtifacts( stubFactory.getScopedArtifacts() );
        mojo.getProject().setDependencyArtifacts( new HashSet<Artifact>() );
        mojo.includeScope = "runtime";

        mojo.execute();

        ScopeArtifactFilter saf = new ScopeArtifactFilter( mojo.includeScope );

        Set<Artifact> artifacts = mojo.getProject().getArtifacts();
        for ( Artifact artifact : artifacts )
        {
            String fileName = DependencyUtil.getFormattedFileName( artifact, false );
            File file = new File( mojo.outputDirectory, fileName );

            assertEquals( saf.include( artifact ), file.exists() );
        }
    }

    public void testCopyDependenciesMojoIncludeprovidedScope()
        throws Exception
    {
        mojo.getProject().setArtifacts( stubFactory.getScopedArtifacts() );
        mojo.getProject().setDependencyArtifacts( new HashSet<Artifact>() );
        mojo.includeScope = "provided";

        mojo.execute();

        Set<Artifact> artifacts = mojo.getProject().getArtifacts();
        for ( Artifact artifact : artifacts )
        {
            String fileName = DependencyUtil.getFormattedFileName( artifact, false );
            File file = new File( mojo.outputDirectory, fileName );

            assertEquals( Artifact.SCOPE_PROVIDED.equals( artifact.getScope() ), file.exists() );
        }
    }

    public void testCopyDependenciesMojoIncludesystemScope()
        throws Exception
    {
        mojo.getProject().setArtifacts( stubFactory.getScopedArtifacts() );
        mojo.getProject().setDependencyArtifacts( new HashSet<Artifact>() );
        mojo.includeScope = "system";

        mojo.execute();

        Set<Artifact> artifacts = mojo.getProject().getArtifacts();
        for ( Artifact artifact : artifacts )
        {
            String fileName = DependencyUtil.getFormattedFileName( artifact, false );
            File file = new File( mojo.outputDirectory, fileName );

            assertEquals( Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ), file.exists() );
        }
    }

    public void testSubPerArtifact()
        throws Exception
    {
        mojo.useSubDirectoryPerArtifact = true;

        mojo.execute();

        Set<Artifact> artifacts = mojo.getProject().getArtifacts();
        for ( Artifact artifact : artifacts )
        {
            String fileName = DependencyUtil.getFormattedFileName( artifact, false );
            File folder = DependencyUtil.getFormattedOutputDirectory( false, false, true, false, false,
                                                                      mojo.outputDirectory, artifact );
            File file = new File( folder, fileName );
            assertTrue( file.exists() );
        }
    }

    public void testSubPerArtifactAndType()
        throws Exception
    {
        mojo.getProject().setArtifacts( stubFactory.getTypedArtifacts() );
        mojo.getProject().setDependencyArtifacts( new HashSet<Artifact>() );
        mojo.useSubDirectoryPerArtifact = true;
        mojo.useSubDirectoryPerType = true;

        mojo.execute();

        Set<Artifact> artifacts = mojo.getProject().getArtifacts();
        for ( Artifact artifact : artifacts )
        {
            String fileName = DependencyUtil.getFormattedFileName( artifact, false );
            File folder = DependencyUtil.getFormattedOutputDirectory( false, true, true, false, false,
                                                                      mojo.outputDirectory, artifact );
            File file = new File( folder, fileName );
            assertTrue( file.exists() );
        }
    }

    public void testSubPerArtifactAndScope()
        throws Exception
    {
        mojo.getProject().setArtifacts( stubFactory.getTypedArtifacts() );
        mojo.getProject().setDependencyArtifacts( new HashSet<Artifact>() );
        mojo.useSubDirectoryPerArtifact = true;
        mojo.useSubDirectoryPerScope = true;

        mojo.execute();

        Set<Artifact> artifacts = mojo.getProject().getArtifacts();
        for ( Artifact artifact : artifacts )
        {
            String fileName = DependencyUtil.getFormattedFileName( artifact, false );
            File folder = DependencyUtil.getFormattedOutputDirectory( true, false, true, false, false,
                                                                      mojo.outputDirectory, artifact );
            File file = new File( folder, fileName );
            assertTrue( file.exists() );
        }
    }

    public void testRepositoryLayout()
        throws Exception
    {
        String baseVersion = "2.0-SNAPSHOT";
        String groupId = "testGroupId";
        String artifactId = "expanded-snapshot";

        Artifact expandedSnapshot =
            createExpandedVersionArtifact( baseVersion, groupId, artifactId, "compile", "jar", null );

        mojo.getProject().getArtifacts().add( expandedSnapshot );
        mojo.getProject().getDependencyArtifacts().add( expandedSnapshot );

        Artifact pomExpandedSnapshot =
            createExpandedVersionArtifact( baseVersion, groupId, artifactId, "compile", "pom", null );
        mojo.getProject().getArtifacts().add( pomExpandedSnapshot );
        mojo.getProject().getDependencyArtifacts().add( pomExpandedSnapshot );

        mojo.useRepositoryLayout = true;
        mojo.execute();

        ArtifactFactory artifactFactory = lookup( ArtifactFactory.class );

        File outputDirectory = mojo.outputDirectory;
        ArtifactRepository targetRepository =
            new MavenArtifactRepository( "local", outputDirectory.toURL().toExternalForm(),
                                         new DefaultRepositoryLayout(), new ArtifactRepositoryPolicy(),
                                         new ArtifactRepositoryPolicy() );

        Set<Artifact> artifacts = mojo.getProject().getArtifacts();
        for ( Artifact artifact : artifacts )
        {
            assertArtifactExists( artifact, targetRepository );

            if ( !artifact.getBaseVersion().equals( artifact.getVersion() ) )
            {
                Artifact baseArtifact = artifactFactory.createArtifact( artifact.getGroupId(), artifact.getArtifactId(),
                                                                        artifact.getBaseVersion(), artifact.getScope(),
                                                                        artifact.getType() );
                assertArtifactExists( baseArtifact, targetRepository );
            }

        }
    }

    private Artifact createExpandedVersionArtifact( String baseVersion, String groupId, String artifactId, String scope,
                                                    String type, String classifier )
        throws IOException
    {
        Artifact expandedSnapshot =
            this.stubFactory.createArtifact( groupId, artifactId, VersionRange.createFromVersion( baseVersion ), scope,
                                             type, classifier, false );

        Snapshot snapshot = new Snapshot();
        snapshot.setTimestamp( "20130710.122148" );
        snapshot.setBuildNumber( 1 );
        RepositoryMetadata metadata = new SnapshotArtifactRepositoryMetadata( expandedSnapshot, snapshot );
        String newVersion = snapshot.getTimestamp() + "-" + snapshot.getBuildNumber();
        expandedSnapshot.setResolvedVersion( StringUtils.replace( baseVersion, Artifact.SNAPSHOT_VERSION,
                                                                  newVersion ) );
        expandedSnapshot.addMetadata( metadata );
        return expandedSnapshot;
    }

    private void assertArtifactExists( Artifact artifact, ArtifactRepository targetRepository )
    {
        File file = new File( targetRepository.getBasedir(), targetRepository.getLayout().pathOf( artifact ) );
        assertTrue( "File doesn't exist: " + file.getAbsolutePath(), file.exists() );

        Collection<ArtifactMetadata> metas = artifact.getMetadataList();
        for ( ArtifactMetadata meta : metas )
        {
            File metaFile =
                new File( targetRepository.getBasedir(),
                          targetRepository.getLayout().pathOfLocalRepositoryMetadata( meta, targetRepository ) );
            assertTrue( metaFile.exists() );
        }
    }

    public void testSubPerArtifactRemoveVersion()
        throws Exception
    {
        mojo.useSubDirectoryPerArtifact = true;
        mojo.stripVersion = true;

        mojo.execute();

        Set<Artifact> artifacts = mojo.getProject().getArtifacts();
        for ( Artifact artifact : artifacts )
        {
            String fileName = DependencyUtil.getFormattedFileName( artifact, true );
            File folder = DependencyUtil.getFormattedOutputDirectory( false, false, true, false, true,
                                                                      mojo.outputDirectory, artifact );
            File file = new File( folder, fileName );
            assertTrue( file.exists() );
        }
    }

    public void testSubPerArtifactAndTypeRemoveVersion()
        throws Exception
    {
        mojo.getProject().setArtifacts( stubFactory.getTypedArtifacts() );
        mojo.getProject().setDependencyArtifacts( new HashSet<Artifact>() );
        mojo.useSubDirectoryPerArtifact = true;
        mojo.useSubDirectoryPerType = true;
        mojo.stripVersion = true;

        mojo.execute();

        Set<Artifact> artifacts = mojo.getProject().getArtifacts();
        for ( Artifact artifact : artifacts )
        {
            String fileName = DependencyUtil.getFormattedFileName( artifact, true );
            File folder = DependencyUtil.getFormattedOutputDirectory( false, true, true, false, true,
                                                                      mojo.outputDirectory, artifact );
            File file = new File( folder, fileName );
            assertTrue( file.exists() );
        }
    }

}
