/*
 * 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.run;

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;

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.AbstractMojo;
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.BuildConstants;

/**
 * Mojo for starting launchpad.
 */
@Mojo(
        name = "start",
        defaultPhase = LifecyclePhase.PRE_INTEGRATION_TEST,
        threadSafe = true
    )
public class StartMojo extends AbstractMojo {

    /**
     * Set this to "true" to skip starting the launchpad
     *
     */
    @Parameter(property = "maven.test.skip", defaultValue = "false")
    protected boolean skipLaunchpad;

    /**
     * Parameter containing the list of server configurations
     */
    @Parameter
    private List<ServerConfiguration> servers;
    
    /**
     * 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.
     */
    @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 system properties file will contain all started instances with their ports etc.
     */
    @Parameter(defaultValue = "${project.build.directory}/launchpad-runner.properties")
    protected File systemPropertiesFile;

    /**
     * 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;
    }

    /**
     * @see org.apache.maven.plugin.Mojo#execute()
     */
    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        if (this.skipLaunchpad) {
            this.getLog().info("Executing of the start launchpad mojo is disabled by configuration.");
            return;
        }

        // 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;
                }
            }
        }
    }

    /**
     * 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)) {
            final File jarFile = new File(this.project.getBuild().getDirectory(), this.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();
            }
        }

        // 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;
    }
}
