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

/*
 * 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.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import org.apache.maven.shared.release.scm.IdentifiedScm;

/**
 * Class providing utility methods used during the release process
 *
 * @author <a href="mailto:jwhitlock@apache.org">Jeremy Whitlock</a>
 */
public class ReleaseUtils
{
    private ReleaseUtils()
    {
        // nothing to see here
    }

    /**
     * Merge two descriptors together. All SCM settings are overridden by the merge descriptor, as is the
     * <code>workingDirectory</code> field. The <code>completedPhase</code> field is used as
     * a default from the merge descriptor, but not overridden if it exists.
     *
     * @param mergeInto  the descriptor to be merged into
     * @param toBeMerged the descriptor to merge into mergeInto
     * @return ReleaseDescriptor the merged descriptor
     */
    public static ReleaseDescriptor merge( ReleaseDescriptor mergeInto, ReleaseDescriptor toBeMerged )
    {
        // Overridden if configured from the caller
        mergeInto.setScmId( mergeOverride( mergeInto.getScmId(), toBeMerged.getScmId() ) );
        mergeInto.setScmSourceUrl( mergeOverride( mergeInto.getScmSourceUrl(), toBeMerged.getScmSourceUrl() ) );
        mergeInto.setScmCommentPrefix(
            mergeOverride( mergeInto.getScmCommentPrefix(), toBeMerged.getScmCommentPrefix() ) );
        mergeInto.setScmReleaseLabel( mergeOverride( mergeInto.getScmReleaseLabel(),
                                                     toBeMerged.getScmReleaseLabel() ) );
        mergeInto.setScmTagBase( mergeOverride( mergeInto.getScmTagBase(), toBeMerged.getScmTagBase() ) );
        mergeInto.setScmTagNameFormat(
            mergeOverride( mergeInto.getScmTagNameFormat(), toBeMerged.getScmTagNameFormat() ) );
        mergeInto.setScmBranchBase( mergeOverride( mergeInto.getScmBranchBase(), toBeMerged.getScmBranchBase() ) );
        mergeInto.setScmUsername( mergeOverride( mergeInto.getScmUsername(), toBeMerged.getScmUsername() ) );
        mergeInto.setScmPassword( mergeOverride( mergeInto.getScmPassword(), toBeMerged.getScmPassword() ) );
        mergeInto.setScmPrivateKey( mergeOverride( mergeInto.getScmPrivateKey(), toBeMerged.getScmPrivateKey() ) );
        mergeInto.setScmPrivateKeyPassPhrase(
            mergeOverride( mergeInto.getScmPrivateKeyPassPhrase(), toBeMerged.getScmPrivateKeyPassPhrase() ) );
        mergeInto.setScmCommentPrefix(
            mergeOverride( mergeInto.getScmCommentPrefix(), toBeMerged.getScmCommentPrefix() ) );
        mergeInto.setAdditionalArguments(
            mergeOverride( mergeInto.getAdditionalArguments(), toBeMerged.getAdditionalArguments() ) );
        mergeInto.setPreparationGoals(
            mergeOverride( mergeInto.getPreparationGoals(), toBeMerged.getPreparationGoals() ) );
        mergeInto.setCompletionGoals(
            mergeOverride( mergeInto.getCompletionGoals(), toBeMerged.getCompletionGoals() ) );
        mergeInto.setPerformGoals( mergeOverride( mergeInto.getPerformGoals(), toBeMerged.getPerformGoals() ) );
        mergeInto.setPomFileName( mergeOverride( mergeInto.getPomFileName(), toBeMerged.getPomFileName() ) );
        mergeInto.setCheckModificationExcludes( toBeMerged.getCheckModificationExcludes() );
        mergeInto.setScmUseEditMode( toBeMerged.isScmUseEditMode() );
        mergeInto.setAddSchema( toBeMerged.isAddSchema() );
        mergeInto.setGenerateReleasePoms( toBeMerged.isGenerateReleasePoms() );
        mergeInto.setInteractive( toBeMerged.isInteractive() );
        mergeInto.setUpdateDependencies( toBeMerged.isUpdateDependencies() );
        mergeInto.setCommitByProject( mergeOverride( mergeInto.isCommitByProject(), toBeMerged.isCommitByProject(),
                                                     false ) );
        mergeInto.setUseReleaseProfile( toBeMerged.isUseReleaseProfile() );
        mergeInto.setBranchCreation( toBeMerged.isBranchCreation() );
        mergeInto.setUpdateBranchVersions( toBeMerged.isUpdateBranchVersions() );
        mergeInto.setUpdateWorkingCopyVersions( toBeMerged.isUpdateWorkingCopyVersions() );
        mergeInto.setSuppressCommitBeforeTagOrBranch( toBeMerged.isSuppressCommitBeforeTagOrBranch() );
        mergeInto.setUpdateVersionsToSnapshot( toBeMerged.isUpdateVersionsToSnapshot() );
        mergeInto.setAllowTimestampedSnapshots( toBeMerged.isAllowTimestampedSnapshots() );
        mergeInto.setSnapshotReleasePluginAllowed( toBeMerged.isSnapshotReleasePluginAllowed() );
        mergeInto.setAutoVersionSubmodules( toBeMerged.isAutoVersionSubmodules() );
        mergeInto.setDefaultReleaseVersion( mergeOverride( mergeInto.getDefaultReleaseVersion(),
                                                           toBeMerged.getDefaultReleaseVersion() ) );
        mergeInto.setDefaultDevelopmentVersion( mergeOverride( mergeInto.getDefaultDevelopmentVersion(),
                                                               toBeMerged.getDefaultDevelopmentVersion() ) );
        mergeInto.setRemoteTagging( toBeMerged.isRemoteTagging() );
        mergeInto.setLocalCheckout( toBeMerged.isLocalCheckout() );
        mergeInto.setPushChanges( toBeMerged.isPushChanges() );
        mergeInto.setWaitBeforeTagging( toBeMerged.getWaitBeforeTagging() );

        // If the user specifies versions, these should be override the existing versions
        if ( toBeMerged.getReleaseVersions() != null )
        {
            mergeInto.getReleaseVersions().putAll( toBeMerged.getReleaseVersions() );
        }
        if ( toBeMerged.getDevelopmentVersions() != null )
        {
            mergeInto.getDevelopmentVersions().putAll( toBeMerged.getDevelopmentVersions() );
        }
        // These must be overridden, as they are not stored
        mergeInto.setWorkingDirectory(
            mergeOverride( mergeInto.getWorkingDirectory(), toBeMerged.getWorkingDirectory() ) );
        mergeInto.setCheckoutDirectory(
            mergeOverride( mergeInto.getCheckoutDirectory(), toBeMerged.getCheckoutDirectory() ) );

        // Not overridden - not configured from caller
        mergeInto.setCompletedPhase( mergeDefault( mergeInto.getCompletedPhase(), toBeMerged.getCompletedPhase() ) );

        mergeInto.setProjectVersionPolicyId(
            mergeDefault( mergeInto.getProjectVersionPolicyId(), toBeMerged.getProjectVersionPolicyId() ) );

        return mergeInto;
    }

    private static String mergeOverride( String thisValue, String mergeValue )
    {
        return mergeValue != null ? mergeValue : thisValue;
    }

    private static String mergeDefault( String thisValue, String mergeValue )
    {
        return thisValue != null ? thisValue : mergeValue;
    }

    private static boolean mergeOverride( boolean thisValue, boolean mergeValue, boolean defaultValue )
    {
        return mergeValue != defaultValue ? mergeValue : thisValue;
    }

    public static ReleaseDescriptor copyPropertiesToReleaseDescriptor( Properties properties )
    {
        ReleaseDescriptor releaseDescriptor = new ReleaseDescriptor();
        releaseDescriptor.setCompletedPhase( properties.getProperty( "completedPhase" ) );
        releaseDescriptor.setCommitByProject( Boolean.parseBoolean( properties.getProperty( "commitByProject" ) ) );
        releaseDescriptor.setScmId( properties.getProperty( "scm.id" ) );
        releaseDescriptor.setScmSourceUrl( properties.getProperty( "scm.url" ) );
        releaseDescriptor.setScmUsername( properties.getProperty( "scm.username" ) );
        releaseDescriptor.setScmPassword( properties.getProperty( "scm.password" ) );
        releaseDescriptor.setScmPrivateKey( properties.getProperty( "scm.privateKey" ) );
        releaseDescriptor.setScmPrivateKeyPassPhrase( properties.getProperty( "scm.passphrase" ) );
        releaseDescriptor.setScmTagBase( properties.getProperty( "scm.tagBase" ) );
        releaseDescriptor.setScmTagNameFormat( properties.getProperty( "scm.tagNameFormat" ) );
        releaseDescriptor.setScmBranchBase( properties.getProperty( "scm.branchBase" ) );
        releaseDescriptor.setScmReleaseLabel( properties.getProperty( "scm.tag" ) );
        releaseDescriptor.setScmCommentPrefix( properties.getProperty( "scm.commentPrefix" ) );
        releaseDescriptor.setAdditionalArguments( properties.getProperty( "exec.additionalArguments" ) );
        releaseDescriptor.setPomFileName( properties.getProperty( "exec.pomFileName" ) );
        releaseDescriptor.setPreparationGoals( properties.getProperty( "preparationGoals" ) );
        releaseDescriptor.setCompletionGoals( properties.getProperty( "completionGoals" ) );
        releaseDescriptor.setProjectVersionPolicyId( properties.getProperty( "projectVersionPolicyId" ) );
        String snapshotReleasePluginAllowedStr = properties.getProperty( "exec.snapshotReleasePluginAllowed" );
        releaseDescriptor.setSnapshotReleasePluginAllowed( snapshotReleasePluginAllowedStr == null
                                                               ? false
                                                               : Boolean.valueOf(
                                                                   snapshotReleasePluginAllowedStr ).booleanValue() );
        String remoteTaggingStr = properties.getProperty( "remoteTagging" );
        releaseDescriptor.setRemoteTagging(
            remoteTaggingStr == null ? false : Boolean.valueOf( remoteTaggingStr ).booleanValue() );
        String pushChanges = properties.getProperty( "pushChanges" );
        releaseDescriptor.setPushChanges( pushChanges == null ? true : Boolean.valueOf( pushChanges ).booleanValue() );

        loadResolvedDependencies( properties, releaseDescriptor );

        // boolean properties are not written to the properties file because the value from the caller is always used

        for ( Iterator<?> i = properties.keySet().iterator(); i.hasNext(); )
        {
            String property = (String) i.next();
            if ( property.startsWith( "project.rel." ) )
            {
                releaseDescriptor.mapReleaseVersion( property.substring( "project.rel.".length() ),
                                                     properties.getProperty( property ) );
            }
            else if ( property.startsWith( "project.dev." ) )
            {
                releaseDescriptor.mapDevelopmentVersion( property.substring( "project.dev.".length() ),
                                                         properties.getProperty( property ) );
            }
            else if ( property.startsWith( "project.scm." ) )
            {
                int index = property.lastIndexOf( '.' );
                if ( index > "project.scm.".length() )
                {
                    String key = property.substring( "project.scm.".length(), index );

                    if ( !releaseDescriptor.getOriginalScmInfo().containsKey( key ) )
                    {
                        if ( properties.getProperty( "project.scm." + key + ".empty" ) != null )
                        {
                            releaseDescriptor.mapOriginalScmInfo( key, null );
                        }
                        else
                        {
                            IdentifiedScm scm = new IdentifiedScm();
                            scm.setConnection( properties.getProperty( "project.scm." + key + ".connection" ) );
                            scm.setDeveloperConnection(
                                properties.getProperty( "project.scm." + key + ".developerConnection" ) );
                            scm.setUrl( properties.getProperty( "project.scm." + key + ".url" ) );
                            scm.setTag( properties.getProperty( "project.scm." + key + ".tag" ) );
                            scm.setId( properties.getProperty( "project.scm." + key + ".id" ) );

                            releaseDescriptor.mapOriginalScmInfo( key, scm );
                        }
                    }
                }
            }
        }
        return releaseDescriptor;
    }

    private static void loadResolvedDependencies( Properties prop, ReleaseDescriptor descriptor )
    {
        Map<String, Map<String, String>> resolvedDependencies = new HashMap<String, Map<String, String>>();

        Set entries = prop.entrySet();
        Iterator<Entry<String, String>> iterator = entries.iterator();
        String propertyName;
        Entry<String, String> currentEntry;

        while ( iterator.hasNext() )
        {
            currentEntry = iterator.next();
            propertyName = currentEntry.getKey();

            if ( propertyName.startsWith( "dependency." ) )
            {
                Map<String, String> versionMap;
                String artifactVersionlessKey;
                int startIndex = "dependency.".length();
                int endIndex;
                String versionType;

                versionMap = new HashMap<String, String>();

                if ( propertyName.indexOf( ".development" ) != -1 )
                {
                    endIndex = propertyName.lastIndexOf( ".development" );
                    versionType = ReleaseDescriptor.DEVELOPMENT_KEY;
                }
                else if ( propertyName.indexOf( ".release" ) != -1 )
                {
                    endIndex = propertyName.lastIndexOf( ".release" );
                    versionType = ReleaseDescriptor.RELEASE_KEY;
                }
                else
                {
                    // MRELEASE-834, probably a maven-dependency-plugin property
                    continue;
                }

                artifactVersionlessKey = propertyName.substring( startIndex, endIndex );

                if ( resolvedDependencies.containsKey( artifactVersionlessKey ) )
                {
                    versionMap = resolvedDependencies.get( artifactVersionlessKey );
                }
                else
                {
                    versionMap = new HashMap<String, String>();
                    resolvedDependencies.put( artifactVersionlessKey, versionMap );
                }

                versionMap.put( versionType, currentEntry.getValue() );
            }
        }

        descriptor.setResolvedSnapshotDependencies( resolvedDependencies );
    }

}
