package org.apache.maven.scm.provider.hg;

/*
 * 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.scm.ScmException;
import org.apache.maven.scm.ScmFileSet;
import org.apache.maven.scm.ScmFileStatus;
import org.apache.maven.scm.ScmResult;
import org.apache.maven.scm.log.DefaultLog;
import org.apache.maven.scm.log.ScmLogger;
import org.apache.maven.scm.provider.hg.command.HgCommandConstants;
import org.apache.maven.scm.provider.hg.command.HgConsumer;
import org.apache.maven.scm.provider.hg.command.inventory.HgChangeSet;
import org.apache.maven.scm.provider.hg.command.inventory.HgOutgoingConsumer;
import org.codehaus.plexus.util.cli.CommandLineException;
import org.codehaus.plexus.util.cli.CommandLineUtils;
import org.codehaus.plexus.util.cli.Commandline;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Common code for executing hg commands.
 *
 * @author <a href="mailto:thurner.rupert@ymono.net">thurner rupert</a>
 *
 */
public final class HgUtils
{

    public static final String DEFAULT = "default";

    private HgUtils()
    {
        // no op
    }

    /**
     * Map between command and its valid exit codes
     */
    private static final Map<String, List<Integer>> EXIT_CODE_MAP = new HashMap<String, List<Integer>>();

    /**
     * Default exit codes for entries not in exitCodeMap
     */
    private static final List<Integer> DEFAULT_EXIT_CODES = new ArrayList<Integer>();

    /** Setup exit codes*/
    static
    {
        DEFAULT_EXIT_CODES.add( Integer.valueOf( 0 ) );

        //Diff is different
        List<Integer> diffExitCodes = new ArrayList<Integer>( 3 );
        diffExitCodes.add( Integer.valueOf( 0 ) ); //No difference
        diffExitCodes.add( Integer.valueOf( 1 ) ); //Conflicts in merge-like or changes in diff-like
        diffExitCodes.add( Integer.valueOf( 2 ) ); //Unrepresentable diff changes
        EXIT_CODE_MAP.put( HgCommandConstants.DIFF_CMD, diffExitCodes );
        //Outgoing is different
        List<Integer> outgoingExitCodes = new ArrayList<Integer>( 2 );
        outgoingExitCodes.add( Integer.valueOf( 0 ) ); //There are changes
        outgoingExitCodes.add( Integer.valueOf( 1 ) ); //No changes
        EXIT_CODE_MAP.put( HgCommandConstants.OUTGOING_CMD, outgoingExitCodes );
    }

    public static ScmResult execute( HgConsumer consumer, ScmLogger logger, File workingDir, String[] cmdAndArgs )
        throws ScmException
    {
        try
        {
            //Build commandline
            Commandline cmd = buildCmd( workingDir, cmdAndArgs );
            if ( logger.isInfoEnabled() )
            {
                logger.info( "EXECUTING: " + maskPassword( cmd ) );
            }

            //Execute command
            int exitCode = executeCmd( consumer, cmd );

            //Return result
            List<Integer> exitCodes = DEFAULT_EXIT_CODES;
            if ( EXIT_CODE_MAP.containsKey( cmdAndArgs[0] ) )
            {
                exitCodes = EXIT_CODE_MAP.get( cmdAndArgs[0] );
            }
            boolean success = exitCodes.contains( Integer.valueOf( exitCode ) );

            //On failure (and not due to exceptions) - run diagnostics
            String providerMsg = "Execution of hg command succeded";
            if ( !success )
            {
                HgConfig config = new HgConfig( workingDir );
                providerMsg =
                    "\nEXECUTION FAILED" + "\n  Execution of cmd : " + cmdAndArgs[0] + " failed with exit code: "
                        + exitCode + "." + "\n  Working directory was: " + "\n    " + workingDir.getAbsolutePath()
                        + config.toString( workingDir ) + "\n";
                if ( logger.isErrorEnabled() )
                {
                    logger.error( providerMsg );
                }
            }

            return new ScmResult( cmd.toString(), providerMsg, consumer.getStdErr(), success );
        }
        catch ( ScmException se )
        {
            String msg =
                "EXECUTION FAILED" + "\n  Execution failed before invoking the Hg command. Last exception:" + "\n    "
                    + se.getMessage();

            //Add nested cause if any
            if ( se.getCause() != null )
            {
                msg += "\n  Nested exception:" + "\n    " + se.getCause().getMessage();
            }

            //log and return
            if ( logger.isErrorEnabled() )
            {
                logger.error( msg );
            }
            throw se;
        }
    }

    static Commandline buildCmd( File workingDir, String[] cmdAndArgs )
        throws ScmException
    {
        Commandline cmd = new Commandline();
        cmd.setExecutable( HgCommandConstants.EXEC );
        cmd.addArguments( cmdAndArgs );
        if ( workingDir != null )
        {
            cmd.setWorkingDirectory( workingDir.getAbsolutePath() );

            if ( !workingDir.exists() )
            {
                boolean success = workingDir.mkdirs();
                if ( !success )
                {
                    String msg = "Working directory did not exist" + " and it couldn't be created: " + workingDir;
                    throw new ScmException( msg );
                }
            }
        }
        return cmd;
    }

    static int executeCmd( HgConsumer consumer, Commandline cmd )
        throws ScmException
    {
        final int exitCode;
        try
        {
            exitCode = CommandLineUtils.executeCommandLine( cmd, consumer, consumer );
        }
        catch ( CommandLineException ex )
        {
            throw new ScmException( "Command could not be executed: " + cmd, ex );
        }
        return exitCode;
    }

    public static ScmResult execute( File workingDir, String[] cmdAndArgs )
        throws ScmException
    {
        ScmLogger logger = new DefaultLog();
        return execute( new HgConsumer( logger ), logger, workingDir, cmdAndArgs );
    }

    public static String[] expandCommandLine( String[] cmdAndArgs, ScmFileSet additionalFiles )
    {
        List<File> filesList = additionalFiles.getFileList();
        String[] cmd = new String[filesList.size() + cmdAndArgs.length];

        // Copy command into array
        System.arraycopy( cmdAndArgs, 0, cmd, 0, cmdAndArgs.length );

        // Add files as additional parameter into the array
        int i = 0;
        for ( File scmFile : filesList )
        {
            String file = scmFile.getPath().replace( '\\', File.separatorChar );
            cmd[i + cmdAndArgs.length] = file;
            i++;
        }

        return cmd;
    }

    public static int getCurrentRevisionNumber( ScmLogger logger, File workingDir )
        throws ScmException
    {

        String[] revCmd = new String[]{ HgCommandConstants.REVNO_CMD };
        HgRevNoConsumer consumer = new HgRevNoConsumer( logger );
        HgUtils.execute( consumer, logger, workingDir, revCmd );

        return consumer.getCurrentRevisionNumber();
    }

    public static String getCurrentBranchName( ScmLogger logger, File workingDir )
        throws ScmException
    {
        String[] branchnameCmd = new String[]{ HgCommandConstants.BRANCH_NAME_CMD };
        HgBranchnameConsumer consumer = new HgBranchnameConsumer( logger );
        HgUtils.execute( consumer, logger, workingDir, branchnameCmd );
        return consumer.getBranchName();
    }

    /**
     * Get current (working) revision.
     * <p/>
     * Resolve revision to the last integer found in the command output.
     */
    private static class HgRevNoConsumer
        extends HgConsumer
    {

        private int revNo;

        HgRevNoConsumer( ScmLogger logger )
        {
            super( logger );
        }

        public void doConsume( ScmFileStatus status, String line )
        {
            try
            {
                revNo = Integer.valueOf( line ).intValue();
            }
            catch ( NumberFormatException e )
            {
                // ignore
            }
        }

        int getCurrentRevisionNumber()
        {
            return revNo;
        }
    }

    /**
     * Get current (working) branch name
     */
    private static class HgBranchnameConsumer
        extends HgConsumer
    {

        private String branchName;

        HgBranchnameConsumer( ScmLogger logger )
        {
            super( logger );
        }

        public void doConsume( ScmFileStatus status, String trimmedLine )
        {
            branchName = String.valueOf( trimmedLine );
        }

        String getBranchName()
        {
            return branchName;
        }

        /** {@inheritDoc} */
        public void consumeLine( String line )
        {
            if ( getLogger().isDebugEnabled() )
            {
                getLogger().debug( line );
            }
            String trimmedLine = line.trim();

            doConsume( null, trimmedLine );
        }
    }


    /**
     * Check if there are outgoing changes on a different branch. If so, Mercurial default behaviour
     * is to block the push and warn using a 'push creates new remote branch !' message.
     * We also warn, and return true if a different outgoing branch was found
     * <p/>
     * Method users should not stop the push on a negative return, instead, they should
     * hg push -r(branch being released)
     *
     * @param logger            the logger31
     * @param workingDir        the working dir
     * @param workingbranchName the working branch name
     * @return true if a different outgoing branch was found
     * @throws ScmException on outgoing command error
     */
    public static boolean differentOutgoingBranchFound( ScmLogger logger, File workingDir, String workingbranchName )
        throws ScmException
    {
        String[] outCmd = new String[]{ HgCommandConstants.OUTGOING_CMD };
        HgOutgoingConsumer outConsumer = new HgOutgoingConsumer( logger );
        ScmResult outResult = HgUtils.execute( outConsumer, logger, workingDir, outCmd );
        List<HgChangeSet> changes = outConsumer.getChanges();
        if ( outResult.isSuccess() )
        {
            for ( HgChangeSet set : changes )
            {
                if ( !getBranchName( workingbranchName ).equals( getBranchName( set.getBranch() ) ) )
                {
                    logger.warn( "A different branch than " + getBranchName( workingbranchName )
                        + " was found in outgoing changes, branch name was " + getBranchName( set.getBranch() )
                        + ". Only local branch named " + getBranchName( workingbranchName ) + " will be pushed." );
                    return true;
                }
            }
        }
        return false;
    }

    private static String getBranchName( String branch )
    {
        return branch == null ? DEFAULT : branch;
    }

    public static String maskPassword( Commandline cl )
    {
        String clString = cl.toString();

        int pos = clString.indexOf( '@' );

        if ( pos > 0 )
        {
            clString = clString.replaceAll( ":\\w+@", ":*****@" );
        }

        return clString;
    }
}
