package org.eclipse.aether.internal.impl;

/*
 * 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.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Named;

import org.eclipse.aether.RepositoryEvent;
import org.eclipse.aether.RepositoryEvent.EventType;
import org.eclipse.aether.RepositoryException;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.RequestTrace;
import org.eclipse.aether.SyncContext;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.deployment.DeployRequest;
import org.eclipse.aether.deployment.DeployResult;
import org.eclipse.aether.deployment.DeploymentException;
import org.eclipse.aether.impl.Deployer;
import org.eclipse.aether.impl.MetadataGenerator;
import org.eclipse.aether.impl.MetadataGeneratorFactory;
import org.eclipse.aether.impl.OfflineController;
import org.eclipse.aether.impl.RemoteRepositoryManager;
import org.eclipse.aether.impl.RepositoryConnectorProvider;
import org.eclipse.aether.impl.RepositoryEventDispatcher;
import org.eclipse.aether.impl.SyncContextFactory;
import org.eclipse.aether.impl.UpdateCheck;
import org.eclipse.aether.impl.UpdateCheckManager;
import org.eclipse.aether.metadata.MergeableMetadata;
import org.eclipse.aether.metadata.Metadata;
import org.eclipse.aether.repository.LocalRepositoryManager;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.repository.RepositoryPolicy;
import org.eclipse.aether.spi.connector.ArtifactUpload;
import org.eclipse.aether.spi.connector.MetadataDownload;
import org.eclipse.aether.spi.connector.MetadataUpload;
import org.eclipse.aether.spi.connector.RepositoryConnector;
import org.eclipse.aether.spi.io.FileProcessor;
import org.eclipse.aether.spi.locator.Service;
import org.eclipse.aether.spi.locator.ServiceLocator;
import org.eclipse.aether.transfer.ArtifactTransferException;
import org.eclipse.aether.transfer.MetadataNotFoundException;
import org.eclipse.aether.transfer.MetadataTransferException;
import org.eclipse.aether.transfer.NoRepositoryConnectorException;
import org.eclipse.aether.transfer.RepositoryOfflineException;
import org.eclipse.aether.transfer.TransferCancelledException;
import org.eclipse.aether.transfer.TransferEvent;
import org.eclipse.aether.transform.FileTransformer;
import org.eclipse.aether.transform.FileTransformerManager;

/**
 */
@Named
public class DefaultDeployer
    implements Deployer, Service
{
    private FileProcessor fileProcessor;

    private RepositoryEventDispatcher repositoryEventDispatcher;

    private RepositoryConnectorProvider repositoryConnectorProvider;

    private RemoteRepositoryManager remoteRepositoryManager;

    private UpdateCheckManager updateCheckManager;

    private Collection<MetadataGeneratorFactory> metadataFactories = new ArrayList<>();

    private SyncContextFactory syncContextFactory;

    private OfflineController offlineController;

    public DefaultDeployer()
    {
        // enables default constructor
    }

    @SuppressWarnings( "checkstyle:parameternumber" )
    @Inject
    DefaultDeployer( FileProcessor fileProcessor, RepositoryEventDispatcher repositoryEventDispatcher,
                     RepositoryConnectorProvider repositoryConnectorProvider,
                     RemoteRepositoryManager remoteRepositoryManager, UpdateCheckManager updateCheckManager,
                     Set<MetadataGeneratorFactory> metadataFactories, SyncContextFactory syncContextFactory,
                     OfflineController offlineController )
    {
        setFileProcessor( fileProcessor );
        setRepositoryEventDispatcher( repositoryEventDispatcher );
        setRepositoryConnectorProvider( repositoryConnectorProvider );
        setRemoteRepositoryManager( remoteRepositoryManager );
        setUpdateCheckManager( updateCheckManager );
        setMetadataGeneratorFactories( metadataFactories );
        setSyncContextFactory( syncContextFactory );
        setOfflineController( offlineController );
    }

    public void initService( ServiceLocator locator )
    {
        setFileProcessor( locator.getService( FileProcessor.class ) );
        setRepositoryEventDispatcher( locator.getService( RepositoryEventDispatcher.class ) );
        setRepositoryConnectorProvider( locator.getService( RepositoryConnectorProvider.class ) );
        setRemoteRepositoryManager( locator.getService( RemoteRepositoryManager.class ) );
        setUpdateCheckManager( locator.getService( UpdateCheckManager.class ) );
        setMetadataGeneratorFactories( locator.getServices( MetadataGeneratorFactory.class ) );
        setSyncContextFactory( locator.getService( SyncContextFactory.class ) );
        setOfflineController( locator.getService( OfflineController.class ) );
    }

    public DefaultDeployer setFileProcessor( FileProcessor fileProcessor )
    {
        this.fileProcessor = requireNonNull( fileProcessor, "file processor cannot be null" );
        return this;
    }

    public DefaultDeployer setRepositoryEventDispatcher( RepositoryEventDispatcher repositoryEventDispatcher )
    {
        this.repositoryEventDispatcher = requireNonNull(
                repositoryEventDispatcher, "repository event dispatcher cannot be null" );
        return this;
    }

    public DefaultDeployer setRepositoryConnectorProvider( RepositoryConnectorProvider repositoryConnectorProvider )
    {
        this.repositoryConnectorProvider = requireNonNull(
                repositoryConnectorProvider, "repository connector provider cannot be null" );
        return this;
    }

    public DefaultDeployer setRemoteRepositoryManager( RemoteRepositoryManager remoteRepositoryManager )
    {
        this.remoteRepositoryManager = requireNonNull(
                remoteRepositoryManager, "remote repository provider cannot be null" );
        return this;
    }

    public DefaultDeployer setUpdateCheckManager( UpdateCheckManager updateCheckManager )
    {
        this.updateCheckManager = requireNonNull( updateCheckManager, "update check manager cannot be null" );
        return this;
    }

    public DefaultDeployer addMetadataGeneratorFactory( MetadataGeneratorFactory factory )
    {
        metadataFactories.add( requireNonNull( factory, "metadata generator factory cannot be null" ) );
        return this;
    }

    public DefaultDeployer setMetadataGeneratorFactories( Collection<MetadataGeneratorFactory> metadataFactories )
    {
        if ( metadataFactories == null )
        {
            this.metadataFactories = new ArrayList<>();
        }
        else
        {
            this.metadataFactories = metadataFactories;
        }
        return this;
    }

    public DefaultDeployer setSyncContextFactory( SyncContextFactory syncContextFactory )
    {
        this.syncContextFactory = requireNonNull( syncContextFactory, "sync context factory cannot be null" );
        return this;
    }

    public DefaultDeployer setOfflineController( OfflineController offlineController )
    {
        this.offlineController = requireNonNull( offlineController, "offline controller cannot be null" );
        return this;
    }

    public DeployResult deploy( RepositorySystemSession session, DeployRequest request )
        throws DeploymentException
    {
        try
        {
            Utils.checkOffline( session, offlineController, request.getRepository() );
        }
        catch ( RepositoryOfflineException e )
        {
            throw new DeploymentException( "Cannot deploy while " + request.getRepository().getId() + " ("
                + request.getRepository().getUrl() + ") is in offline mode", e );
        }

        try ( SyncContext syncContext = syncContextFactory.newInstance( session, false ) )
        {
            return deploy( syncContext, session, request );
        }
    }

    private DeployResult deploy( SyncContext syncContext, RepositorySystemSession session, DeployRequest request )
        throws DeploymentException
    {
        DeployResult result = new DeployResult( request );

        RequestTrace trace = RequestTrace.newChild( request.getTrace(), request );

        RemoteRepository repository = request.getRepository();

        RepositoryConnector connector;
        try
        {
            connector = repositoryConnectorProvider.newRepositoryConnector( session, repository );
        }
        catch ( NoRepositoryConnectorException e )
        {
            throw new DeploymentException( "Failed to deploy artifacts/metadata: " + e.getMessage(), e );
        }

        try
        {
            List<? extends MetadataGenerator> generators = getMetadataGenerators( session, request );

            FileTransformerManager fileTransformerManager = session.getFileTransformerManager();

            List<ArtifactUpload> artifactUploads = new ArrayList<>();
            List<MetadataUpload> metadataUploads = new ArrayList<>();
            IdentityHashMap<Metadata, Object> processedMetadata = new IdentityHashMap<>();

            EventCatapult catapult = new EventCatapult( session, trace, repository, repositoryEventDispatcher );

            List<Artifact> artifacts = new ArrayList<>( request.getArtifacts() );

            List<Metadata> metadatas = Utils.prepareMetadata( generators, artifacts );

            syncContext.acquire( artifacts, Utils.combine( request.getMetadata(), metadatas ) );

            for ( Metadata metadata : metadatas )
            {
                upload( metadataUploads, session, metadata, repository, connector, catapult );
                processedMetadata.put( metadata, null );
            }

            for ( int i = 0; i < artifacts.size(); i++ )
            {
                Artifact artifact = artifacts.get( i );

                for ( MetadataGenerator generator : generators )
                {
                    artifact = generator.transformArtifact( artifact );
                }

                artifacts.set( i, artifact );

                Collection<FileTransformer> fileTransformers =
                        fileTransformerManager.getTransformersForArtifact( artifact );
                if ( !fileTransformers.isEmpty() )
                {
                    for ( FileTransformer fileTransformer : fileTransformers )
                    {
                        Artifact targetArtifact = fileTransformer.transformArtifact( artifact );

                        ArtifactUpload upload = new ArtifactUpload( targetArtifact, artifact.getFile(),
                                fileTransformer );
                        upload.setTrace( trace );
                        upload.setListener( new ArtifactUploadListener( catapult, upload ) );
                        artifactUploads.add( upload );
                    }
                }
                else
                {
                    ArtifactUpload upload = new ArtifactUpload( artifact, artifact.getFile() );
                    upload.setTrace( trace );
                    upload.setListener( new ArtifactUploadListener( catapult, upload ) );
                    artifactUploads.add( upload );
                }
            }

            connector.put( artifactUploads, null );

            for ( ArtifactUpload upload : artifactUploads )
            {
                if ( upload.getException() != null )
                {
                    throw new DeploymentException( "Failed to deploy artifacts: " + upload.getException().getMessage(),
                                                   upload.getException() );
                }
                result.addArtifact( upload.getArtifact() );
            }

            metadatas = Utils.finishMetadata( generators, artifacts );

            syncContext.acquire( null, metadatas );

            for ( Metadata metadata : metadatas )
            {
                upload( metadataUploads, session, metadata, repository, connector, catapult );
                processedMetadata.put( metadata, null );
            }

            for ( Metadata metadata : request.getMetadata() )
            {
                if ( !processedMetadata.containsKey( metadata ) )
                {
                    upload( metadataUploads, session, metadata, repository, connector, catapult );
                    processedMetadata.put( metadata, null );
                }
            }

            connector.put( null, metadataUploads );

            for ( MetadataUpload upload : metadataUploads )
            {
                if ( upload.getException() != null )
                {
                    throw new DeploymentException( "Failed to deploy metadata: " + upload.getException().getMessage(),
                                                   upload.getException() );
                }
                result.addMetadata( upload.getMetadata() );
            }
        }
        finally
        {
            connector.close();
        }

        return result;
    }

    private List<? extends MetadataGenerator> getMetadataGenerators( RepositorySystemSession session,
                                                                     DeployRequest request )
    {
        PrioritizedComponents<MetadataGeneratorFactory> factories =
            Utils.sortMetadataGeneratorFactories( session, this.metadataFactories );

        List<MetadataGenerator> generators = new ArrayList<>();

        for ( PrioritizedComponent<MetadataGeneratorFactory> factory : factories.getEnabled() )
        {
            MetadataGenerator generator = factory.getComponent().newInstance( session, request );
            if ( generator != null )
            {
                generators.add( generator );
            }
        }

        return generators;
    }

    private void upload( Collection<MetadataUpload> metadataUploads, RepositorySystemSession session,
                         Metadata metadata, RemoteRepository repository, RepositoryConnector connector,
                         EventCatapult catapult )
        throws DeploymentException
    {
        LocalRepositoryManager lrm = session.getLocalRepositoryManager();
        File basedir = lrm.getRepository().getBasedir();

        File dstFile = new File( basedir, lrm.getPathForRemoteMetadata( metadata, repository, "" ) );

        if ( metadata instanceof MergeableMetadata )
        {
            if ( !( (MergeableMetadata) metadata ).isMerged() )
            {
                RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_RESOLVING );
                event.setTrace( catapult.getTrace() );
                event.setMetadata( metadata );
                event.setRepository( repository );
                repositoryEventDispatcher.dispatch( event.build() );

                event = new RepositoryEvent.Builder( session, EventType.METADATA_DOWNLOADING );
                event.setTrace( catapult.getTrace() );
                event.setMetadata( metadata );
                event.setRepository( repository );
                repositoryEventDispatcher.dispatch( event.build() );

                RepositoryPolicy policy = getPolicy( session, repository, metadata.getNature() );
                MetadataDownload download = new MetadataDownload();
                download.setMetadata( metadata );
                download.setFile( dstFile );
                download.setChecksumPolicy( policy.getChecksumPolicy() );
                download.setListener( SafeTransferListener.wrap( session ) );
                download.setTrace( catapult.getTrace() );
                connector.get( null, Arrays.asList( download ) );

                Exception error = download.getException();

                if ( error instanceof MetadataNotFoundException )
                {
                    dstFile.delete();
                }

                event = new RepositoryEvent.Builder( session, EventType.METADATA_DOWNLOADED );
                event.setTrace( catapult.getTrace() );
                event.setMetadata( metadata );
                event.setRepository( repository );
                event.setException( error );
                event.setFile( dstFile );
                repositoryEventDispatcher.dispatch( event.build() );

                event = new RepositoryEvent.Builder( session, EventType.METADATA_RESOLVED );
                event.setTrace( catapult.getTrace() );
                event.setMetadata( metadata );
                event.setRepository( repository );
                event.setException( error );
                event.setFile( dstFile );
                repositoryEventDispatcher.dispatch( event.build() );

                if ( error != null && !( error instanceof MetadataNotFoundException ) )
                {
                    throw new DeploymentException( "Failed to retrieve remote metadata " + metadata + ": "
                        + error.getMessage(), error );
                }
            }

            try
            {
                ( (MergeableMetadata) metadata ).merge( dstFile, dstFile );
            }
            catch ( RepositoryException e )
            {
                throw new DeploymentException( "Failed to update metadata " + metadata + ": " + e.getMessage(), e );
            }
        }
        else
        {
            if ( metadata.getFile() == null )
            {
                throw new DeploymentException( "Failed to update metadata " + metadata + ": No file attached." );
            }
            try
            {
                fileProcessor.copy( metadata.getFile(), dstFile );
            }
            catch ( IOException e )
            {
                throw new DeploymentException( "Failed to update metadata " + metadata + ": " + e.getMessage(), e );
            }
        }

        UpdateCheck<Metadata, MetadataTransferException> check = new UpdateCheck<>();
        check.setItem( metadata );
        check.setFile( dstFile );
        check.setRepository( repository );
        check.setAuthoritativeRepository( repository );
        updateCheckManager.touchMetadata( session, check );

        MetadataUpload upload = new MetadataUpload( metadata, dstFile );
        upload.setTrace( catapult.getTrace() );
        upload.setListener( new MetadataUploadListener( catapult, upload ) );
        metadataUploads.add( upload );
    }

    private RepositoryPolicy getPolicy( RepositorySystemSession session, RemoteRepository repository,
                                        Metadata.Nature nature )
    {
        boolean releases = !Metadata.Nature.SNAPSHOT.equals( nature );
        boolean snapshots = !Metadata.Nature.RELEASE.equals( nature );
        return remoteRepositoryManager.getPolicy( session, repository, releases, snapshots );
    }

    static final class EventCatapult
    {

        private final RepositorySystemSession session;

        private final RequestTrace trace;

        private final RemoteRepository repository;

        private final RepositoryEventDispatcher dispatcher;

        EventCatapult( RepositorySystemSession session, RequestTrace trace, RemoteRepository repository,
                              RepositoryEventDispatcher dispatcher )
        {
            this.session = session;
            this.trace = trace;
            this.repository = repository;
            this.dispatcher = dispatcher;
        }

        public RepositorySystemSession getSession()
        {
            return session;
        }

        public RequestTrace getTrace()
        {
            return trace;
        }

        public void artifactDeploying( Artifact artifact, File file )
        {
            RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_DEPLOYING );
            event.setTrace( trace );
            event.setArtifact( artifact );
            event.setRepository( repository );
            event.setFile( file );

            dispatcher.dispatch( event.build() );
        }

        public void artifactDeployed( Artifact artifact, File file, ArtifactTransferException exception )
        {
            RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_DEPLOYED );
            event.setTrace( trace );
            event.setArtifact( artifact );
            event.setRepository( repository );
            event.setFile( file );
            event.setException( exception );

            dispatcher.dispatch( event.build() );
        }

        public void metadataDeploying( Metadata metadata, File file )
        {
            RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_DEPLOYING );
            event.setTrace( trace );
            event.setMetadata( metadata );
            event.setRepository( repository );
            event.setFile( file );

            dispatcher.dispatch( event.build() );
        }

        public void metadataDeployed( Metadata metadata, File file, Exception exception )
        {
            RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_DEPLOYED );
            event.setTrace( trace );
            event.setMetadata( metadata );
            event.setRepository( repository );
            event.setFile( file );
            event.setException( exception );

            dispatcher.dispatch( event.build() );
        }

    }

    static final class ArtifactUploadListener
        extends SafeTransferListener
    {

        private final EventCatapult catapult;

        private final ArtifactUpload transfer;

        ArtifactUploadListener( EventCatapult catapult, ArtifactUpload transfer )
        {
            super( catapult.getSession() );
            this.catapult = catapult;
            this.transfer = transfer;
        }

        @Override
        public void transferInitiated( TransferEvent event )
            throws TransferCancelledException
        {
            super.transferInitiated( event );
            catapult.artifactDeploying( transfer.getArtifact(), transfer.getFile() );
        }

        @Override
        public void transferFailed( TransferEvent event )
        {
            super.transferFailed( event );
            catapult.artifactDeployed( transfer.getArtifact(), transfer.getFile(), transfer.getException() );
        }

        @Override
        public void transferSucceeded( TransferEvent event )
        {
            super.transferSucceeded( event );
            catapult.artifactDeployed( transfer.getArtifact(), transfer.getFile(), null );
        }

    }

    static final class MetadataUploadListener
        extends SafeTransferListener
    {

        private final EventCatapult catapult;

        private final MetadataUpload transfer;

        MetadataUploadListener( EventCatapult catapult, MetadataUpload transfer )
        {
            super( catapult.getSession() );
            this.catapult = catapult;
            this.transfer = transfer;
        }

        @Override
        public void transferInitiated( TransferEvent event )
            throws TransferCancelledException
        {
            super.transferInitiated( event );
            catapult.metadataDeploying( transfer.getMetadata(), transfer.getFile() );
        }

        @Override
        public void transferFailed( TransferEvent event )
        {
            super.transferFailed( event );
            catapult.metadataDeployed( transfer.getMetadata(), transfer.getFile(), transfer.getException() );
        }

        @Override
        public void transferSucceeded( TransferEvent event )
        {
            super.transferSucceeded( event );
            catapult.metadataDeployed( transfer.getMetadata(), transfer.getFile(), null );
        }

    }

}
