package org.apache.maven.artifact.ant;

/*
 * 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.deployer.ArtifactDeployer;
import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
import org.apache.maven.artifact.metadata.ArtifactMetadata;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import org.apache.maven.model.DistributionManagement;
import org.apache.maven.project.artifact.ProjectArtifactMetadata;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;

/**
 * Deploy task, using maven-artifact.
 *
 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 * @version $Id$
 */
public class DeployTask
    extends InstallDeployTaskSupport
{
    private RemoteRepository remoteRepository;

    private RemoteRepository remoteSnapshotRepository;

    private boolean uniqueVersion = true;

    /**
     * Create a core-Maven deployment ArtifactRepository from a Maven Ant Tasks's RemoteRepository definition.
     * @param repository the remote repository as defined in Ant
     * @return the corresponding ArtifactRepository
     */
    protected ArtifactRepository createDeploymentArtifactRepository( RemoteRepository repository )
    {
        if ( repository.getId().equals( repository.getUrl() ) )
        {
            // MANTTASKS-103: avoid default id set to the url, since it is used for maven-metadata-<id>.xml
            repository.setId( "remote" );
        }

        updateRepositoryAuthentication( repository );
        updateRepositoryProxy( repository );

        ArtifactRepositoryLayout repositoryLayout =
            (ArtifactRepositoryLayout) lookup( ArtifactRepositoryLayout.ROLE, repository.getLayout() );

        ArtifactRepositoryFactory repositoryFactory = null;

        ArtifactRepository artifactRepository;

        try
        {
            repositoryFactory = getArtifactRepositoryFactory( repository );

            artifactRepository =
                repositoryFactory.createDeploymentArtifactRepository( repository.getId(), repository.getUrl(),
                                                                      repositoryLayout, uniqueVersion );
        }
        finally
        {
            releaseArtifactRepositoryFactory( repositoryFactory );
        }

        return artifactRepository;
    }


    protected void doExecute()
    {
        if ( file == null && ( attachedArtifacts.size() == 0 ) )
        {
            throw new BuildException( "You must specify a file and/or an attached artifact "
                + "to deploy to the repository." );
        }

        ArtifactRepository localRepo = createLocalArtifactRepository();

        Pom pom = initializePom( localRepo );

        if ( pom == null )
        {
            throw new BuildException( "A POM element is required to deploy to the repository" );
        }

        Artifact artifact = pom.getArtifact();

        // Deploy the POM
        boolean isPomArtifact = "pom".equals( pom.getPackaging() );
        if ( !isPomArtifact )
        {
            ArtifactMetadata metadata = new ProjectArtifactMetadata( artifact, pom.getFile() );
            artifact.addMetadata( metadata );
        }

        ArtifactRepository deploymentRepository = getDeploymentRepository( pom, artifact );

        log( "Deploying to " + deploymentRepository.getUrl(), Project.MSG_INFO );
        ArtifactDeployer deployer = (ArtifactDeployer) lookup( ArtifactDeployer.ROLE );
        try
        {
            if ( file != null )
            {
                if ( !isPomArtifact )
                {
                    deployer.deploy( file, artifact, deploymentRepository, localRepo );
                }
                else
                {
                    deployer.deploy( pom.getFile(), artifact, deploymentRepository, localRepo );
                }
            }

            // Deploy any attached artifacts
            if ( attachedArtifacts != null )
            {
                for ( Artifact attachedArtifact : pom.getAttachedArtifacts() )
                {
                    deployer.deploy( attachedArtifact.getFile(), attachedArtifact, deploymentRepository, localRepo );
                }
            }
        }
        catch ( ArtifactDeploymentException e )
        {
            throw new BuildException(
                "Error deploying artifact '" + artifact.getDependencyConflictId() + "': " + e.getMessage(), e );
        }
    }

    private ArtifactRepository getDeploymentRepository( Pom pom, Artifact artifact )
    {
        DistributionManagement distributionManagement = pom.getDistributionManagement();

        if ( remoteSnapshotRepository == null && remoteRepository == null )
        {
            if ( distributionManagement != null )
            {
                if ( distributionManagement.getSnapshotRepository() != null )
                {
                    remoteSnapshotRepository = createAntRemoteRepositoryBase( distributionManagement
                        .getSnapshotRepository() );
                    uniqueVersion = distributionManagement.getSnapshotRepository().isUniqueVersion();
                }
                if ( distributionManagement.getRepository() != null )
                {
                    remoteRepository = createAntRemoteRepositoryBase( distributionManagement.getRepository() );
                }
            }
        }

        if ( remoteSnapshotRepository == null )
        {
            remoteSnapshotRepository = remoteRepository;
        }

        ArtifactRepository deploymentRepository;
        if ( artifact.isSnapshot() && remoteSnapshotRepository != null )
        {
            deploymentRepository = createDeploymentArtifactRepository( remoteSnapshotRepository );
        }
        else if ( remoteRepository != null )
        {
            deploymentRepository = createDeploymentArtifactRepository( remoteRepository );
        }
        else
        {
            throw new BuildException(
                "A distributionManagement element or remoteRepository element is required to deploy" );
        }

        return deploymentRepository;
    }

    public RemoteRepository getRemoteRepository()
    {
        return remoteRepository;
    }

    public void addRemoteSnapshotRepository( RemoteRepository remoteSnapshotRepository )
    {
        this.remoteSnapshotRepository = remoteSnapshotRepository;
    }

    public void addRemoteRepository( RemoteRepository remoteRepository )
    {
        this.remoteRepository = remoteRepository;
    }

    public void setUniqueVersion( boolean uniqueVersion )
    {
        this.uniqueVersion = uniqueVersion;
    }

    public boolean getUniqueVersion()
    {
        return uniqueVersion;
    }
}
