/*
 * 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.
 */
package org.apache.sling.maven.kickstart.run;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.sling.maven.kickstart.BuildConstants;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * Start one or multiple Kickstart instance(s).
 */
@Mojo(
        name = "start",
        defaultPhase = LifecyclePhase.PRE_INTEGRATION_TEST,
        threadSafe = true
    )
public class StartMojo extends AbstractStartStopMojo {

    private static Dependency defaultKickstart = new Dependency();

    static {
        defaultKickstart.setGroupId("org.apache.sling");
        defaultKickstart.setArtifactId("org.apache.sling.kickstart");
        defaultKickstart.setVersion("0.0.6");
    }

    /**
     * Overwrites debug parameter of all server configurations (if set).
     * Attaches a debugger to the forked JVM. If set to {@code "true"}, the process will allow a debugger to connect on port 8000.
     * If set to some other string, that string will be appended to the server's {@code vmOpts}, allowing you to configure arbitrary debugging options.
     */
    @Parameter(property = "kickstart.debug")
    protected String debug;

    /**
     * Ready timeout in seconds. If the kickstart has not been started in this
     * time, it's assumed that the startup failed.
     */
    @Parameter(property = "kickstart.ready.timeout", defaultValue = "600")
    private int kickstartReadyTimeOutSec;

    /**
     * The kickstart jar. This option has precedence over "kickstartDependency".
     */
    @Parameter(property = "kickstart.jar")
    private File kickstartJar;

    /**
     * The kickstart jar as a dependency. This is only used if "kickstartJar" is not
     * specified.
     */
    @Parameter
    private Dependency kickstartDependency = defaultKickstart;

    /**
     * Clean the working directory before start.
     */
    @Parameter(property = "kickstart.clean.workdir", defaultValue = "false")
    private boolean cleanWorkingDirectory;

    /**
     * Keep the kickstart running.
     * @deprecated Use {@link AbstractStartStopMojo# blockUntilKeyIsPressed} instead.
     */
    @Deprecated
    @Parameter(property = "kickstart.keep.running", defaultValue = "false")
    private boolean keepKickstartRunning;

    /**
     * Set the execution of kickstart instances to be run in parallel (threads)
     */
    @Parameter(property = "kickstart.parallelExecution", defaultValue = "true")
    private boolean parallelExecution;

    /**
     * The Maven project.
     */
    @Parameter(property = "project", readonly = true, required = true)
    private MavenProject project;

    /**
     * The Maven session.
     */
    @Parameter(property = "session", readonly = true, required = true)
    private MavenSession mavenSession;

    @Component
    private ArtifactHandlerManager artifactHandlerManager;

    /**
     * Used to look up Artifacts in the remote repository.
     *
     */
    @Component
    private ArtifactResolver resolver;

    /**
     * Get a resolved Artifact from the coordinates provided
     *
     * @return the artifact, which has been resolved.
     * @throws MojoExecutionException
     */
    private Artifact getArtifact(final Dependency d)
            throws MojoExecutionException {
        final Artifact prjArtifact = new DefaultArtifact(d.getGroupId(),
                        d.getArtifactId(),
                        VersionRange.createFromVersion(d.getVersion()),
                        d.getScope(),
                        d.getType(),
                        d.getClassifier(),
                        this.artifactHandlerManager.getArtifactHandler(d.getType()));
        try {
            this.resolver.resolve(prjArtifact, this.project.getRemoteArtifactRepositories(), this.mavenSession.getLocalRepository());
        } catch (final ArtifactResolutionException e) {
            throw new MojoExecutionException("Unable to get artifact for " + d, e);
        } catch (ArtifactNotFoundException e) {
            throw new MojoExecutionException("Unable to get artifact for " + d, e);
        }

        return prjArtifact;
    }

    
    @Override
    protected void doExecute() throws MojoExecutionException, MojoFailureException {
        // delete properties
        if ( systemPropertiesFile != null && systemPropertiesFile.exists() ) {
            FileUtils.deleteQuietly(this.systemPropertiesFile);
        }

        // get configurations
        final Collection<ServerConfiguration> configurations = getKickstartConfigurations();

        // create the common environment
        getLog().info("Keep kickstart Running: " + this.keepKickstartRunning);
        final KickstartEnvironment env = new KickstartEnvironment(this.findKickstartJar(),
                this.cleanWorkingDirectory,
                !this.keepKickstartRunning,
                this.kickstartReadyTimeOutSec,
                this.debug);

        // create callables
        final Collection<LauncherCallable> tasks = new LinkedList<LauncherCallable>();

        for (final ServerConfiguration kickstartConfiguration : configurations) {
            validateConfiguration(kickstartConfiguration);

            tasks.add(createTask(kickstartConfiguration, env));
        }

        // create the kickstart runner properties
        this.createKickstartRunnerProperties(configurations);

        if (parallelExecution) {
            // ExecutorService for starting kickstart instances in parallel
            final ExecutorService executor = Executors.newCachedThreadPool();
            try {
                final List<Future<ProcessDescription>> resultsCollector = executor.invokeAll(tasks);
                for (final Future<ProcessDescription> future : resultsCollector) {
                    try {
                        if (null == future.get()) {
                            throw new MojoExecutionException("Cannot start all the instances");
                        }
                    } catch (final ExecutionException e) {
                        throw new MojoExecutionException(e.getLocalizedMessage(), e);
                    }
                }
            } catch ( final InterruptedException e) {
                throw new MojoExecutionException(e.getLocalizedMessage(), e);
            }
        } else {
            for (final LauncherCallable task : tasks) {
                try {
                    if (null == task.call()) {
                        throw new MojoExecutionException("Cannot start all the instances");
                    }
                } catch (final Exception e) {
                    throw new MojoExecutionException(e.getLocalizedMessage(), e);
                }
            }
        }
        if (this.keepKickstartRunning) {
            getLog().info("Press CTRL-C to stop kickstart instance(s)...");
            while ( true && this.isRunning(tasks)) {
                try {
                    Thread.sleep(5000);
                } catch (final InterruptedException ie) {
                    break;
                }
            }
        }
        blockIfNecessary();
    }

    /**
     * Are all kickstarts still running?
     */
    private boolean isRunning(final Collection<LauncherCallable> tasks) {
        for(final LauncherCallable task : tasks) {
            if ( !task.isRunning() ) {
                return false;
            }
        }
        return true;
    }

    private void createKickstartRunnerProperties(final Collection<ServerConfiguration> configurations)
    throws MojoExecutionException {
        // create properties
        OutputStream writer = null;
        final Properties props = new Properties();
        try {
            writer = new FileOutputStream(this.systemPropertiesFile);

            // disable sling startup check
            props.put("kickstart.skip.startupcheck", "true");

            // write out all instances
            int index = 0;
            for (final ServerConfiguration kickstartConfiguration : configurations) {
                index++;
                props.put("kickstart.instance.id." + String.valueOf(index), kickstartConfiguration.getId());
                String runMode = kickstartConfiguration.getRunmode();
                if ( runMode == null ) {
                    runMode = "";
                }
                props.put("kickstart.instance.runmode." + String.valueOf(index), runMode);
                props.put("kickstart.instance.server." + String.valueOf(index), kickstartConfiguration.getServer());
                props.put("kickstart.instance.port." + String.valueOf(index), kickstartConfiguration.getPort());
                props.put("kickstart.instance.contextPath." + String.valueOf(index), kickstartConfiguration.getContextPath());
                final String url = createServerUrl(kickstartConfiguration);
                props.put("kickstart.instance.url." + String.valueOf(index), url);
            }
            props.put("kickstart.instances", String.valueOf(index));

            props.store(writer, null);
        } catch (final IOException e) {
            throw new MojoExecutionException(e.getLocalizedMessage(), e);
        } finally {
            IOUtils.closeQuietly(writer);
        }
    }

    private static String createServerUrl(final ServerConfiguration qc) {
        final StringBuilder sb = new StringBuilder();
        sb.append("http://");
        sb.append(qc.getServer());
        if ( !qc.getPort().equals("80") ) {
            sb.append(':');
            sb.append(qc.getPort());
        }
        final String contextPath = qc.getContextPath();
        if ( contextPath != null && contextPath.trim().length() > 0 && !contextPath.equals("/") ) {
            if ( !contextPath.startsWith("/") ) {
                sb.append('/');
            }
            if ( contextPath.endsWith("/") ) {
                sb.append(contextPath, 0, contextPath.length()-1);
            } else {
                sb.append(contextPath);
            }
        }
        return sb.toString();
    }

    /**
     * @param kickstartConfiguration
     */
    private LauncherCallable createTask(final ServerConfiguration kickstartConfiguration,
                                               final KickstartEnvironment env)
    throws MojoExecutionException, MojoFailureException {
        final String id = kickstartConfiguration.getId();
        getLog().debug(new StringBuilder("Starting ").append(id).
                append(" with runmode ").append(kickstartConfiguration.getRunmode()).
                append(" on port ").append(kickstartConfiguration.getPort()).
                append(" in folder ").append(kickstartConfiguration.getFolder().getAbsolutePath()).toString());

        // create task
        return new LauncherCallable(this.getLog(), kickstartConfiguration, env);

    }

    /**
     * Validate a configuration
     * @param kickstartConfiguration The kickstart configuration
     * @throws MojoExecutionException
     */
    private void validateConfiguration(final ServerConfiguration kickstartConfiguration)
    throws MojoExecutionException {
        if ( kickstartConfiguration.getPort() == null ) {
            kickstartConfiguration.setPort(String.valueOf(PortHelper.getNextAvailablePort()));
        }

        if ( kickstartConfiguration.getControlPort() == null ) {
            kickstartConfiguration.setControlPort(String.valueOf(PortHelper.getNextAvailablePort()));
        }

        // set the id of the kickstart
        if ( kickstartConfiguration.getId() == null || kickstartConfiguration.getId().trim().length() == 0 ) {
            String runMode = kickstartConfiguration.getRunmode();
            if ( runMode == null ) {
                runMode = "_";
            }
            final String id = new StringBuilder(runMode.replace(',', '_')).append('-').append(kickstartConfiguration.getPort()).toString();
            kickstartConfiguration.setId(id);
        }

        // populate folder if not set
        if (kickstartConfiguration.getFolder() == null) {
            final File folder = new File(new StringBuilder(this.project.getBuild().getDirectory()).append('/').append(kickstartConfiguration.getId()).toString());
            kickstartConfiguration.setFolder(folder);
        }
        // context path should not be null
        if ( kickstartConfiguration.getContextPath() == null ) {
            kickstartConfiguration.setContextPath("");
        }

        if ( kickstartConfiguration.getInstances() < 0 ) {
            kickstartConfiguration.setInstances(1);
        }
    }

    /**
     * Finds the kickstart.jar artifact of the project being built.
     *
     * @return the kickstart.jar artifact
     * @throws MojoFailureException if a kickstart.jar artifact was not found
     */
    private File findKickstartJar() throws MojoFailureException, MojoExecutionException {

        // If a kickstart JAR is specified, use it
        if (kickstartJar != null) {
            getLog().info("Using kickstart jar from '" +  kickstartJar + "' given as configuration parameter!");
            return kickstartJar;
        }

        // If a kickstart dependency is configured, resolve it
        if (kickstartDependency != null) {
            getLog().info("Using kickstart dependency '" +  kickstartDependency + "' given as configuration parameter!");
            return getArtifact(kickstartDependency).getFile();
        }

        // If the current project is a slingstart project, use its JAR artifact
        if (this.project.getPackaging().equals(BuildConstants.PACKAGING_SLINGQUICKSTART)) {
            File jarFile = project.getArtifact().getFile();
            if (jarFile != null && jarFile.exists()) {
                getLog().info("Using kickstart jar being generated as this project's primary artifact: '" +  jarFile + "'!");
                return jarFile;
            }
            else {
                jarFile = new File(project.getBuild().getDirectory(), project.getBuild().getFinalName() + ".jar");
                if (jarFile.exists()) {
                    getLog().info("Using kickstart jar being generated as this project's primary artifact: '" +  jarFile + "'!");
                    return jarFile;
                }
            }
        }

        // In case there was a provisioning model found but this is not a slingstart project, the JAR might be attached already through goal "package"
        for (Artifact attachedArtifact : project.getAttachedArtifacts()) {
            // find the attached artifact with classifier "standalone"
            if (BuildConstants.TYPE_JAR.equals(attachedArtifact.getType()) && BuildConstants.CLASSIFIER_APP.equals(attachedArtifact.getClassifier())) {
                getLog().info("Using kickstart jar being attached as additional project artifact: '" +  attachedArtifact.getFile() + "'!");
                return attachedArtifact.getFile();
            }
        }
        
        // also check for jars in known target folders (in case the jar has been created in this project's target folder but not attached to the Maven project)
//AS TODO: Is Package Mojo still needed / supported ?
//        File localJarFile = PackageMojo.getNonPrimaryBuildFile(project, ".jar");
//        if (localJarFile.exists()) {
//            getLog().info("Using local kickstart jar being created in predefined directory: '" +  localJarFile + "'!");
//            return localJarFile;
//        }
        
        // Last chance: use the first declared dependency with type "slingstart"
        final Set<Artifact> dependencies = this.project.getDependencyArtifacts();
        for (final Artifact dep : dependencies) {
            if (BuildConstants.PACKAGING_SLINGQUICKSTART.equals(dep.getType())) {
                final Dependency d = new Dependency();
                d.setGroupId(dep.getGroupId());
                d.setArtifactId(dep.getArtifactId());
                d.setVersion(dep.getVersion());
                d.setScope(Artifact.SCOPE_RUNTIME);
                d.setType(BuildConstants.TYPE_JAR);
                getLog().info("Using kickstart jar from first dependency of type 'slingstart': '"+ d +"'!");
                return getArtifact(d).getFile();
            }
        }

        // kickstart has not been found, throw an exception
        throw new MojoFailureException("Could not find the kickstart jar. " +
                "Either specify the 'kickstartJar' configuration or use this inside a slingstart project.");
    }

    /**
     * Get all configurations
     * @return Collection of configurations.
     */
    private Collection<ServerConfiguration> getKickstartConfigurations() {
        final List<ServerConfiguration> configs = new ArrayList<ServerConfiguration>();
        if ( this.servers != null && !this.servers.isEmpty() ) {
            for(final ServerConfiguration config : this.servers) {
                // if instances is set to 0, no instance is added
                if ( config.getInstances() != 0 ) {
                    configs.add(config);
                    for(int i=2; i<=config.getInstances();i++) {
                        final ServerConfiguration replicaConfig = config.copy();
                        replicaConfig.setPort(null);
                        final File folder = replicaConfig.getFolder();
                        if ( folder != null ) {
                            replicaConfig.setFolder(new File(folder.getParentFile(), folder.getName() + '-' + String.valueOf(i)));
                        }
                        configs.add(replicaConfig);
                    }
                    config.setInstances(1);
                }
            }
        } else {
            // use single default instance
            configs.add(new ServerConfiguration());
        }
        return configs;
    }
}
