/*
 * 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 launchpad instance(s).
 */
@Mojo(
        name = "start",
        defaultPhase = LifecyclePhase.PRE_INTEGRATION_TEST,
        threadSafe = true
    )
public class StartMojo extends AbstractStartStopMojo {

    /**
     * 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 = "launchpad.debug")
    protected String debug;

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

    /**
     * The launchpad jar. This option has precedence over "launchpadDependency".
     */
    @Parameter(property = "launchpad.jar")
    private File launchpadJar;

    /**
     * The launchpad jar as a dependency. This is only used if "launchpadJar" is not
     * specified.
     */
    @Parameter
    private Dependency launchpadDependency;

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

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

    /**
     * Set the execution of launchpad instances to be run in parallel (threads)
     */
    @Parameter(property = "launchpad.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 = getLaunchpadConfigurations();

        // create the common environment
        getLog().info("Keep Launchpad Running: " + this.keepLaunchpadRunning);
        final LaunchpadEnvironment env = new LaunchpadEnvironment(this.findLaunchpadJar(),
                this.cleanWorkingDirectory,
                !this.keepLaunchpadRunning,
                this.launchpadReadyTimeOutSec,
                this.debug);

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

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

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

        // create the launchpad runner properties
        this.createLaunchpadRunnerProperties(configurations);

        if (parallelExecution) {
            // ExecutorService for starting launchpad 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.keepLaunchpadRunning) {
            getLog().info("Press CTRL-C to stop launchpad instance(s)...");
            while ( true && this.isRunning(tasks)) {
                try {
                    Thread.sleep(5000);
                } catch (final InterruptedException ie) {
                    break;
                }
            }
        }
        blockIfNecessary();
    }

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

    private void createLaunchpadRunnerProperties(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("launchpad.skip.startupcheck", "true");

            // write out all instances
            int index = 0;
            for (final ServerConfiguration launchpadConfiguration : configurations) {
                index++;
                props.put("launchpad.instance.id." + String.valueOf(index), launchpadConfiguration.getId());
                String runMode = launchpadConfiguration.getRunmode();
                if ( runMode == null ) {
                    runMode = "";
                }
                props.put("launchpad.instance.runmode." + String.valueOf(index), runMode);
                props.put("launchpad.instance.server." + String.valueOf(index), launchpadConfiguration.getServer());
                props.put("launchpad.instance.port." + String.valueOf(index), launchpadConfiguration.getPort());
                props.put("launchpad.instance.contextPath." + String.valueOf(index), launchpadConfiguration.getContextPath());
                final String url = createServerUrl(launchpadConfiguration);
                props.put("launchpad.instance.url." + String.valueOf(index), url);
            }
            props.put("launchpad.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 launchpadConfiguration
     */
    private LauncherCallable createTask(final ServerConfiguration launchpadConfiguration,
                                               final LaunchpadEnvironment env)
    throws MojoExecutionException, MojoFailureException {
        final String id = launchpadConfiguration.getId();
        getLog().debug(new StringBuilder("Starting ").append(id).
                append(" with runmode ").append(launchpadConfiguration.getRunmode()).
                append(" on port ").append(launchpadConfiguration.getPort()).
                append(" in folder ").append(launchpadConfiguration.getFolder().getAbsolutePath()).toString());

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

    }

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

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

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

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

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

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

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

        // If a launchpad dependency is configured, resolve it
        if (launchpadDependency != null) {
            getLog().info("Using launchpad dependency '" +  launchpadDependency + "' given as configuration parameter!");
            return getArtifact(launchpadDependency).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 launchpad 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 launchpad 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 launchpad 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 launchpad 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 launchpad jar from first dependency of type 'slingstart': '"+ d +"'!");
                return getArtifact(d).getFile();
            }
        }

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

    /**
     * Get all configurations
     * @return Collection of configurations.
     */
    private Collection<ServerConfiguration> getLaunchpadConfigurations() {
        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;
    }
}
