package org.apache.maven.shared.utils.cli;

/*
 * 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.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.maven.shared.utils.Os;
import org.apache.maven.shared.utils.StringUtils;
import org.apache.maven.shared.utils.cli.shell.BourneShell;
import org.apache.maven.shared.utils.cli.shell.CmdShell;
import org.apache.maven.shared.utils.cli.shell.CommandShell;
import org.apache.maven.shared.utils.cli.shell.Shell;

/**
 * <p/>
 * Commandline objects help handling command lines specifying processes to
 * execute.
 * </p>
 * <p/>
 * The class can be used to define a command line as nested elements or as a
 * helper to define a command line by an application.
 * </p>
 * <p/>
 * <code>
 * &lt;someelement&gt;<br>
 * &nbsp;&nbsp;&lt;acommandline executable="/executable/to/run"&gt;<br>
 * &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument value="argument 1" /&gt;<br>
 * &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument line="argument_1 argument_2 argument_3" /&gt;<br>
 * &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument value="argument 4" /&gt;<br>
 * &nbsp;&nbsp;&lt;/acommandline&gt;<br>
 * &lt;/someelement&gt;<br>
 * </code>
 * </p>
 * <p/>
 * The element <code>someelement</code> must provide a method
 * <code>createAcommandline</code> which returns an instance of this class.
 * </p>
 *
 * @author thomas.haas@softwired-inc.com
 * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
 */
public class Commandline
    implements Cloneable
{
    private final List<Argument> arguments = new ArrayList<>();

    //protected Vector envVars = new Vector();
    // synchronized added to preserve synchronize of Vector class
    private final Map<String, String> envVars = Collections.synchronizedMap( new LinkedHashMap<String, String>() );

    private Shell shell;

    /**
     * Create a new command line object.
     * Shell is autodetected from operating system
     * @param shell The shell instance.
     */
    public Commandline( Shell shell )
    {
        this.shell = shell;
    }

    /**
     * Create a new command line object.
     * Shell is autodetected from operating system
     *
     * @param toProcess The command to process
     */
    public Commandline( String toProcess ) throws CommandLineException
    {
        setDefaultShell();
        String[] tmp = CommandLineUtils.translateCommandline( toProcess );
        if ( tmp.length > 0 )
        {
            setExecutable( tmp[0] );
            for ( int i = 1; i < tmp.length; i++ )
            {
                createArg().setValue( tmp[i] );
            }
        }
    }

    /**
     * Create a new command line object.
     * Shell is autodetected from operating system
     */
    public Commandline()
    {
        setDefaultShell();
    }

    /**
     * <p>Sets the shell or command-line interpretor for the detected operating system,
     * and the shell arguments.</p>
     */
    private void setDefaultShell()
    {
        //If this is windows set the shell to command.com or cmd.exe with correct arguments.
        if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
        {
            if ( Os.isFamily( Os.FAMILY_WIN9X ) )
            {
                setShell( new CommandShell() );
            }
            else
            {
                setShell( new CmdShell() );
            }
        }
        else
        {
            setShell( new BourneShell() );
        }
    }

    /**
     * Creates an argument object.
     * <p/>
     * <p>Each commandline object has at most one instance of the
     * argument class.  This method calls
     * <code>this.createArgument(false)</code>.</p>
     *
     * @return the argument object.
     */
    public Arg createArg()
    {
        return this.createArg( false );
    }

    /**
     * Creates an argument object and adds it to our list of args.
     * <p/>
     * <p>Each commandline object has at most one instance of the
     * argument class.</p>
     *
     * @param insertAtStart if true, the argument is inserted at the
     *                      beginning of the list of args, otherwise it is appended.
     * @return The arguments.
     */
    public Arg createArg( boolean insertAtStart )
    {
        Argument argument = new Argument();
        if ( insertAtStart )
        {
            arguments.add( 0, argument );
        }
        else
        {
            arguments.add( argument );
        }
        return argument;
    }

    /**
     * Sets the executable to run.
     * @param executable The executable.
     */
    public void setExecutable( String executable )
    {
        shell.setExecutable( executable );
    }

    /**
     * @return The executable.
     */
    public String getExecutable()
    {

        return shell.getExecutable();
    }

    /**
     * @param line The arguments.
     */
    public void addArguments( String... line )
    {
        for ( String aLine : line )
        {
            createArg().setValue( aLine );
        }
    }

    /**
     * Add an environment variable
     * @param name The name of the environment variable.
     * @param value The appropriate value.
     */
    public void addEnvironment( String name, String value )
    {
        //envVars.add( name + "=" + value );
        envVars.put( name, value );
    }

    /**
     * Add system environment variables
     */
    public void addSystemEnvironment()
    {
        Properties systemEnvVars = CommandLineUtils.getSystemEnvVars();

        for ( Object o : systemEnvVars.keySet() )
        {
            String key = (String) o;
            if ( !envVars.containsKey( key ) )
            {
                addEnvironment( key, systemEnvVars.getProperty( key ) );
            }
        }
    }

    /**
     * Return the list of environment variables
     * @return an array of all environment variables.
     */
    public String[] getEnvironmentVariables()
    {
        addSystemEnvironment();
        String[] environmentVars = new String[envVars.size()];
        int i = 0;
        for ( String name : envVars.keySet() )
        {
            String value = envVars.get( name );
            environmentVars[i] = name + "=" + value;
            i++;
        }
        return environmentVars;
    }

    /**
     * Returns the executable and all defined arguments.
     * @return an array of all arguments incl. executable.
     */
    public String[] getCommandline()
    {
        final String[] args = getArguments();
        String executable = getExecutable();

        if ( executable == null )
        {
            return args;
        }
        final String[] result = new String[args.length + 1];
        result[0] = executable;
        System.arraycopy( args, 0, result, 1, args.length );
        return result;
    }

    /**
     * @return the shell, executable and all defined arguments without masking any arguments.
     */
    private String[] getShellCommandline()
    {
        return getShellCommandline( false ) ;
    }

    /**
     * @param mask flag to mask any arguments (having his {@code mask} field to {@code true}).
     * @return the shell, executable and all defined arguments with masking some arguments if
     * {@code mask} parameter is on
     */
    private String[] getShellCommandline( boolean mask )
    {
        List<String> shellCommandLine = getShell().getShellCommandLine( getArguments( mask ) );
        return shellCommandLine.toArray( new String[shellCommandLine.size()] );
    }

    /**
     * Returns all arguments defined by <code>addLine</code>,
     * <code>addValue</code> or the argument object.
     * @return an array of arguments.
     */
    public String[] getArguments()
    {
        return getArguments( false );
    }

    /**
     * Returns all arguments defined by <code>addLine</code>,
     * <code>addValue</code> or the argument object.
     *
     * @param mask flag to mask any arguments (having his {@code mask} field to {@code true}).
     * @return an array of arguments.
     */
    public String[] getArguments( boolean mask )
    {
        List<String> result = new ArrayList<>( arguments.size() * 2 );
        for ( Argument arg : arguments )
        {
            String[] s = arg.getParts();
            if ( s != null )
            {
                if ( mask && ( arg.isMask() ) )
                {
                    // should be a key-pair argument
                    if ( s.length > 0 )
                    {

                        // use a masked copy
                        String[] copy = new String[s.length];
                        Arrays.fill( copy, "*****" );
                        s = copy;
                    }
                }
                Collections.addAll( result, s );
            }
        }

        return result.toArray( new String[result.size()] );
    }

    @Override
    public String toString()
    {
        return StringUtils.join( getShellCommandline( true ), " " );
    }

    @Override
    public Object clone()
    {
        throw new RuntimeException( "Do we ever clone a commandline?" );
/*        Commandline c = new Commandline( (Shell) shell.clone() );
       c.addArguments( getArguments() );
        return c;*/
    }

    /**
     * Sets working directory.
     * @param path The to be set as working directory.
     */
    public void setWorkingDirectory( String path )
    {
        shell.setWorkingDirectory( path );
    }

    /**
     * Sets execution directory.
     * @param workingDirectory The working directory.
     */
    public void setWorkingDirectory( File workingDirectory )
    {
        shell.setWorkingDirectory( workingDirectory );
    }

    /**
     * @return The working directory.
     */
    public File getWorkingDirectory()
    {
        return shell.getWorkingDirectory();
    }

    /**
     * Clear out the arguments but leave the executable in place for another operation.
     */
    public void clearArgs()
    {
        arguments.clear();
    }

    /**
     * Executes the command.
     * @return The process.
     * @throws CommandLineException in case of errors.
     */
    public Process execute()
        throws CommandLineException
    {
        Process process;

        //addEnvironment( "MAVEN_TEST_ENVAR", "MAVEN_TEST_ENVAR_VALUE" );

        String[] environment = getEnvironmentVariables();

        File workingDir = shell.getWorkingDirectory();

        try
        {
            if ( workingDir == null )
            {
                process = Runtime.getRuntime().exec( getShellCommandline(), environment );
            }
            else
            {
                if ( !workingDir.exists() )
                {
                    throw new CommandLineException(
                        "Working directory \"" + workingDir.getPath() + "\" does not exist!" );
                }
                else if ( !workingDir.isDirectory() )
                {
                    throw new CommandLineException(
                        "Path \"" + workingDir.getPath() + "\" does not specify a directory." );
                }

                process = Runtime.getRuntime().exec( getShellCommandline(), environment, workingDir );
            }
        }
        catch ( IOException ex )
        {
            throw new CommandLineException( "Error while executing process.", ex );
        }

        return process;
    }

    /**
     * Allows to set the shell to be used in this command line.
     *
     * @param shell the shell
     */
    void setShell( Shell shell )
    {
        this.shell = shell;
    }

    /**
     * Get the shell to be used in this command line.
     * @return the shell.
     */
    public Shell getShell()
    {
        return shell;
    }

    /**
     * 
     */
    public static class Argument
        implements Arg
    {
        private String[] parts;

        private boolean mask;

        @Override
        public void setValue( String value )
        {
            if ( value != null )
            {
                parts = new String[]{ value };
            }
        }

        @Override
        public void setLine( String line ) throws CommandLineException
        {
            if ( line == null )
            {
                return;
            }
            try
            {
                parts = CommandLineUtils.translateCommandline( line );
            }
            catch ( CommandLineException e )
            {
                System.err.println( "Error translating Commandline." );
                throw( e );
            }
        }

        @Override
        public void setFile( File value )
        {
            parts = new String[]{ value.getAbsolutePath() };
        }

        @Override
        public void setMask( boolean mask )
        {
            this.mask = mask;
        }

        /**
         * @return The parts.
         */
        private String[] getParts()
        {
            return parts;
        }

        /**
         * @return true/false
         */
        public boolean isMask()
        {
            return mask;
        }
    }
}
