package org.apache.maven.wagon.providers.ssh.external;

/*
 * 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.wagon.AbstractWagon;
import org.apache.maven.wagon.CommandExecutionException;
import org.apache.maven.wagon.CommandExecutor;
import org.apache.maven.wagon.PathUtils;
import org.apache.maven.wagon.PermissionModeUtils;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.apache.maven.wagon.Streams;
import org.apache.maven.wagon.TransferFailedException;
import org.apache.maven.wagon.WagonConstants;
import org.apache.maven.wagon.authentication.AuthenticationException;
import org.apache.maven.wagon.authentication.AuthenticationInfo;
import org.apache.maven.wagon.authorization.AuthorizationException;
import org.apache.maven.wagon.events.TransferEvent;
import org.apache.maven.wagon.providers.ssh.ScpHelper;
import org.apache.maven.wagon.repository.RepositoryPermissions;
import org.apache.maven.wagon.resource.Resource;
import org.codehaus.plexus.util.StringUtils;
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.io.FileNotFoundException;
import java.util.List;
import java.util.Locale;

/**
 * SCP deployer using "external" scp program.  To allow for
 * ssh-agent type behavior, until we can construct a Java SSH Agent and interface for JSch.
 *
 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 * @todo [BP] add compression flag
 * @plexus.component role="org.apache.maven.wagon.Wagon"
 * role-hint="scpexe"
 * instantiation-strategy="per-lookup"
 */
public class ScpExternalWagon
    extends AbstractWagon
    implements CommandExecutor
{
    /**
     * The external SCP command to use - default is <code>scp</code>.
     *
     * @component.configuration default="scp"
     */
    private String scpExecutable = "scp";

    /**
     * The external SSH command to use - default is <code>ssh</code>.
     *
     * @component.configuration default="ssh"
     */
    private String sshExecutable = "ssh";

    /**
     * Arguments to pass to the SCP command.
     *
     * @component.configuration
     */
    private String scpArgs;

    /**
     * Arguments to pass to the SSH command.
     *
     * @component.configuration
     */
    private String sshArgs;

    private ScpHelper sshTool = new ScpHelper( this );

    private static final int SSH_FATAL_EXIT_CODE = 255;

    // ----------------------------------------------------------------------
    //
    // ----------------------------------------------------------------------

    protected void openConnectionInternal()
        throws AuthenticationException
    {
        if ( authenticationInfo == null )
        {
            authenticationInfo = new AuthenticationInfo();
        }
    }

    public void closeConnection()
    {
        // nothing to disconnect
    }

    public boolean getIfNewer( String resourceName, File destination, long timestamp )
        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
    {
        fireSessionDebug( "getIfNewer in SCP wagon is not supported - performing an unconditional get" );
        get( resourceName, destination );
        return true;
    }

    /**
     * @return The hostname of the remote server prefixed with the username, which comes either from the repository URL
     *         or from the authenticationInfo.
     */
    private String buildRemoteHost()
    {
        String username = this.getRepository().getUsername();
        if ( username == null )
        {
            username = authenticationInfo.getUserName();
        }

        if ( username == null )
        {
            return getRepository().getHost();
        }
        else
        {
            return username + "@" + getRepository().getHost();
        }
    }

    public void executeCommand( String command )
        throws CommandExecutionException
    {
        fireTransferDebug( "Executing command: " + command );

        executeCommand( command, false );
    }

    public Streams executeCommand( String command, boolean ignoreFailures )
        throws CommandExecutionException
    {
        boolean putty = isPuTTY();

        File privateKey;
        try
        {
            privateKey = ScpHelper.getPrivateKey( authenticationInfo );
        }
        catch ( FileNotFoundException e )
        {
            throw new CommandExecutionException( e.getMessage(), e );
        }
        Commandline cl = createBaseCommandLine( putty, sshExecutable, privateKey );

        int port =
            repository.getPort() == WagonConstants.UNKNOWN_PORT ? ScpHelper.DEFAULT_SSH_PORT : repository.getPort();
        if ( port != ScpHelper.DEFAULT_SSH_PORT )
        {
            if ( putty )
            {
                cl.createArg().setLine( "-P " + port );
            }
            else
            {
                cl.createArg().setLine( "-p " + port );
            }
        }

        if ( sshArgs != null )
        {
            cl.createArg().setLine( sshArgs );
        }

        String remoteHost = this.buildRemoteHost();

        cl.createArg().setValue( remoteHost );

        cl.createArg().setValue( command );

        fireSessionDebug( "Executing command: " + cl.toString() );

        try
        {
            CommandLineUtils.StringStreamConsumer out = new CommandLineUtils.StringStreamConsumer();
            CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
            int exitCode = CommandLineUtils.executeCommandLine( cl, out, err );
            Streams streams = new Streams();
            streams.setOut( out.getOutput() );
            streams.setErr( err.getOutput() );
            fireSessionDebug( streams.getOut() );
            fireSessionDebug( streams.getErr() );
            if ( exitCode != 0 )
            {
                if ( !ignoreFailures || exitCode == SSH_FATAL_EXIT_CODE )
                {
                    throw new CommandExecutionException( "Exit code " + exitCode + " - " + err.getOutput() );
                }
            }
            return streams;
        }
        catch ( CommandLineException e )
        {
            throw new CommandExecutionException( "Error executing command line", e );
        }
    }

    protected boolean isPuTTY()
    {
        String exe = sshExecutable.toLowerCase( Locale.ENGLISH );
        return exe.contains( "plink" ) || exe.contains( "klink" );
    }

    private Commandline createBaseCommandLine( boolean putty, String executable, File privateKey )
    {
        Commandline cl = new Commandline();

        cl.setExecutable( executable );

        if ( privateKey != null )
        {
            cl.createArg().setValue( "-i" );
            cl.createArg().setFile( privateKey );
        }

        String password = authenticationInfo.getPassword();
        if ( putty && password != null )
        {
            cl.createArg().setValue( "-pw" );
            cl.createArg().setValue( password );
        }

        // should check interactive flag, but scpexe never works in interactive mode right now due to i/o streams
        if ( putty )
        {
            cl.createArg().setValue( "-batch" );
        }
        else
        {
            cl.createArg().setValue( "-o" );
            cl.createArg().setValue( "BatchMode yes" );
        }
        return cl;
    }


    private void executeScpCommand( Resource resource, File localFile, boolean put )
        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
    {
        boolean putty = isPuTTYSCP();

        File privateKey;
        try
        {
            privateKey = ScpHelper.getPrivateKey( authenticationInfo );
        }
        catch ( FileNotFoundException e )
        {
            fireSessionConnectionRefused();

            throw new AuthorizationException( e.getMessage() );
        }
        Commandline cl = createBaseCommandLine( putty, scpExecutable, privateKey );

        cl.setWorkingDirectory( localFile.getParentFile().getAbsolutePath() );

        int port =
            repository.getPort() == WagonConstants.UNKNOWN_PORT ? ScpHelper.DEFAULT_SSH_PORT : repository.getPort();
        if ( port != ScpHelper.DEFAULT_SSH_PORT )
        {
            cl.createArg().setLine( "-P " + port );
        }

        if ( scpArgs != null )
        {
            cl.createArg().setLine( scpArgs );
        }

        String resourceName = normalizeResource( resource );
        String remoteFile = getRepository().getBasedir() + "/" + resourceName;

        remoteFile = StringUtils.replace( remoteFile, " ", "\\ " );

        String qualifiedRemoteFile = this.buildRemoteHost() + ":" + remoteFile;
        if ( put )
        {
            cl.createArg().setValue( localFile.getName() );
            cl.createArg().setValue( qualifiedRemoteFile );
        }
        else
        {
            cl.createArg().setValue( qualifiedRemoteFile );
            cl.createArg().setValue( localFile.getName() );
        }

        fireSessionDebug( "Executing command: " + cl.toString() );

        try
        {
            CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
            int exitCode = CommandLineUtils.executeCommandLine( cl, null, err );
            if ( exitCode != 0 )
            {
                if ( !put
                    && err.getOutput().trim().toLowerCase( Locale.ENGLISH ).contains( "no such file or directory" ) )
                {
                    throw new ResourceDoesNotExistException( err.getOutput() );
                }
                else
                {
                    TransferFailedException e =
                        new TransferFailedException( "Exit code: " + exitCode + " - " + err.getOutput() );

                    fireTransferError( resource, e, put ? TransferEvent.REQUEST_PUT : TransferEvent.REQUEST_GET );

                    throw e;
                }
            }
        }
        catch ( CommandLineException e )
        {
            fireTransferError( resource, e, put ? TransferEvent.REQUEST_PUT : TransferEvent.REQUEST_GET );

            throw new TransferFailedException( "Error executing command line", e );
        }
    }

    boolean isPuTTYSCP()
    {
        String exe = scpExecutable.toLowerCase( Locale.ENGLISH );
        return exe.contains( "pscp" ) || exe.contains( "kscp" );
    }

    private String normalizeResource( Resource resource )
    {
        return StringUtils.replace( resource.getName(), "\\", "/" );
    }

    public void put( File source, String destination )
        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
    {
        Resource resource = new Resource( destination );

        firePutInitiated( resource, source );

        if ( !source.exists() )
        {
            throw new ResourceDoesNotExistException( "Specified source file does not exist: " + source );
        }

        String basedir = getRepository().getBasedir();

        String resourceName = StringUtils.replace( destination, "\\", "/" );

        String dir = PathUtils.dirname( resourceName );

        dir = StringUtils.replace( dir, "\\", "/" );

        String umaskCmd = null;
        if ( getRepository().getPermissions() != null )
        {
            String dirPerms = getRepository().getPermissions().getDirectoryMode();

            if ( dirPerms != null )
            {
                umaskCmd = "umask " + PermissionModeUtils.getUserMaskFor( dirPerms );
            }
        }

        String mkdirCmd = "mkdir -p " + basedir + "/" + dir + "\n";

        if ( umaskCmd != null )
        {
            mkdirCmd = umaskCmd + "; " + mkdirCmd;
        }

        try
        {
            executeCommand( mkdirCmd );
        }
        catch ( CommandExecutionException e )
        {
            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );

            throw new TransferFailedException( "Error executing command for transfer", e );
        }

        resource.setContentLength( source.length() );

        resource.setLastModified( source.lastModified() );

        firePutStarted( resource, source );

        executeScpCommand( resource, source, true );

        postProcessListeners( resource, source, TransferEvent.REQUEST_PUT );

        try
        {
            RepositoryPermissions permissions = getRepository().getPermissions();

            if ( permissions != null && permissions.getGroup() != null )
            {
                executeCommand( "chgrp -f " + permissions.getGroup() + " " + basedir + "/" + resourceName + "\n",
                                true );
            }

            if ( permissions != null && permissions.getFileMode() != null )
            {
                executeCommand( "chmod -f " + permissions.getFileMode() + " " + basedir + "/" + resourceName + "\n",
                                true );
            }
        }
        catch ( CommandExecutionException e )
        {
            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );

            throw new TransferFailedException( "Error executing command for transfer", e );
        }
        firePutCompleted( resource, source );
    }

    public void get( String resourceName, File destination )
        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
    {
        String path = StringUtils.replace( resourceName, "\\", "/" );

        Resource resource = new Resource( path );

        fireGetInitiated( resource, destination );

        createParentDirectories( destination );

        fireGetStarted( resource, destination );

        executeScpCommand( resource, destination, false );

        postProcessListeners( resource, destination, TransferEvent.REQUEST_GET );

        fireGetCompleted( resource, destination );
    }

    //
    // these parameters are user specific, so should not be read from the repository itself.
    // They can be configured by plexus, or directly on the instantiated object.
    // Alternatively, we may later accept a generic parameters argument to connect, or some other configure(Properties)
    // method on a Wagon.
    //

    public List<String> getFileList( String destinationDirectory )
        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
    {
        return sshTool.getFileList( destinationDirectory, repository );
    }

    public void putDirectory( File sourceDirectory, String destinationDirectory )
        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
    {
        sshTool.putDirectory( this, sourceDirectory, destinationDirectory );
    }

    public boolean resourceExists( String resourceName )
        throws TransferFailedException, AuthorizationException
    {
        return sshTool.resourceExists( resourceName, repository );
    }

    public boolean supportsDirectoryCopy()
    {
        return true;
    }

    public String getScpExecutable()
    {
        return scpExecutable;
    }

    public void setScpExecutable( String scpExecutable )
    {
        this.scpExecutable = scpExecutable;
    }

    public String getSshExecutable()
    {
        return sshExecutable;
    }

    public void setSshExecutable( String sshExecutable )
    {
        this.sshExecutable = sshExecutable;
    }

    public String getScpArgs()
    {
        return scpArgs;
    }

    public void setScpArgs( String scpArgs )
    {
        this.scpArgs = scpArgs;
    }

    public String getSshArgs()
    {
        return sshArgs;
    }

    public void setSshArgs( String sshArgs )
    {
        this.sshArgs = sshArgs;
    }
}
