/*
 * 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.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.lang.ProcessBuilder.Redirect;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;

import org.apache.commons.io.IOUtils;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.shared.utils.StringUtils;
import org.apache.sling.maven.slingstart.launcher.Main;

/**
 * A callable for launchpad an instance
 */
public class LauncherCallable implements Callable<ProcessDescription> {

    private final LaunchpadEnvironment environment;
    private final ServerConfiguration configuration;
    private final Log logger;

    public LauncherCallable(final Log logger,
                                  final ServerConfiguration configuration,
                                  final LaunchpadEnvironment environment) {
        this.logger = logger;
        this.configuration = configuration;
        this.environment = environment;
    }

    /**
     * @see java.util.concurrent.Callable#call()
     */
    @Override
    public ProcessDescription call() throws Exception {

        // fail if launchpad with this id is already started
        if (!ProcessDescriptionProvider.getInstance().isRunConfigurationAvailable(configuration.getId())) {
            throw new Exception("Launchpad with id " + configuration.getId() + " is not available");
        }

        // get the launchpad jar
        final File launchpad = this.environment.prepare(this.configuration.getFolder());

        // Lock the launchpad id
        final String launchpadKey = ProcessDescriptionProvider.getInstance().getId(configuration.getId());

        // start launchpad
        ProcessDescription cfg = this.start(launchpad);

        // Add thread hook to shutdown launchpad
        if (environment.isShutdownOnExit()) {
            cfg.installShutdownHook();
        }

        // Add configuration to the config provider
        ProcessDescriptionProvider.getInstance().addRunConfiguration(cfg, launchpadKey);

        boolean started = false;
        try {
            final long endTime = System.currentTimeMillis() + this.environment.getReadyTimeOutSec() * 1000;
            boolean finished = false;
            while ( !started && !finished && System.currentTimeMillis() < endTime ) {
                Thread.sleep(5000);
                started = cfg.getControlListener().isStarted();
                try {
                    // if we get an exit value, the process has stopped
                    cfg.getProcess().exitValue();
                    finished = true;
                } catch ( final IllegalThreadStateException itse) {
                    // everything as expected
                }
            }

            if ( finished ) {
                throw new Exception("Launchpad did exit unexpectedly.");
            }
            if ( !started ) {
                throw new Exception("Launchpad did not start successfully in " + this.environment.getReadyTimeOutSec() + " seconds.");
            }
            this.logger.info("Started Launchpad '" + configuration.getId() +
                    "' at port " + configuration.getPort()+ " [run modes: " + configuration.getRunmode()+ "]");
        } finally {
            // stop control port
            cfg.getControlListener().stop();

            // call launchpad stop routine if not properly started
            if (!started) {
                stop(this.logger, cfg);
                ProcessDescriptionProvider.getInstance().removeRunConfiguration(cfg.getId());
                cfg = null;
            }
        }

        return cfg;
    }

    public boolean isRunning() {
        return getControlPortFile(this.configuration.getFolder()).exists();
    }

    private void add(final List<String> args, final String value) {
        if ( value != null ) {
            final String[] single = value.trim().split(" ");
            for(final String v : single) {
                if ( v.trim().length() > 0 ) {
                    args.add(v.trim());
                }
            }
        }
    }

    private ProcessDescription start(final File jar) throws Exception {
        final ProcessDescription cfg = new ProcessDescription(this.configuration.getId(), this.configuration.getFolder());

        final ProcessBuilder builder = new ProcessBuilder();
        final List<String> args = new ArrayList<String>();

        args.add("java");
        add(args, this.configuration.getVmOpts());
        add(args, this.configuration.getVmDebugOpts(this.environment.getDebug()));

        args.add("-cp");
        args.add("bin");
        args.add(Main.class.getName());
        // first three arguments: jar, listener port, verbose
        args.add(jar.getPath());
        args.add(String.valueOf(cfg.getControlListener().getPort()));
        args.add("true");

        // from here on launchpad properties
        add(args, this.configuration.getOpts());

        final String contextPath = this.configuration.getContextPath();
        if ( contextPath != null && contextPath.length() > 0 && !contextPath.equals("/") ) {
            args.add("-r");
            args.add(contextPath);
        }

        if ( this.configuration.getPort() != null ) {
            args.add("-p");
            args.add(this.configuration.getPort());
        }

        if ( this.configuration.getControlPort() != null ) {
            args.add("-j");
            args.add(this.configuration.getControlPort());
        }
        if ( this.configuration.getRunmode() != null && this.configuration.getRunmode().length() > 0 ) {
            args.add("-Dsling.run.modes=" + this.configuration.getRunmode());
        }
        if ( !this.environment.isShutdownOnExit() ) {
            args.add("start");
        }

        builder.command(args.toArray(new String[args.size()]));
        builder.directory(this.configuration.getFolder());
        builder.redirectErrorStream(true);
        logger.info("Starting Launchpad " + this.configuration.getId() +  "...");
        String stdOutFile = this.configuration.getStdOutFile();
        if (StringUtils.isNotBlank(stdOutFile)) {
            File absoluteStdOutFile = new File(builder.directory(), stdOutFile);
            // make sure to create the parent directories (if they do not exist yet)
            absoluteStdOutFile.getParentFile().mkdirs();
            builder.redirectOutput(absoluteStdOutFile);
            logger.info("Redirecting stdout and stderr to " + absoluteStdOutFile);
        } else {
            builder.redirectOutput(Redirect.INHERIT);
        }

        logger.debug("Launchpad cmd: " + builder.command());
        logger.debug("Launchpad dir: " + builder.directory());

        try {
            cfg.setProcess(builder.start());
        } catch (final IOException e) {
            if (cfg.getProcess() != null) {
                cfg.getProcess().destroy();
                cfg.setProcess(null);
            }
            throw new Exception("Could not start the Launchpad", e);
        }

        return cfg;
    }

    public static void stop(final Log LOG, final ProcessDescription cfg) throws Exception {
        boolean isNew = false;

        if (cfg.getProcess() != null || isNew ) {
            LOG.info("Stopping Launchpad '" + cfg.getId() + "'");
            boolean destroy = true;
            final int twoMinutes = 2 * 60 * 1000;
            final File controlPortFile = getControlPortFile(cfg.getDirectory());
            LOG.debug("Control port file " + controlPortFile + " exists: " + controlPortFile.exists());
            if ( controlPortFile.exists() ) {
                // reading control port
                int controlPort = -1;
                String secretKey = null;
                LineNumberReader lnr = null;
                String serverName = null;
                try {
                    lnr = new LineNumberReader(new FileReader(controlPortFile));
                    final String portLine = lnr.readLine();
                    final int pos = portLine.indexOf(':');
                    controlPort = Integer.parseInt(portLine.substring(pos + 1));
                    if ( pos > 0 ) {
                        serverName = portLine.substring(0, pos);
                    }
                    secretKey = lnr.readLine();
                } catch ( final NumberFormatException ignore) {
                    // we ignore this
                    LOG.debug("Error reading control port file " + controlPortFile, ignore);
                } catch ( final IOException ignore) {
                    // we ignore this
                    LOG.debug("Error reading control port file " + controlPortFile, ignore);
                } finally {
                    IOUtils.closeQuietly(lnr);
                }

                if ( controlPort != -1 ) {
                    final List<String> hosts = new ArrayList<String>();
                    if ( serverName != null ) {
                        hosts.add(serverName);
                    }
                    hosts.add("localhost");
                    hosts.add("127.0.0.1");
                    LOG.debug("Found control port " + controlPort);
                    int index = 0;
                    while ( destroy && index < hosts.size() ) {
                        final String hostName = hosts.get(index);

                        Socket clientSocket = null;
                        DataOutputStream out = null;
                        BufferedReader in = null;
                        try {
                            LOG.debug("Trying to connect to " + hostName + ":" + controlPort);
                            clientSocket = new Socket();
                            // set a socket timeout
                            clientSocket.connect(new InetSocketAddress(hostName, controlPort), twoMinutes);
                            // without that, read() call on the InputStream associated with this Socket is infinite
                            clientSocket.setSoTimeout(twoMinutes);

                            LOG.debug(hostName + ":" + controlPort + " connection estabilished, sending the 'stop' command...");

                            out = new DataOutputStream(clientSocket.getOutputStream());
                            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                            if (secretKey != null) {
                                out.writeBytes(secretKey);
                                out.write(' ');
                            }
                            out.writeBytes("stop\n");
                            in.readLine();
                            destroy = false;
                            LOG.debug("'stop' command sent to " + hostName + ":" + controlPort);
                        } catch (final Throwable ignore) {
                            // catch Throwable because InetSocketAddress and Socket#connect throws unchecked exceptions
                            // we ignore this for now
                            LOG.debug("Error sending 'stop' command to " + hostName + ":" + controlPort + " due to: " + ignore.getMessage());
                        } finally {
                            IOUtils.closeQuietly(in);
                            IOUtils.closeQuietly(out);
                            IOUtils.closeQuietly(clientSocket);
                        }
                        index++;
                    }
                }
            }
            if ( cfg.getProcess() != null ) {
                final Process process = cfg.getProcess();

                if (!destroy) {
                    // as shutdown might block forever, we use a timeout
                    final long now = System.currentTimeMillis();
                    final long end = now + twoMinutes;

                    LOG.debug("Waiting for process to stop...");

                    while (isAlive(process) && (System.currentTimeMillis() < end)) {
                        try {
                            Thread.sleep(2500);
                        } catch (InterruptedException e) {
                            // ignore
                        }
                    }
                    if (isAlive( process)) {
                        LOG.debug("Process timeout out after 2 minutes");
                        destroy = true;
                    } else {
                        LOG.debug("Process stopped");
                    }
                }

                if (destroy) {
                    LOG.debug("Destroying process...");
                    process.destroy();
                    LOG.debug("Process destroyed");
                }

                cfg.setProcess(null);
            }
        } else {
            LOG.warn("Launchpad already stopped");
        }
    }

    private static boolean isAlive(Process process) {
        try {
            process.exitValue();
            return false;
        } catch (IllegalThreadStateException e) {
            return true;
        }
    }

    private static File getControlPortFile(final File directory) {
        final File launchpadDir = new File(directory, LaunchpadEnvironment.WORK_DIR_NAME);
        final File confDir = new File(launchpadDir, "conf");
        final File controlPortFile = new File(confDir, "controlport");
        return controlPortFile;
    }
}