package org.apache.maven.shared.release.phase;

/*
 * 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.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.release.ReleaseExecutionException;
import org.apache.maven.shared.release.ReleaseFailureException;
import org.apache.maven.shared.release.ReleaseResult;
import org.apache.maven.shared.release.config.ReleaseDescriptor;
import org.apache.maven.shared.release.env.ReleaseEnvironment;
import org.apache.maven.shared.release.versions.DefaultVersionInfo;
import org.apache.maven.shared.release.versions.VersionInfo;
import org.apache.maven.shared.release.versions.VersionParseException;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.components.interactivity.Prompter;
import org.codehaus.plexus.components.interactivity.PrompterException;

/**
 * Check the dependencies of all projects being released to see if there are any unreleased snapshots.
 *
 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 * @todo plugins with no version will be resolved to RELEASE which is not a snapshot, but remains unresolved to this point. This is a potential hole in the check, and should be revisited after the release pom writing is done and resolving versions to verify whether it is.
 * @todo plugins injected by the lifecycle are not tested here. They will be injected with a RELEASE version so are covered under the above point.
 */
@Component( role = ReleasePhase.class, hint = "check-dependency-snapshots" )
public class CheckDependencySnapshotsPhase
    extends AbstractReleasePhase
{
    public static final String RESOLVE_SNAPSHOT_MESSAGE = "There are still some remaining snapshot dependencies.\n";

    public static final String RESOLVE_SNAPSHOT_PROMPT = "Do you want to resolve them now?";

    public static final String RESOLVE_SNAPSHOT_TYPE_MESSAGE = "Dependency type to resolve,";

    public static final String RESOLVE_SNAPSHOT_TYPE_PROMPT =
        "specify the selection number ( 0:All 1:Project Dependencies 2:Plugins 3:Reports 4:Extensions ):";

    /**
     * Component used to prompt for input.
     */
    @Requirement
    private Prompter prompter;
    
    // Be aware of the difference between usedSnapshots and specifiedSnapshots:
    // UsedSnapshots end up on the classpath.
    // SpecifiedSnapshots are defined anywhere in the pom.
    // We'll probably need to introduce specifiedSnapshots as well.
    // @TODO MRELEASE-378: verify custom dependencies in plugins. Be aware of deprecated/removed Components in M3, such as PluginCollector
    // @TODO MRELEASE-763: verify all dependencies in inactive profiles
    
    // Don't prompt for every project in reactor, remember state of questions
    private String resolveSnapshot;

    private String resolveSnapshotType;
    
    @Override
    public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
                                  List<MavenProject> reactorProjects )
        throws ReleaseExecutionException, ReleaseFailureException
    {
        ReleaseResult result = new ReleaseResult();

        if ( !releaseDescriptor.isAllowTimestampedSnapshots() )
        {
            logInfo( result, "Checking dependencies and plugins for snapshots ..." );

            for ( MavenProject project : reactorProjects )
            {
                checkProject( project, releaseDescriptor );
            }
        }
        else
        {
            logInfo( result, "Ignoring SNAPSHOT depenedencies and plugins ..." );
        }
        result.setResultCode( ReleaseResult.SUCCESS );

        return result;
    }

    private void checkProject( MavenProject project, ReleaseDescriptor releaseDescriptor )
        throws ReleaseFailureException, ReleaseExecutionException
    {
        Map<String, Artifact> artifactMap = ArtifactUtils.artifactMapByVersionlessId( project.getArtifacts() );
        
        Set<Artifact> usedSnapshotDependencies = new HashSet<>();

        if ( project.getParentArtifact() != null )
        {
            if ( checkArtifact( project.getParentArtifact(), artifactMap, releaseDescriptor ) )
            {
                usedSnapshotDependencies.add( project.getParentArtifact() );
            }
        }

        Set<Artifact> dependencyArtifacts = project.getArtifacts();
        usedSnapshotDependencies.addAll( checkDependencies( releaseDescriptor, artifactMap, dependencyArtifacts ) );

        //@todo check dependencyManagement

        Set<Artifact> pluginArtifacts = project.getPluginArtifacts();
        Set<Artifact> usedSnapshotPlugins = checkPlugins( releaseDescriptor, artifactMap, pluginArtifacts );

        //@todo check pluginManagement

        Set<Artifact> reportArtifacts = project.getReportArtifacts();
        Set<Artifact> usedSnapshotReports = checkReports( releaseDescriptor, artifactMap, reportArtifacts );

        Set<Artifact> extensionArtifacts = project.getExtensionArtifacts();
        Set<Artifact> usedSnapshotExtensions = checkExtensions( releaseDescriptor, artifactMap, extensionArtifacts );

        //@todo check profiles

        if ( !usedSnapshotDependencies.isEmpty() || !usedSnapshotReports.isEmpty()
                        || !usedSnapshotExtensions.isEmpty() || !usedSnapshotPlugins.isEmpty() )
        {
            if ( releaseDescriptor.isInteractive() )
            {
                resolveSnapshots( usedSnapshotDependencies, usedSnapshotReports, usedSnapshotExtensions,
                                  usedSnapshotPlugins, releaseDescriptor );
            }

            if ( !usedSnapshotDependencies.isEmpty() || !usedSnapshotReports.isEmpty()
                            || !usedSnapshotExtensions.isEmpty() || !usedSnapshotPlugins.isEmpty() )
            {
                StringBuilder message = new StringBuilder();

                printSnapshotDependencies( usedSnapshotDependencies, message );
                printSnapshotDependencies( usedSnapshotReports, message );
                printSnapshotDependencies( usedSnapshotExtensions, message );
                printSnapshotDependencies( usedSnapshotPlugins, message );
                message.append( "in project '" + project.getName() + "' (" + project.getId() + ")" );

                throw new ReleaseFailureException(
                    "Can't release project due to non released dependencies :\n" + message );
            }
        }
    }

    private Set<Artifact> checkPlugins( ReleaseDescriptor releaseDescriptor,
                               Map<String, Artifact> artifactMap, Set<Artifact> pluginArtifacts )
        throws ReleaseExecutionException
    {
        Set<Artifact> usedSnapshotPlugins = new HashSet<>();
        for ( Artifact artifact : pluginArtifacts )
        {
            if ( checkArtifact( artifact, artifactMap, releaseDescriptor ) )
            {
                boolean addToFailures;

                if ( "org.apache.maven.plugins".equals( artifact.getGroupId() ) && "maven-release-plugin".equals(
                    artifact.getArtifactId() ) )
                {
                    // It's a snapshot of the release plugin. Maybe just testing - ask
                    // By default, we fail as for any other plugin
                    if ( releaseDescriptor.isSnapshotReleasePluginAllowed() )
                    {
                        addToFailures = false;
                    }
                    else if ( releaseDescriptor.isInteractive() )
                    {
                        try
                        {
                            String result;
                            if ( !releaseDescriptor.isSnapshotReleasePluginAllowed() )
                            {
                                prompter.showMessage( "This project relies on a SNAPSHOT of the release plugin. "
                                                          + "This may be necessary during testing.\n" );
                                result = prompter.prompt( "Do you want to continue with the release?",
                                                          Arrays.asList( "yes", "no" ), "no" );
                            }
                            else
                            {
                                result = "yes";
                            }

                            if ( result.toLowerCase( Locale.ENGLISH ).startsWith( "y" ) )
                            {
                                addToFailures = false;
                            }
                            else
                            {
                                addToFailures = true;
                            }
                        }
                        catch ( PrompterException e )
                        {
                            throw new ReleaseExecutionException( e.getMessage(), e );
                        }
                    }
                    else
                    {
                        addToFailures = true;
                    }
                }
                else
                {
                    addToFailures = true;
                }

                if ( addToFailures )
                {
                    usedSnapshotPlugins.add( artifact );
                }
            }
        }
        return usedSnapshotPlugins;
    }

    private Set<Artifact> checkDependencies( ReleaseDescriptor releaseDescriptor,
                                    Map<String, Artifact> artifactMap, 
                                    Set<Artifact> dependencyArtifacts )
    {
        Set<Artifact> usedSnapshotDependencies = new HashSet<>();
        for ( Artifact artifact : dependencyArtifacts )
        {
            if ( checkArtifact( artifact, artifactMap, releaseDescriptor ) )
            {
                usedSnapshotDependencies.add( getArtifactFromMap( artifact, artifactMap ) );
            }
        }
        return usedSnapshotDependencies;
    }

    private Set<Artifact> checkReports( ReleaseDescriptor releaseDescriptor,
                               Map<String, Artifact> artifactMap, Set<Artifact> reportArtifacts )
    {
        Set<Artifact> usedSnapshotReports = new HashSet<>();
        for ( Artifact artifact : reportArtifacts )
        {
            if ( checkArtifact( artifact, artifactMap, releaseDescriptor ) )
            {
                //snapshotDependencies.add( artifact );
                usedSnapshotReports.add( artifact );
            }
        }
        return usedSnapshotReports;
    }

    private Set<Artifact> checkExtensions( ReleaseDescriptor releaseDescriptor,
                                  Map<String, Artifact> artifactMap, Set<Artifact> extensionArtifacts )
    {
        Set<Artifact> usedSnapshotExtensions = new HashSet<>();
        for ( Artifact artifact : extensionArtifacts )
        {
            if ( checkArtifact( artifact, artifactMap, releaseDescriptor ) )
            {
                usedSnapshotExtensions.add( artifact );
            }
        }
        return usedSnapshotExtensions;
    }

    private static boolean checkArtifact( Artifact artifact,
                                          Map<String, Artifact> artifactMapByVersionlessId,
                                          ReleaseDescriptor releaseDescriptor )
    {
        Artifact checkArtifact = getArtifactFromMap( artifact, artifactMapByVersionlessId );

        return checkArtifact( checkArtifact, releaseDescriptor );
    }

    private static Artifact getArtifactFromMap( Artifact artifact, Map<String, Artifact> artifactMapByVersionlessId )
    {
        String versionlessId = ArtifactUtils.versionlessKey( artifact );
        Artifact checkArtifact = artifactMapByVersionlessId.get( versionlessId );

        if ( checkArtifact == null )
        {
            checkArtifact = artifact;
        }
        return checkArtifact;
    }

    private static boolean checkArtifact( Artifact artifact, ReleaseDescriptor releaseDescriptor )
    {
        String versionlessKey = ArtifactUtils.versionlessKey( artifact.getGroupId(), artifact.getArtifactId() );
        
        // We are only looking at dependencies external to the project - ignore anything found in the reactor as
        // it's version will be updated
        boolean result = artifact.isSnapshot()
                && !artifact.getBaseVersion().equals( releaseDescriptor.getProjectOriginalVersion( versionlessKey ) );

        // If we have a snapshot but allowTimestampedSnapshots is true, accept the artifact if the version
        // indicates that it is a timestamped snapshot.
        if ( result && releaseDescriptor.isAllowTimestampedSnapshots() )
        {
            result = artifact.getVersion().indexOf( Artifact.SNAPSHOT_VERSION ) >= 0;
        }

        return result;
    }

    @Override
    public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
                                   List<MavenProject> reactorProjects )
        throws ReleaseExecutionException, ReleaseFailureException
    {
        // It makes no modifications, so simulate is the same as execute
        return execute( releaseDescriptor, releaseEnvironment, reactorProjects );
    }

    public void setPrompter( Prompter prompter )
    {
        this.prompter = prompter;
    }

    private StringBuilder printSnapshotDependencies( Set<Artifact> snapshotsSet, StringBuilder message )
    {
        List<Artifact> snapshotsList = new ArrayList<>( snapshotsSet );

        Collections.sort( snapshotsList );

        for ( Artifact artifact : snapshotsList )
        {
            message.append( "    " );

            message.append( artifact );

            message.append( "\n" );
        }

        return message;
    }

    private void resolveSnapshots( Set<Artifact> projectDependencies, Set<Artifact> reportDependencies,
                                   Set<Artifact> extensionDependencies, Set<Artifact> pluginDependencies,
                                   ReleaseDescriptor releaseDescriptor )
        throws ReleaseExecutionException
    {
        try
        {
            if ( resolveSnapshot == null )
            {
                prompter.showMessage( RESOLVE_SNAPSHOT_MESSAGE );
                resolveSnapshot = prompter.prompt( RESOLVE_SNAPSHOT_PROMPT, Arrays.asList( "yes", "no" ), "no" );
            }

            if ( resolveSnapshot.toLowerCase( Locale.ENGLISH ).startsWith( "y" ) )
            {
                if ( resolveSnapshotType == null )
                {
                    prompter.showMessage( RESOLVE_SNAPSHOT_TYPE_MESSAGE );
                    resolveSnapshotType =
                        prompter.prompt( RESOLVE_SNAPSHOT_TYPE_PROMPT, Arrays.asList( "0", "1", "2", "3" ), "1" );
                }

                switch ( Integer.parseInt( resolveSnapshotType.toLowerCase( Locale.ENGLISH ) ) )
                {
                    // all
                    case 0:
                        processSnapshot( projectDependencies, releaseDescriptor );
                        processSnapshot( pluginDependencies, releaseDescriptor );
                        processSnapshot( reportDependencies, releaseDescriptor );
                        processSnapshot( extensionDependencies, releaseDescriptor );
                        break;

                        // project dependencies
                    case 1:
                        processSnapshot( projectDependencies, releaseDescriptor );
                        break;

                        // plugins
                    case 2:
                        processSnapshot( pluginDependencies, releaseDescriptor );
                        break;

                        // reports
                    case 3:
                        processSnapshot( reportDependencies, releaseDescriptor );
                        break;

                        // extensions
                    case 4:
                        processSnapshot( extensionDependencies, releaseDescriptor );
                        break;

                    default:
                }
            }
        }
        catch ( PrompterException | VersionParseException e )
        {
            throw new ReleaseExecutionException( e.getMessage(), e );
        }
    }

    private void processSnapshot( Set<Artifact> snapshotSet, ReleaseDescriptor releaseDescriptor )
        throws PrompterException, VersionParseException
    {
        Iterator<Artifact> iterator = snapshotSet.iterator();

        while ( iterator.hasNext() )
        {
            Artifact currentArtifact = iterator.next();
            String versionlessKey = ArtifactUtils.versionlessKey( currentArtifact );

            VersionInfo versionInfo = new DefaultVersionInfo( currentArtifact.getBaseVersion() );
            releaseDescriptor.addDependencyOriginalVersion( versionlessKey, versionInfo.toString() );

            prompter.showMessage(
                "Dependency '" + versionlessKey + "' is a snapshot (" + currentArtifact.getVersion() + ")\n" );
            String result = prompter.prompt( "Which release version should it be set to?",
                                             versionInfo.getReleaseVersionString() );
            
            releaseDescriptor.addDependencyReleaseVersion( versionlessKey, result );

            iterator.remove();

            // by default, keep the same version for the dependency after release, unless it was previously newer
            // the user may opt to type in something different
            VersionInfo nextVersionInfo = new DefaultVersionInfo( result );

            String nextVersion;
            if ( nextVersionInfo.compareTo( versionInfo ) > 0 )
            {
                nextVersion = nextVersionInfo.toString();
            }
            else
            {
                nextVersion = versionInfo.toString();
            }

            result = prompter.prompt( "What version should the dependency be reset to for development?", nextVersion );
            
            releaseDescriptor.addDependencyDevelopmentVersion( versionlessKey, result );
        }
    }
}