package org.apache.maven.it;

/*
 * 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.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.maven.shared.utils.StringUtils;
import org.apache.maven.shared.utils.cli.CommandLineException;
import org.apache.maven.shared.utils.cli.CommandLineUtils;
import org.apache.maven.shared.utils.cli.Commandline;
import org.apache.maven.shared.utils.cli.StreamConsumer;
import org.apache.maven.shared.utils.cli.WriterStreamConsumer;
import org.apache.maven.shared.utils.io.FileUtils;

/**
 * @author Benjamin Bentmann
 */
class ForkedLauncher
    implements MavenLauncher
{

    private final String mavenHome;

    private final String executable;

    private final Map<String, String> envVars;

    ForkedLauncher( String mavenHome )
    {
        this( mavenHome, Collections.<String, String>emptyMap(), false );
    }

    ForkedLauncher( String mavenHome, Map<String, String> envVars, boolean debugJvm )
    {
        this( mavenHome, envVars, debugJvm, false );
    }

    ForkedLauncher( String mavenHome, Map<String, String> envVars, boolean debugJvm, boolean wrapper )
    {
        this.mavenHome = mavenHome;
        this.envVars = envVars;

        if ( wrapper )
        {
            String script = "mvnw" + ( debugJvm ? "Debug" : "" );
            executable = new File( script ).getPath();
        }
        else
        {
            String script = "mvn" + ( debugJvm ? "Debug" : "" );

            if ( mavenHome != null )
            {
                executable = new File( mavenHome, "bin/" + script ).getPath();
            }
            else
            {
                executable = script;
            }
        }
    }

    public int run( String[] cliArgs, Properties systemProperties, Map<String, String> envVars,
                    String workingDirectory, File logFile )
        throws IOException, LauncherException
    {
        Commandline cmd = new Commandline();

        cmd.setExecutable( executable );

        if ( mavenHome != null )
        {
            cmd.addEnvironment( "M2_HOME", mavenHome );
        }

        if ( envVars != null )
        {
            for ( Map.Entry<String, String> envVar : envVars.entrySet() )
            {
                cmd.addEnvironment( envVar.getKey(), envVar.getValue() );
            }
        }

        if ( envVars == null || envVars.get( "JAVA_HOME" ) == null )
        {
            cmd.addEnvironment( "JAVA_HOME", System.getProperty( "java.home" ) );
        }

        cmd.addEnvironment( "MAVEN_TERMINATE_CMD", "on" );

        cmd.setWorkingDirectory( workingDirectory );

        for ( Object o : systemProperties.keySet() )
        {
            String key = (String) o;
            String value = systemProperties.getProperty( key );
            cmd.createArg().setValue( "-D" + key + "=" + value );
        }

        for ( String cliArg : cliArgs )
        {
            cmd.createArg().setValue( cliArg );
        }

        Writer logWriter = new FileWriter( logFile );

        StreamConsumer out = new WriterStreamConsumer( logWriter );

        StreamConsumer err = new WriterStreamConsumer( logWriter );

        try
        {
            return CommandLineUtils.executeCommandLine( cmd, out, err );
        }
        catch ( CommandLineException e )
        {
            throw new LauncherException( "Failed to run Maven: " + e.getMessage() + "\n" + cmd, e );
        }
        finally
        {
            logWriter.close();
        }
    }

    public int run( String[] cliArgs, Properties systemProperties, String workingDirectory, File logFile )
        throws IOException, LauncherException
    {
        return run( cliArgs, systemProperties, envVars, workingDirectory, logFile );
    }

    public String getMavenVersion()
        throws IOException, LauncherException
    {
        File logFile;
        try
        {
            logFile = File.createTempFile( "maven", "log" );
        }
        catch ( IOException e )
        {
            throw new LauncherException( "Error creating temp file", e );
        }

        // disable EMMA runtime controller port allocation, should be harmless if EMMA is not used
        Map<String, String> envVars = Collections.singletonMap( "MAVEN_OPTS", "-Demma.rt.control=false" );
        run( new String[] { "--version" }, new Properties(), envVars, null, logFile );

        List<String> logLines = FileUtils.loadFile( logFile );
        // noinspection ResultOfMethodCallIgnored
        logFile.delete();

        String version = extractMavenVersion( logLines );

        if ( version == null )
        {
            throw new LauncherException( "Illegal Maven output: String 'Maven' not found in the following output:\n"
                + StringUtils.join( logLines.iterator(), "\n" ) );
        }
        else
        {
            return version;
        }
    }

    static String extractMavenVersion( List<String> logLines )
    {
        String version = null;

        final Pattern mavenVersion = Pattern.compile( "(?i).*Maven.*? ([0-9]\\.\\S*).*" );

        for ( Iterator<String> it = logLines.iterator(); version == null && it.hasNext(); )
        {
            String line = it.next();

            Matcher m = mavenVersion.matcher( line );
            if ( m.matches() )
            {
                version = m.group( 1 );
            }
        }

        return version;
    }

}
