/*
 * 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.slingstart.feature.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.slingstart.feature.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
        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_SLINGSTART)) {
            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_SLINGSTART.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;
    }
}
