package org.apache.maven.continuum.installation;

/*
 * 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.continuum.dao.InstallationDao;
import org.apache.maven.continuum.execution.ExecutorConfigurator;
import org.apache.maven.continuum.model.system.Installation;
import org.apache.maven.continuum.model.system.Profile;
import org.apache.maven.continuum.profile.AlreadyExistsProfileException;
import org.apache.maven.continuum.profile.ProfileException;
import org.apache.maven.continuum.profile.ProfileService;
import org.apache.maven.continuum.store.ContinuumStoreException;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
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 org.codehaus.plexus.util.cli.StreamConsumer;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * @author <a href="mailto:olamy@codehaus.org">olamy</a>
 * @version $Id$
 * @plexus.component role="org.apache.maven.continuum.installation.InstallationService"
 * TODO use some cache mechanism to prevent always reading from store ?
 * @since 13 juin 07
 */
public class DefaultInstallationService
    extends AbstractLogEnabled
    implements InstallationService, Initializable
{
    /**
     * @plexus.requirement
     */
    private InstallationDao installationDao;

    /**
     * @plexus.requirement role-hint="default"
     */
    private ProfileService profileService;

    private Map<String, ExecutorConfigurator> typesValues;

    // ---------------------------------------------
    // Plexus lifecycle
    // ---------------------------------------------

    public void initialize()
        throws InitializationException
    {
        this.typesValues = new HashMap<String, ExecutorConfigurator>();
        this.typesValues.put( InstallationService.ANT_TYPE,
                              new ExecutorConfigurator( "ant", "bin", "ANT_HOME", "-version" ) );

        this.typesValues.put( InstallationService.ENVVAR_TYPE, null );
        this.typesValues.put( InstallationService.JDK_TYPE,
                              new ExecutorConfigurator( "java", "bin", "JAVA_HOME", "-version" ) );
        this.typesValues.put( InstallationService.MAVEN1_TYPE,
                              new ExecutorConfigurator( "maven", "bin", "MAVEN_HOME", "-v" ) );
        this.typesValues
            .put( InstallationService.MAVEN2_TYPE, new ExecutorConfigurator( "mvn", "bin", "M2_HOME", "-v" ) );
    }

    /**
     * @see org.apache.maven.continuum.installation.InstallationService#add(org.apache.maven.continuum.model.system.Installation)
     */
    public Installation add( Installation installation )
        throws InstallationException, AlreadyExistsInstallationException
    {
        try
        {
            return this.add( installation, false );
        }
        catch ( AlreadyExistsProfileException e )
        {
            // normally cannot happend here but anyway we throw the exception
            throw new InstallationException( e.getMessage(), e );
        }
    }

    public Installation add( Installation installation, boolean automaticProfile )
        throws InstallationException, AlreadyExistsProfileException, AlreadyExistsInstallationException
    {
        if ( alreadyExistInstallationName( installation ) )
        {
            throw new AlreadyExistsInstallationException(
                "Installation with name " + installation.getName() + " already exists" );
        }
        // TODO must be done in the same transaction
        Installation storedOne = null;
        try
        {
            String envVarName = this.getEnvVar( installation.getType() );
            // override with the defined var name for defined types
            if ( StringUtils.isNotEmpty( envVarName ) )
            {
                installation.setVarName( envVarName );
            }
            storedOne = installationDao.addInstallation( installation );
        }
        catch ( ContinuumStoreException e )
        {
            throw new InstallationException( e.getMessage(), e );
        }
        try
        {
            if ( automaticProfile )
            {
                Profile profile = new Profile();
                profile.setName( storedOne.getName() );
                profile = profileService.addProfile( profile );
                profileService.addInstallationInProfile( profile, storedOne );
            }
        }
        catch ( ProfileException e )
        {
            throw new InstallationException( "failed to create automatic Profile " + e.getMessage(), e );
        }
        return storedOne;
    }

    /**
     * @see org.apache.maven.continuum.installation.InstallationService#delete(org.apache.maven.continuum.model.system.Installation)
     */
    public void delete( Installation installation )
        throws InstallationException
    {
        try
        {
            installationDao.removeInstallation( installation );
        }
        catch ( ContinuumStoreException e )
        {
            throw new InstallationException( e.getMessage(), e );
        }

    }

    /**
     * @see org.apache.maven.continuum.installation.InstallationService#getAllInstallations()
     */
    @SuppressWarnings("unchecked")
    public List<Installation> getAllInstallations()
        throws InstallationException
    {
        try
        {
            List installations = installationDao.getAllInstallations();
            return installations == null ? Collections.EMPTY_LIST : installations;
        }
        catch ( ContinuumStoreException e )
        {
            throw new InstallationException( e.getMessage(), e );
        }
    }

    /**
     * @see org.apache.maven.continuum.installation.InstallationService#getInstallation(int)
     */
    public Installation getInstallation( int installationId )
        throws InstallationException
    {
        try
        {
            return installationDao.getInstallation( installationId );
        }
        catch ( ContinuumStoreException e )
        {
            throw new InstallationException( e.getMessage(), e );
        }
    }

    /**
     * @see org.apache.maven.continuum.installation.InstallationService#update(org.apache.maven.continuum.model.system.Installation)
     */
    public void update( Installation installation )
        throws InstallationException
    {
        try
        {
            Installation stored = getInstallation( installation.getInstallationId() );
            if ( stored == null )
            {
                throw new InstallationException( "installation with name " + installation.getName() + " not exists" );
            }

            stored.setName( installation.getName() );
            stored.setType( installation.getType() );
            String envVarName = this.getEnvVar( installation.getType() );
            // override with the defined var name for defined types
            if ( StringUtils.isNotEmpty( envVarName ) )
            {
                installation.setVarName( envVarName );
            }
            else
            {
                stored.setVarName( installation.getVarName() );
            }
            stored.setVarValue( installation.getVarValue() );
            installationDao.updateInstallation( stored );
        }
        catch ( ContinuumStoreException e )
        {
            throw new InstallationException( e.getMessage(), e );
        }

    }

    /**
     * @see org.apache.maven.continuum.installation.InstallationService#getExecutorConfigurator(java.lang.String)
     */
    public ExecutorConfigurator getExecutorConfigurator( String type )
    {
        return this.typesValues.get( type );
    }

    /**
     * @see org.apache.maven.continuum.installation.InstallationService#getEnvVar(java.lang.String)
     */
    public String getEnvVar( String type )
    {
        ExecutorConfigurator executorConfigurator = this.typesValues.get( type );
        return executorConfigurator == null ? null : executorConfigurator.getEnvVar();
    }

    // -------------------------------------------------------------
    // versions informations on jdk and builders (mvn, maven, ant )
    // -------------------------------------------------------------

    /**
     * TODO replace with calling getExecutorConfiguratorVersion
     *
     * @see org.apache.maven.continuum.installation.InstallationService#getDefaultJdkInformations()
     */
    public List<String> getDefaultJdkInformations()
        throws InstallationException
    {
        try
        {
            Properties systemEnvVars = CommandLineUtils.getSystemEnvVars( false );

            String javaHome = (String) systemEnvVars.get( "JAVA_HOME" );
            // olamy : JAVA_HOME can not exists with a mac user
            if ( StringUtils.isEmpty( javaHome ) )
            {
                return getJavaHomeInformations( System.getProperty( "java.home" ) );
            }
            return getJavaHomeInformations( javaHome );

        }
        catch ( IOException e )
        {
            throw new InstallationException( e.getMessage(), e );
        }
        catch ( CommandLineException e )
        {
            throw new InstallationException( e.getMessage(), e );
        }
    }

    /**
     * TODO replace with calling getExecutorConfiguratorVersion
     *
     * @see org.apache.maven.continuum.installation.InstallationService#getJdkInformations(org.apache.maven.continuum.model.system.Installation)
     */
    public List<String> getJdkInformations( Installation installation )
        throws InstallationException
    {
        if ( installation == null )
        {
            return getDefaultJdkInformations();
        }
        if ( StringUtils.isEmpty( installation.getVarValue() ) )
        {
            return getDefaultJdkInformations();
        }
        try
        {
            return getJavaHomeInformations( installation.getVarValue() );
        }
        catch ( CommandLineException e )
        {
            throw new InstallationException( e.getMessage(), e );
        }
    }

    /**
     * @param javaHome
     * @return
     * @throws CommandLineException
     */
    private List<String> getJavaHomeInformations( String javaHome )
        throws CommandLineException
    {
        Commandline commandline = new Commandline();

        String executable = javaHome + File.separator + "bin" + File.separator + "java";

        commandline.setExecutable( executable );
        commandline.addArguments( new String[]{"-version"} );
        final List<String> cliOutput = new ArrayList<String>();
        //TODO ShellCommandHelper ?
        int result = CommandLineUtils.executeCommandLine( commandline, new StreamConsumer()
        {
            public void consumeLine( String line )
            {
                cliOutput.add( line );
            }
        }, new StreamConsumer()
        {
            public void consumeLine( String line )
            {
                cliOutput.add( line );
            }
        } );
        if ( result != 0 )
        {
            throw new CommandLineException( "cli to get JAVA_HOME informations return code " + result );
        }
        return cliOutput;
    }

    private Map<String, String> getEnvVars( Profile profile )
    {
        Map<String, String> environnments = new HashMap<String, String>();
        if ( profile == null )
        {
            return environnments;
        }
        if ( profile.getBuilder() != null )
        {
            environnments.put( profile.getBuilder().getVarName(), profile.getBuilder().getVarValue() );
        }
        if ( profile.getJdk() != null )
        {
            environnments.put( profile.getJdk().getVarName(), profile.getJdk().getVarValue() );
        }
        if ( profile.getEnvironmentVariables() != null )
        {
            for ( Installation installation : (List<Installation>) profile.getEnvironmentVariables() )
            {
                environnments.put( installation.getVarName(), installation.getVarValue() );
            }
        }
        return environnments;
    }

    /**
     * @see org.apache.maven.continuum.installation.InstallationService#getExecutorConfiguratorVersion(java.lang.String,org.apache.maven.continuum.execution.ExecutorConfigurator,Profile)
     */
    @SuppressWarnings("unchecked")
    public List<String> getExecutorConfiguratorVersion( String path, ExecutorConfigurator executorConfigurator,
                                                        Profile profile )
        throws InstallationException
    {

        if ( executorConfigurator == null )
        {
            return Collections.EMPTY_LIST;
        }
        if ( executorConfigurator.getExecutable() == null )
        {
            return Collections.EMPTY_LIST;
        }
        StringBuilder executable = new StringBuilder();
        try
        {
            Commandline commandline = new Commandline();
            if ( StringUtils.isNotEmpty( path ) )
            {
                executable.append( path ).append( File.separator );
                executable.append( executorConfigurator.getRelativePath() + File.separator );
                commandline.addEnvironment( executorConfigurator.getEnvVar(), path );
            }
            //Installations are env var they must be add if exists
            Map<String, String> environments = getEnvVars( profile );
            // no null check we use a private method just here
            for ( Iterator<String> iterator = environments.keySet().iterator(); iterator.hasNext(); )
            {
                String key = iterator.next();
                String value = environments.get( key );
                commandline.addEnvironment( key, value );
            }

            executable = executable.append( executorConfigurator.getExecutable() );
            commandline.setExecutable( executable.toString() );
            commandline.addArguments( new String[]{executorConfigurator.getVersionArgument()} );
            final List<String> cliOutput = new ArrayList<String>();
            //TODO ShellCommandHelper ?
            int result = CommandLineUtils.executeCommandLine( commandline, new StreamConsumer()
            {
                public void consumeLine( String line )
                {
                    cliOutput.add( line );
                }
            }, new StreamConsumer()
            {
                public void consumeLine( String line )
                {
                    cliOutput.add( line );
                }
            } );
            if ( result != 0 )
            {
                throw new InstallationException( "cli to get " + executable + " version return code " + result );
            }
            return cliOutput;
        }
        catch ( CommandLineException e )
        {
            getLogger().error(
                "fail to execute " + executable + " with arg " + executorConfigurator.getVersionArgument() );
            throw new InstallationException( e.getMessage(), e );
        }
    }

    private boolean alreadyExistInstallationName( Installation installation )
        throws InstallationException
    {
        List<Installation> all = getAllInstallations();
        for ( Installation install : all )
        {
            if ( org.apache.commons.lang.StringUtils.equals( installation.getName(), install.getName() ) )
            {
                return true;
            }
        }
        return false;
    }

}
