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.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.model.Build;
import org.apache.maven.model.BuildBase;
import org.apache.maven.model.Model;
import org.apache.maven.model.ModelBase;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.Profile;
import org.apache.maven.project.MavenProject;
import org.apache.maven.scm.ScmException;
import org.apache.maven.scm.ScmFileSet;
import org.apache.maven.scm.command.edit.EditScmResult;
import org.apache.maven.scm.manager.NoSuchScmProviderException;
import org.apache.maven.scm.provider.ScmProvider;
import org.apache.maven.scm.repository.ScmRepository;
import org.apache.maven.scm.repository.ScmRepositoryException;
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.scm.ReleaseScmCommandException;
import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
import org.apache.maven.shared.release.scm.ScmTranslator;
import org.apache.maven.shared.release.transform.ModelETLRequest;
import org.apache.maven.shared.release.transform.MavenCoordinate;
import org.apache.maven.shared.release.transform.ModelETL;
import org.apache.maven.shared.release.transform.ModelETLFactory;
import org.apache.maven.shared.release.transform.jdom.JDomModelETLFactory;
import org.apache.maven.shared.release.util.ReleaseUtil;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.util.StringUtils;

/**
 * Base class for rewriting phases.
 *
 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 */
public abstract class AbstractRewritePomsPhase
    extends AbstractReleasePhase
{
    /**
     * Tool that gets a configured SCM repository from release configuration.
     */
    @Requirement
    private ScmRepositoryConfigurator scmRepositoryConfigurator;

    @Requirement( role = ModelETLFactory.class )
    private Map<String, ModelETLFactory> modelETLFactories;

    /**
     * Use jdom-sax as default
     */
    private String modelETL = JDomModelETLFactory.ROLE_HINT;

    /**
     * SCM URL translators mapped by provider name.
     */
    @Requirement( role = ScmTranslator.class )
    private Map<String, ScmTranslator> scmTranslators;

    protected final Map<String, ScmTranslator> getScmTranslators()
    {
        return scmTranslators;
    }

    private String ls = ReleaseUtil.LS;

    public void setLs( String ls )
    {
        this.ls = ls;
    }

    public void setModelETL( String modelETL )
    {
        this.modelETL = modelETL;
    }

    protected abstract String getPomSuffix();

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

        transform( releaseDescriptor, releaseEnvironment, reactorProjects, false, result );

        result.setResultCode( ReleaseResult.SUCCESS );

        return result;
    }

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

        transform( releaseDescriptor, releaseEnvironment, reactorProjects, true, result );

        result.setResultCode( ReleaseResult.SUCCESS );

        return result;
    }

    @Override
    public ReleaseResult clean( List<MavenProject> reactorProjects )
    {
        ReleaseResult result = new ReleaseResult();

        super.clean( reactorProjects );

        if ( reactorProjects != null )
        {
            for ( MavenProject project : reactorProjects )
            {
                File pomFile = ReleaseUtil.getStandardPom( project );
                // MRELEASE-273 : if no pom
                if ( pomFile != null )
                {
                    File file = new File( pomFile.getParentFile(), pomFile.getName() + "." + getPomSuffix() );
                    if ( file.exists() )
                    {
                        file.delete();
                    }
                }
            }
        }

        result.setResultCode( ReleaseResult.SUCCESS );

        return result;
    }

    private void transform( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
                            List<MavenProject> reactorProjects, boolean simulate, ReleaseResult result )
        throws ReleaseExecutionException, ReleaseFailureException
    {
        for ( MavenProject project : reactorProjects )
        {
            logInfo( result, "Transforming '" + project.getName() + "'..." );

            transformProject( project, releaseDescriptor, releaseEnvironment, reactorProjects, simulate, result );
        }
    }

    private void transformProject( MavenProject project, ReleaseDescriptor releaseDescriptor,
                                   ReleaseEnvironment releaseEnvironment, List<MavenProject> reactorProjects,
                                   boolean simulate, ReleaseResult result )
        throws ReleaseExecutionException, ReleaseFailureException
    {
        File pomFile = ReleaseUtil.getStandardPom( project );

        ModelETLRequest request = new ModelETLRequest();
        request.setLineSeparator( ls );
        request.setProject( project );
        request.setReleaseDescriptor( releaseDescriptor );

        ModelETL etl = modelETLFactories.get( modelETL ).newInstance( request );

        etl.extract( pomFile );

        ScmRepository scmRepository = null;
        ScmProvider provider = null;

        if ( isUpdateScm() )
        {
            try
            {
                scmRepository = scmRepositoryConfigurator.getConfiguredRepository( releaseDescriptor,
                                                                                   releaseEnvironment.getSettings() );

                provider = scmRepositoryConfigurator.getRepositoryProvider( scmRepository );
            }
            catch ( ScmRepositoryException e )
            {
                throw new ReleaseScmRepositoryException( e.getMessage(), e.getValidationMessages() );
            }
            catch ( NoSuchScmProviderException e )
            {
                throw new ReleaseExecutionException( "Unable to configure SCM repository: " + e.getMessage(), e );
            }
        }

        transformDocument( project, etl.getModel(), releaseDescriptor, reactorProjects, scmRepository,
                           result, simulate );

        File outputFile;
        if ( simulate )
        {
            outputFile = new File( pomFile.getParentFile(), pomFile.getName() + "." + getPomSuffix() );
        }
        else
        {
            outputFile = pomFile;
            prepareScm( pomFile, releaseDescriptor, scmRepository, provider );
        }
        etl.load( outputFile );

    }

    private void transformDocument( MavenProject project, Model modelTarget, ReleaseDescriptor releaseDescriptor,
                                    List<MavenProject> reactorProjects, ScmRepository scmRepository,
                                    ReleaseResult result, boolean simulate )
        throws ReleaseExecutionException, ReleaseFailureException
    {
        Model model = project.getModel();

        Properties properties = modelTarget.getProperties();

        String parentVersion = rewriteParent( project, modelTarget, releaseDescriptor, simulate );

        String projectId = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );

        rewriteVersion( modelTarget, releaseDescriptor, projectId, project, parentVersion );

        Build buildTarget = modelTarget.getBuild();
        if ( buildTarget != null )
        {
            // profile.build.extensions doesn't exist, so only rewrite project.build.extensions
            rewriteArtifactVersions( toMavenCoordinates( buildTarget.getExtensions() ), 
                                     model, properties, result, releaseDescriptor, simulate );

            rewriteArtifactVersions( toMavenCoordinates( buildTarget.getPlugins() ), 
                                     model, properties, result, releaseDescriptor, simulate );

            for ( Plugin plugin : buildTarget.getPlugins() )
            {
                rewriteArtifactVersions( toMavenCoordinates( plugin.getDependencies() ),
                                         model, properties,
                                         result, releaseDescriptor, simulate );
            }

            if ( buildTarget.getPluginManagement() != null )
            {
                rewriteArtifactVersions( toMavenCoordinates( buildTarget.getPluginManagement().getPlugins() ), model,
                                         properties, result, releaseDescriptor, simulate );

                for ( Plugin plugin : buildTarget.getPluginManagement().getPlugins() )
                {
                    rewriteArtifactVersions( toMavenCoordinates( plugin.getDependencies() ), model, properties, result,
                                             releaseDescriptor, simulate );
                }
            }
        }

        for ( Profile profile : modelTarget.getProfiles() )
        {
            BuildBase profileBuild = profile.getBuild();
            if ( profileBuild != null )
            {
                rewriteArtifactVersions( toMavenCoordinates( profileBuild.getPlugins() ), model, properties, result,
                                         releaseDescriptor, simulate );

                for ( Plugin plugin : profileBuild.getPlugins() )
                {
                    rewriteArtifactVersions( toMavenCoordinates( plugin.getDependencies() ), model, properties, result,
                                             releaseDescriptor, simulate );
                }

                if ( profileBuild.getPluginManagement() != null )
                {
                    rewriteArtifactVersions( toMavenCoordinates( profileBuild.getPluginManagement().getPlugins() ),
                                             model, properties, result, releaseDescriptor, simulate );

                    for ( Plugin plugin : profileBuild.getPluginManagement().getPlugins() )
                    {
                        rewriteArtifactVersions( toMavenCoordinates( plugin.getDependencies() ), model, properties,
                                                 result, releaseDescriptor, simulate );
                    }
                }
            }
        }

        List<ModelBase> modelBases = new ArrayList<>();
        modelBases.add( modelTarget );
        modelBases.addAll( modelTarget.getProfiles() );

        for ( ModelBase modelBase : modelBases )
        {
            rewriteArtifactVersions( toMavenCoordinates( modelBase.getDependencies() ), model, properties, result,
                                     releaseDescriptor, simulate );

            if ( modelBase.getDependencyManagement() != null )
            {
                rewriteArtifactVersions( toMavenCoordinates( modelBase.getDependencyManagement().getDependencies() ),
                                         model, properties, result, releaseDescriptor, simulate );
            }

            if ( modelBase.getReporting() != null )
            {
                rewriteArtifactVersions( toMavenCoordinates( modelBase.getReporting().getPlugins() ), model, properties,
                                         result, releaseDescriptor, simulate );
            }
        }

        String commonBasedir;
        try
        {
            commonBasedir = ReleaseUtil.getCommonBasedir( reactorProjects );
        }
        catch ( IOException e )
        {
            throw new ReleaseExecutionException( "Exception occurred while calculating common basedir: "
                + e.getMessage(), e );
        }

        transformScm( project, modelTarget, releaseDescriptor, projectId, scmRepository, result,
                      commonBasedir );
    }

    private void rewriteVersion( Model modelTarget, ReleaseDescriptor releaseDescriptor, String projectId,
                                 MavenProject project, String parentVersion )
        throws ReleaseFailureException
    {
        String version = getNextVersion( releaseDescriptor, projectId );
        if ( version == null )
        {
            throw new ReleaseFailureException( "Version for '" + project.getName() + "' was not mapped" );
        }

        modelTarget.setVersion( version );
    }

    private String rewriteParent( MavenProject project, Model targetModel, 
                                  ReleaseDescriptor releaseDescriptor, boolean simulate )
        throws ReleaseFailureException
    {
        String parentVersion = null;
        if ( project.hasParent() )
        {
            MavenProject parent = project.getParent();
            String key = ArtifactUtils.versionlessKey( parent.getGroupId(), parent.getArtifactId() );
            parentVersion = getNextVersion( releaseDescriptor, key );
            if ( parentVersion == null )
            {
                //MRELEASE-317
                parentVersion = getResolvedSnapshotVersion( key, releaseDescriptor );
            }
            if ( parentVersion == null )
            {
                String original = getOriginalVersion( releaseDescriptor, key, simulate );
                if ( parent.getVersion().equals( original ) )
                {
                    throw new ReleaseFailureException( "Version for parent '" + parent.getName() + "' was not mapped" );
                }
            }
            else
            {
                targetModel.getParent().setVersion( parentVersion );
            }
        }
        return parentVersion;
    }

    private void rewriteArtifactVersions( Collection<MavenCoordinate> elements, Model projectModel,
                                          Properties properties, ReleaseResult result,
                                          ReleaseDescriptor releaseDescriptor, boolean simulate )
        throws ReleaseExecutionException, ReleaseFailureException
    {
        if ( elements == null )
        {
            return;
        }
        String projectId = ArtifactUtils.versionlessKey( projectModel.getGroupId(), projectModel.getArtifactId() );
        for ( MavenCoordinate coordinate : elements )
        {
            String rawVersion = coordinate.getVersion();
            if ( rawVersion == null )
            {
                // managed dependency or unversioned plugin
                continue;
            }

            String rawGroupId = coordinate.getGroupId();
            if ( rawGroupId == null )
            {
                if ( "plugin".equals( coordinate.getName() ) )
                {
                    rawGroupId = "org.apache.maven.plugins";
                }
                else
                {
                    // incomplete dependency
                    continue;
                }
            }
            String groupId = ReleaseUtil.interpolate( rawGroupId, projectModel );

            String rawArtifactId = coordinate.getArtifactId();
            if ( rawArtifactId == null )
            {
                // incomplete element
                continue;
            }
            String artifactId = ReleaseUtil.interpolate( rawArtifactId, projectModel );

            String key = ArtifactUtils.versionlessKey( groupId, artifactId );
            String resolvedSnapshotVersion = getResolvedSnapshotVersion( key, releaseDescriptor );
            String mappedVersion = getNextVersion( releaseDescriptor, key );
            String originalVersion = getOriginalVersion( releaseDescriptor, key, simulate );
            if ( originalVersion == null )
            {
                originalVersion = getOriginalResolvedSnapshotVersion( key, releaseDescriptor );
            }

            // MRELEASE-220
            if ( mappedVersion != null && mappedVersion.endsWith( Artifact.SNAPSHOT_VERSION )
                && !rawVersion.endsWith( Artifact.SNAPSHOT_VERSION ) && !releaseDescriptor.isUpdateDependencies() )
            {
                continue;
            }

            if ( mappedVersion != null )
            {
                if ( rawVersion.equals( originalVersion ) )
                {
                    logInfo( result, "  Updating " + artifactId + " to " + mappedVersion );
                    coordinate.setVersion( mappedVersion );
                }
                else if ( rawVersion.matches( "\\$\\{.+\\}" ) )
                {
                    String expression = rawVersion.substring( 2, rawVersion.length() - 1 );

                    if ( expression.startsWith( "project." ) || expression.startsWith( "pom." )
                        || "version".equals( expression ) )
                    {
                        if ( !mappedVersion.equals( getNextVersion( releaseDescriptor, projectId ) ) )
                        {
                            logInfo( result, "  Updating " + artifactId + " to " + mappedVersion );
                            coordinate.setVersion( mappedVersion );
                        }
                        else
                        {
                            logInfo( result, "  Ignoring artifact version update for expression " + rawVersion );
                        }
                    }
                    else if ( properties != null )
                    {
                        // version is an expression, check for properties to update instead

                        String propertyValue = properties.getProperty( expression );

                        if ( propertyValue != null )
                        {
                            if ( propertyValue.equals( originalVersion ) )
                            {
                                logInfo( result, "  Updating " + rawVersion + " to " + mappedVersion );
                                // change the property only if the property is the same as what's in the reactor
                                properties.setProperty( expression, mappedVersion );
                            }
                            else if ( mappedVersion.equals( propertyValue ) )
                            {
                                // this property may have been updated during processing a sibling.
                                logInfo( result, "  Ignoring artifact version update for expression " + rawVersion
                                    + " because it is already updated" );
                            }
                            else if ( !mappedVersion.equals( rawVersion ) )
                            {
                                if ( mappedVersion.matches( "\\$\\{project.+\\}" )
                                    || mappedVersion.matches( "\\$\\{pom.+\\}" )
                                    || "${version}".equals( mappedVersion ) )
                                {
                                    logInfo( result, "  Ignoring artifact version update for expression "
                                        + mappedVersion );
                                    // ignore... we cannot update this expression
                                }
                                else
                                {
                                    // the value of the expression conflicts with what the user wanted to release
                                    throw new ReleaseFailureException( "The artifact (" + key + ") requires a "
                                        + "different version (" + mappedVersion + ") than what is found ("
                                        + propertyValue + ") for the expression (" + expression + ") in the "
                                        + "project (" + projectId + ")." );
                                }
                            }
                        }
                        else
                        {
                            // the expression used to define the version of this artifact may be inherited
                            // TODO needs a better error message, what pom? what dependency?
                            throw new ReleaseFailureException( "The version could not be updated: " + rawVersion );
                        }
                    }
                }
                else
                {
                    // different/previous version not related to current release
                }
            }
            else if ( resolvedSnapshotVersion != null )
            {
                logInfo( result, "  Updating " + artifactId + " to " + resolvedSnapshotVersion );

                coordinate.setVersion( resolvedSnapshotVersion );
            }
            else
            {
                // artifact not related to current release
            }
        }
    }

    private void prepareScm( File pomFile, ReleaseDescriptor releaseDescriptor, ScmRepository repository,
                           ScmProvider provider )
        throws ReleaseExecutionException, ReleaseScmCommandException
    {
        try
        {
            if ( isUpdateScm() && ( releaseDescriptor.isScmUseEditMode() || provider.requiresEditMode() ) )
            {
                EditScmResult result = provider.edit( repository, new ScmFileSet(
                    new File( releaseDescriptor.getWorkingDirectory() ), pomFile ) );

                if ( !result.isSuccess() )
                {
                    throw new ReleaseScmCommandException( "Unable to enable editing on the POM", result );
                }
            }
        }
        catch ( ScmException e )
        {
            throw new ReleaseExecutionException( "An error occurred enabling edit mode: " + e.getMessage(), e );
        }
    }


    protected abstract String getResolvedSnapshotVersion( String artifactVersionlessKey,
                                                          ReleaseDescriptor releaseDscriptor );

    protected abstract String getOriginalVersion( ReleaseDescriptor releaseDescriptor, String projectKey,
                                                  boolean simulate );

    protected abstract String getNextVersion( ReleaseDescriptor releaseDescriptor, String key );

    protected abstract void transformScm( MavenProject project, Model modelTarget, ReleaseDescriptor releaseDescriptor,
                                          String projectId, ScmRepository scmRepository,
                                          ReleaseResult result, String commonBasedir )
        throws ReleaseExecutionException;

    /**
     *
     * @return {@code true} if the SCM-section should be updated, otherwise {@code false}
     * @since 2.4
     */
    protected boolean isUpdateScm()
    {
        return true;
    }

    protected String getOriginalResolvedSnapshotVersion( String artifactVersionlessKey,
                                                         ReleaseDescriptor releaseDescriptor )
    {
        return releaseDescriptor.getDependencyOriginalVersion( artifactVersionlessKey );
    }

    /**
     * Determines the relative path from trunk to tag, and adds this relative path
     * to the url.
     *
     * @param trunkPath - The trunk url
     * @param tagPath   - The tag base
     * @param urlPath   - scm.url or scm.connection
     * @return The url path for the tag.
     */
    protected static String translateUrlPath( String trunkPath, String tagPath, String urlPath )
    {
        trunkPath = trunkPath.trim();
        tagPath = tagPath.trim();
        //Strip the slash at the end if one is present
        if ( trunkPath.endsWith( "/" ) )
        {
            trunkPath = trunkPath.substring( 0, trunkPath.length() - 1 );
        }
        if ( tagPath.endsWith( "/" ) )
        {
            tagPath = tagPath.substring( 0, tagPath.length() - 1 );
        }
        char[] tagPathChars = trunkPath.toCharArray();
        char[] trunkPathChars = tagPath.toCharArray();
        // Find the common path between trunk and tags
        int i = 0;
        while ( ( i < tagPathChars.length ) && ( i < trunkPathChars.length ) && tagPathChars[i] == trunkPathChars[i] )
        {
            ++i;
        }
        // If there is nothing common between trunk and tags, or the relative
        // path does not exist in the url, then just return the tag.
        if ( i == 0 || urlPath.indexOf( trunkPath.substring( i ) ) < 0 )
        {
            return tagPath;
        }
        else
        {
            return StringUtils.replace( urlPath, trunkPath.substring( i ), tagPath.substring( i ) );
        }
    }

    private Collection<MavenCoordinate> toMavenCoordinates( List<?> objects )
    {
        Collection<MavenCoordinate> coordinates = new ArrayList<>( objects.size() );
        for ( Object object : objects )
        {
            if ( object instanceof MavenCoordinate )
            {
                coordinates.add( (MavenCoordinate) object );
            }
            else
            {
                throw new UnsupportedOperationException();
            }
        }
        return coordinates;
    }


}
