package org.apache.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.continuum.utils.shell.ExecutionResult;
import org.apache.continuum.utils.shell.ListOutputConsumer;
import org.apache.continuum.utils.shell.OutputConsumer;
import org.apache.continuum.utils.shell.ShellCommandHelper;
import org.apache.maven.continuum.execution.ExecutorConfigurator;
import org.apache.maven.continuum.installation.AlreadyExistsInstallationException;
import org.apache.maven.continuum.installation.InstallationException;
import org.apache.maven.continuum.installation.InstallationService;
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.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.codehaus.plexus.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.annotation.Resource;

/**
 * @author <a href="mailto:olamy@codehaus.org">olamy</a>
 * @version $Id$
 *          TODO use some cache mechanism to prevent always reading from store ?
 * @since 13 juin 07
 */
@Service( "installationService" )
public class DefaultInstallationService
    implements InstallationService, Initializable
{
    private static final Logger log = LoggerFactory.getLogger( DefaultInstallationService.class );

    @Resource
    private InstallationDao installationDao;

    @Resource
    private ProfileService profileService;

    @Resource
    private ShellCommandHelper shellCommandHelper;

    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;
        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<Installation> 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#getInstallation(String)
     */
    public Installation getInstallation( String installationName )
        throws InstallationException
    {
        try
        {
            return installationDao.getInstallation( installationName );
        }
        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, AlreadyExistsInstallationException
    {
        try
        {
            Installation stored = getInstallation( installation.getInstallationId() );
            if ( stored == null )
            {
                throw new InstallationException( "installation with name " + installation.getName() + " not exists" );
            }

            stored.setName( installation.getName() );
            if ( alreadyExistInstallationName( installation ) )
            {
                throw new AlreadyExistsInstallationException(
                    "Installation with name " + installation.getName() + " already exists" );
            }
            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 getExecutorVersionInfo
     *
     * @see org.apache.maven.continuum.installation.InstallationService#getDefaultJavaVersionInfo()
     */
    public List<String> getDefaultJavaVersionInfo()
        throws InstallationException
    {
        try
        {
            Properties systemEnvVars = shellCommandHelper.getSystemEnvVars();
            String javaHome = (String) systemEnvVars.get( "JAVA_HOME" );
            // olamy : JAVA_HOME may not exist for mac users
            if ( StringUtils.isEmpty( javaHome ) )
            {
                return getJavaVersionInfo( System.getProperty( "java.home" ) );
            }
            return getJavaVersionInfo( javaHome );

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

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

    /**
     * @param homePath
     * @return
     * @throws Exception
     */
    private List<String> getJavaVersionInfo( String homePath )
        throws Exception
    {

        String executable = homePath + File.separator + "bin" + File.separator + "java";
        ListOutputConsumer outputConsumer = new ListOutputConsumer();
        ExecutionResult result = shellCommandHelper.executeShellCommand( null, executable, new String[] { "-version" },
                                                                         outputConsumer, -1, null );
        int exitCode = result.getExitCode();
        if ( exitCode != 0 )
        {
            throw new Exception(
                String.format( "failed to get java version information, %s returned exit code %s", executable,
                               exitCode ) );
        }
        return outputConsumer.getList();
    }

    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#getExecutorVersionInfo(java.lang.String, org.apache.maven.continuum.execution.ExecutorConfigurator, Profile)
     */
    public List<String> getExecutorVersionInfo( String path, ExecutorConfigurator executorConfigurator,
                                                Profile profile )
        throws InstallationException
    {
        if ( executorConfigurator == null || executorConfigurator.getExecutable() == null )
        {
            return Collections.EMPTY_LIST;
        }

        StringBuilder executable = new StringBuilder();

        Map<String, String> env = new HashMap<String, String>();

        if ( StringUtils.isNotEmpty( path ) )
        {
            executable.append( path ).append( File.separator );
            executable.append( executorConfigurator.getRelativePath() ).append( File.separator );
            env.put( executorConfigurator.getEnvVar(), path );
        }
        executable = executable.append( executorConfigurator.getExecutable() );

        env.putAll( getEnvVars( profile ) );

        ListOutputConsumer outputConsumer = new ListOutputConsumer();
        ExecutionResult result;
        try
        {
            result = shellCommandHelper.executeShellCommand( null, executable.toString(),
                                                             new String[] { executorConfigurator.getVersionArgument() },
                                                             outputConsumer, -1, null );
        }
        catch ( Exception e )
        {
            log.error( "failed to get executor version info", e );
            throw new InstallationException( e.getMessage(), e );
        }
        int exitCode = result.getExitCode();
        if ( exitCode != 0 )
        {

            throw new InstallationException(
                String.format( "failed to get executor version info, %s returned exit code %s", executable,
                               exitCode ) );
        }
        return outputConsumer.getList();
    }

    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() ) &&
                ( installation.getInstallationId() == 0 ||
                    installation.getInstallationId() != install.getInstallationId() ) )
            {
                return true;
            }
        }
        return false;
    }

}
