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

import org.apache.openejb.OpenEJBRuntimeException;
import org.apache.openejb.loader.Options;
import org.apache.openejb.util.Join;
import org.apache.openejb.util.Pipe;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;

//import org.apache.openejb.loader.IO;

/**
 * NOTE: Do not add inner or anonymous classes or a dependency without updating ExecMojo
 *
 * @version $Rev$ $Date$
 */
@SuppressWarnings("UseOfSystemOutOrSystemErr")
public class RemoteServer {

    private static final Options options = new Options(System.getProperties());
    public static final String SERVER_DEBUG_PORT = "server.debug.port";
    public static final String SERVER_SHUTDOWN_PORT = "server.shutdown.port";
    public static final String SERVER_SHUTDOWN_HOST = "server.shutdown.host";
    public static final String SERVER_SHUTDOWN_COMMAND = "server.shutdown.command";
    public static final String OPENEJB_SERVER_DEBUG = "openejb.server.debug";
    public static final String START = "start";
    public static final String STOP = "stop";

    private final boolean debug = options.get(OPENEJB_SERVER_DEBUG, false);
    private final boolean profile = options.get("openejb.server.profile", false);
    private final boolean tomcat;
    private final String javaOpts = System.getProperty("java.opts");
    private String additionalClasspath;

    /**
     * Has the remote server's instance been already running ?
     */
    private boolean serverHasAlreadyBeenStarted = true;

    private Properties properties;
    private final AtomicReference<Process> server = new AtomicReference<Process>();
    private final int tries;
    private final boolean verbose;
    private final int portShutdown;
    private final String host;
    private final String command;
    private File home;
    private int portStartup;

    public RemoteServer() {
        this(options.get("connect.tries", 60), options.get("verbose", false));
    }

    public RemoteServer(final int tries, final boolean verbose) {
        this.tries = (tries < 1 ? 1 : (tries > 3600 ? 3600 : tries)); //Wait at least 1 second to start or stop, but not more than an hour.
        this.verbose = verbose;
        home = getHome();
        tomcat = (home != null) && (new File(new File(home, "bin"), "catalina.sh").exists());

        portShutdown = options.get(SERVER_SHUTDOWN_PORT, tomcat ? 8005 : 4200);
        portStartup = portShutdown;
        command = options.get(SERVER_SHUTDOWN_COMMAND, "SHUTDOWN");
        host = options.get(SERVER_SHUTDOWN_HOST, "localhost");
    }

    public void init(final Properties props) {
        properties = props;

        props.put("java.naming.factory.initial", "org.apache.openejb.client.RemoteInitialContextFactory");
        final int port = options.get("ejbd.port", 4201);
        props.put("java.naming.provider.url", options.get("java.naming.provider.url", "127.0.0.1:" + port));
        props.put("java.naming.security.principal", "testuser");
        props.put("java.naming.security.credentials", "testpassword");
    }

    public static void main(final String[] args) {
        assert args.length > 0 : "no arguments supplied: valid arguments are 'start' or 'stop'";
        if (args[0].equalsIgnoreCase(START)) {
            final RemoteServer remoteServer = new RemoteServer();
            try {
                remoteServer.start();
            } catch (final Exception e) {
                remoteServer.destroy();
                e.printStackTrace(System.err);
            }
        } else if (args[0].equalsIgnoreCase(STOP)) {
            final RemoteServer remoteServer = new RemoteServer();
            remoteServer.serverHasAlreadyBeenStarted = false;
            try {
                remoteServer.forceStop();
            } catch (final Exception e) {
                e.printStackTrace(System.err);
            }
        } else {
            throw new OpenEJBRuntimeException("valid arguments are 'start' or 'stop'");
        }
    }

    public int getPortStartup() {
        return this.portStartup;
    }

    public void setPortStartup(final int portStartup) {
        this.portStartup = portStartup;
    }

    public Properties getProperties() {
        return this.properties;
    }

    public void destroy() {

        try {
            final boolean stopSent = stop();

            final Process p = server.get();
            if (p != null) {

                if (stopSent) {
                    waitFor(p);
                } else {
                    p.destroy();
                }
            }
        } catch (final Exception e) {
            Logger.getLogger(RemoteServer.class.getName()).log(Level.WARNING, "Failed to destroy remote server process", e);
        }
    }

    public void start() {
        start(Collections.<String>emptyList(), START, true);
    }

    public void start(final List<String> additionalArgs, final String cmd, final boolean checkPortAvailable) {
        cmd(additionalArgs, cmd, checkPortAvailable);
    }

    private void cmd(final List<String> additionalArgs, final String cmd, final boolean checkPortAvailable) {
        boolean ok = true;
        final int port = START.equals(cmd) ? portStartup : portShutdown;

        if (checkPortAvailable) {
            ok = !connect(port, 1);
        }

        if (ok) {
            try {
                if (verbose) {
                    System.out.println("[] " + cmd.toUpperCase() + " SERVER");
                }

                final File home = getHome();
                final String javaVersion = System.getProperty("java.version");
                if (verbose) {
                    System.out.println("OPENEJB_HOME = " + home.getAbsolutePath());
                    final String systemInfo = "Java " + javaVersion + "; " + System.getProperty("os.name") + "/" + System.getProperty("os.version");
                    System.out.println("SYSTEM_INFO  = " + systemInfo);
                }

                serverHasAlreadyBeenStarted = false;

                final File lib = new File(home, "lib");
                final File webapplib = new File(new File(new File(home, "webapps"), "tomee"), "lib");

                File javaagentJar = null;
                try {
                    javaagentJar = lib("openejb-javaagent", lib, webapplib);
                } catch (final IllegalStateException ise) {
                    // no-op
                }

                final File conf = new File(home, "conf");
                final File loggingProperties = new File(conf, "logging.properties");

                //File openejbJar = new File(lib, "openejb-core-" + version + ".jar");

                final String java;
                final boolean isWindows = System.getProperty("os.name", "unknown").toLowerCase().startsWith("windows");
                if (isWindows && START.equals(cmd) && options.get("server.windows.fork", false)) {
                    // run and forget
                    java = new File(System.getProperty("java.home"), "bin/javaw").getAbsolutePath();
                } else {
                    java = new File(System.getProperty("java.home"), "bin/java").getAbsolutePath();
                }

                final List<String> argsList = new ArrayList<String>(20);
                argsList.add(java);
                argsList.add("-XX:+HeapDumpOnOutOfMemoryError");

                if (debug) {
                    argsList.add("-Xdebug");
                    argsList.add("-Xnoagent");
                    argsList.add("-Djava.compiler=NONE");
                    argsList.add("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=" + options.get(SERVER_DEBUG_PORT, 5005));
                }

                if (profile) {
                    String yourkitHome = options.get("yourkit.home", "/Applications/YourKit_Java_Profiler_9.5.6.app/bin/mac/");
                    if (!yourkitHome.endsWith("/")) {
                        yourkitHome += "/";
                    }
                    final String yourkitOpts = options.get("yourkit.opts", "disablestacktelemetry,disableexceptiontelemetry,builtinprobes=none,delay=10000,sessionname=Tomcat");
                    argsList.add("-agentpath:" + yourkitHome + "libyjpagent.jnilib=" + yourkitOpts);
                }

                if (javaOpts != null) {
                    Collections.addAll(argsList, javaOpts.split(" +"));
                }

                final Map<String, String> addedArgs = new HashMap<String, String>();
                if (additionalArgs != null) {
                    for (final String arg : additionalArgs) {
                        final String[] values = arg.split("=");
                        if (values.length == 1) {
                            addedArgs.put(values[0], "null");
                        } else {
                            addedArgs.put(values[0], values[1]);
                        }
                        argsList.add(arg);
                    }
                }

                if (!addedArgs.containsKey("-Djava.util.logging.config.file") && loggingProperties.exists()) {
                    argsList.add("-Djava.util.logging.config.file=" + loggingProperties.getAbsolutePath());
                }

                if (javaagentJar != null && javaagentJar.exists()) {
                    argsList.add("-javaagent:" + javaagentJar.getAbsolutePath());
                }

                //DMB: If you don't use an array, you get problems with jar paths containing spaces
                // the command won't parse correctly
                final String ps = File.pathSeparator;

                final String[] args;
                if (!tomcat) {
                    final File openejbJar = lib("openejb-core", lib, webapplib);
                    final StringBuilder cp = new StringBuilder(openejbJar.getAbsolutePath());
                    if (additionalClasspath != null) {
                        cp.append(ps).append(additionalClasspath);
                    }

                    argsList.add("-cp");
                    argsList.add(cp.toString());
                    argsList.add("org.apache.openejb.cli.Bootstrap");
                } else {
                    final File bin = new File(home, "bin");
                    final File tlib = new File(home, "lib");
                    final File bootstrapJar = new File(bin, "bootstrap.jar");
                    final File juliJar = new File(bin, "tomcat-juli.jar");
                    final File commonsLoggingJar = new File(bin, "commons-logging-api.jar");

                    final File endorsed = new File(home, "endorsed");
                    final File temp = new File(home, "temp");

//                    if (!addedArgs.containsKey("-Dcom.sun.management.jmxremote")) {
//                        argsList.add("-Dcom.sun.management.jmxremote");
//                    }
                    if (!addedArgs.containsKey("-Djava.util.logging.manager")) {
                        argsList.add("-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager");
                    }
                    if (!addedArgs.containsKey("-Djava.io.tmpdir")) {
                        argsList.add("-Djava.io.tmpdir=" + temp.getAbsolutePath());
                    }
                    if (!addedArgs.containsKey("-Djava.endorsed.dirs")) {
                        argsList.add("-Djava.endorsed.dirs=" + endorsed.getAbsolutePath());
                    }
                    if (!addedArgs.containsKey("-Dcatalina.base")) {
                        argsList.add("-Dcatalina.base=" + home.getAbsolutePath());
                    }
                    if (!addedArgs.containsKey("-Dcatalina.home")) {
                        argsList.add("-Dcatalina.home=" + home.getAbsolutePath());
                    }
                    if (!addedArgs.containsKey("-Dcatalina.ext.dirs")) {
                        argsList.add("-Dcatalina.ext.dirs=" + tlib.getAbsolutePath());
                    }
                    if (!addedArgs.containsKey("-Dorg.apache.catalina.STRICT_SERVLET_COMPLIANCE")) {
                        argsList.add("-Dorg.apache.catalina.STRICT_SERVLET_COMPLIANCE=true");
                    }
                    if (!addedArgs.containsKey("-Dorg.apache.tomcat.util.http.ServerCookie.ALLOW_HTTP_SEPARATORS_IN_V0")) {
                        argsList.add("-Dorg.apache.tomcat.util.http.ServerCookie.ALLOW_HTTP_SEPARATORS_IN_V0=true");
                    }

                    if (addedArgs.isEmpty()) { // default case
                        addIfSet(argsList, "javax.net.ssl.keyStore");
                        addIfSet(argsList, "javax.net.ssl.keyStorePassword");
                        addIfSet(argsList, "javax.net.ssl.trustStore");
                        addIfSet(argsList, "java.protocol.handler.pkgs");
                    }

                    argsList.add("-ea");
                    argsList.add("-classpath");

                    final StringBuilder cp = new StringBuilder(bootstrapJar.getAbsolutePath()).append(ps).append(juliJar.getAbsolutePath());
                    if (commonsLoggingJar.exists()) {
                        cp.append(ps).append(commonsLoggingJar.getAbsolutePath());
                    }
                    if (additionalClasspath != null) {
                        cp.append(ps).append(additionalClasspath);
                    }
                    argsList.add(cp.toString());

                    argsList.add("org.apache.catalina.startup.Bootstrap");
                }

                if (cmd == null) {
                    argsList.add(START);
                } else {
                    argsList.add(cmd);
                }
                args = argsList.toArray(new String[argsList.size()]);

                if (verbose) {
                    System.out.println(Join.join("\n", args));
                }

                // kill3UNIXDebug();
                final ProcessBuilder pb = new ProcessBuilder(args);
                pb.directory(home.getAbsoluteFile());
                Process p = pb.start();

                //Process p = Runtime.getRuntime().exec(args);
                Pipe.pipeOut(p); // why would we need to redirect System.in to the process, TomEE doesn't use it

                if (START.equals(cmd)) {
                    server.set(p);
                } else if (STOP.equals(cmd)) {
                    waitFor(p);
                    p = server.get();
                    if (p != null) {
                        waitFor(p);
                    }
                }

                System.out.println("Started server process on port: " + port);

            } catch (final Exception e) {
                throw (RuntimeException) new OpenEJBRuntimeException("Cannot start the server.  Exception: " + e.getClass().getName() + ": " + e.getMessage()).initCause(e);
            }

            if (debug) {
                if (!connect(port, Integer.MAX_VALUE)) {
                    throw new OpenEJBRuntimeException("Could not connect to server: " + this.host + ":" + port);
                }
            } else {
                if (!connect(port, tries)) {
                    throw new OpenEJBRuntimeException("Could not connect to server: " + this.host + ":" + port);
                }
            }

        } else {
            if (verbose) {
                System.out.println("[] FOUND STARTED SERVER");
            }
        }
    }

    private void waitFor(final Process p) {
        final CountDownLatch latch = new CountDownLatch(1);
        final Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    p.waitFor();
                } catch (final InterruptedException e) {
                    //Ignore
                }

                latch.countDown();
            }
        }, "process-waitFor");

        t.start();

        try {
            if (!latch.await(10, TimeUnit.SECONDS)) {
                killOnExit(p);
                throw new RuntimeException("Timeout waiting for process");
            }
        } catch (final InterruptedException e) {
            killOnExit(p);
        }
    }

    public void kill3UNIX() { // debug purpose only
        if (System.getProperty("os.name", "unknown").toLowerCase().startsWith("windows")) {
            return;
        }

        try {
            final Field f = server.get().getClass().getDeclaredField("pid");
            f.setAccessible(true);
            final int pid = (Integer) f.get(server.get());
            Pipe.pipe(Runtime.getRuntime().exec("kill -3 " + pid));
        } catch (final Exception e1) {
            e1.printStackTrace();
        }
    }

    private File lib(final String name, final File... dirs) {
        for (final File dir : dirs) {
            final File[] files = dir.listFiles();
            if (files != null) {
                for (final File file : files) {
                    if (!file.isFile()) {
                        continue;
                    }
                    if (!file.getName().endsWith(".jar")) {
                        continue;
                    }
                    if (file.getName().startsWith(name)) {
                        return file;
                    }
                }
            }
        }

        if (debug) {
            for (final File dir : dirs) {
                dumpLibs(dir);
            }
        }
        throw new IllegalStateException("Cannot find the " + name + " jar");
    }

    // for debug purpose
    private static void dumpLibs(final File dir) {
        if (!dir.exists()) {
            System.out.println("lib dir doesn't exist");
            return;
        }
        final File[] files = dir.listFiles();
        if (files != null) {
            for (final File lib : files) {
                System.out.println(lib.getAbsolutePath());
            }
        }
    }

    public Process getServer() {
        return server.get();
    }

    private void addIfSet(final List<String> argsList, final String key) {
        if (System.getProperties().containsKey(key)) {
            argsList.add("-D" + key + "=" + System.getProperty(key));
        }
    }

    private File getHome() {
        if (home != null) {
            return home;
        }

        final String openejbHome = System.getProperty("openejb.home");

        if (openejbHome != null) {
            home = new File(openejbHome);
        }
        return home;
    }

    public boolean stop() {
        if (sendShutdown(5)) {
            return true;
        } else {
            if (verbose) {
                notSent();
            }

            return false;
        }
    }

    private void notSent() {
        System.out.println("Failed to send the shutdown notification - TomEE is likely shut down already");
    }

    public void forceStop() throws Exception {
        if (sendShutdown(5)) {

            // Check TomEE was effectively shut down after getting the message
            // There can be concurrent shutdown operations (catalina shutdown hook for instance),
            // so we have to wait here since it is important to be synchronous in this method
            waitForServerShutdown();
        } else {
            if (verbose) {
                notSent();
            }
        }
    }

    private void waitForServerShutdown() throws Exception {

        if (verbose) {
            System.out.print("Waiting for TomEE shutdown.");
        }

        final boolean b = disconnect(portShutdown, tries);

        if (verbose) {
            System.out.println();
        }

        if (!b) {
            //We need to know about this
            System.out.println("SEVERE: Failed to shutdown TomEE running on port " + portStartup + " using shutdown port: " + portShutdown);
        }
    }

    /**
     * Send the shutdown message to the running server
     *
     * @param attempts How many times to try to send the message before giving up
     * @return True is the message was sent, else false if unable to connect after the defined number of attempts
     */
    private boolean sendShutdown(int attempts) {
        Socket socket = null;
        OutputStream stream = null;
        try {
            socket = new Socket(host, portShutdown);
            stream = socket.getOutputStream();
            final String shutdown = command + Character.toString((char) 0);
            for (int i = 0; i < shutdown.length(); i++) {
                stream.write(shutdown.charAt(i));
            }
            stream.flush();
        } catch (final Exception e) {
            if (attempts > 0) {
                try {
                    Thread.sleep(1000);
                } catch (final InterruptedException ie) {
                    return false;
                }
                return sendShutdown(--attempts);
            } else {
                return false;
            }
        } finally {
            if (null != stream) {
                try {
                    stream.close();
                } catch (final Exception e) {
                    // Ignore
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                } catch (final Exception e) {
                    // Ignore
                }
            }
        }

        return true;
    }

    private boolean connect(final int port, int tries) {
        if (verbose) {
            System.out.println("[] CONNECT ATTEMPT " + (this.tries - tries) + " on port: " + port);
        }

        Socket s = null;
        try {
            s = new Socket();
            s.connect(new InetSocketAddress(this.host, port), 1000);
            s.getOutputStream().close();
            if (verbose) {
                System.out.println("[] CONNECTED IN " + (this.tries - tries));
            }
        } catch (final Exception e) {
            if (tries < 2) {
                if (verbose) {
                    System.out.println("[] CONNECT ATTEMPTS FAILED ( " + (this.tries - tries) + " ATTEMPTS)");
                }
                return false;
            } else {
                try {
                    Thread.sleep(1000);
                } catch (final Exception e2) {
                    e2.printStackTrace();
                }
                return connect(port, --tries);
            }
        } finally {
            if (s != null) {
                try {
                    s.close();
                } catch (final Exception ignored) {
                    // no-op
                }
            }
        }

        return true;
    }

    private boolean disconnect(final int port, int tries) {
        if (verbose) {
            System.out.println("[] DISCONNECT ATTEMPT " + (this.tries - tries) + " on port: " + port);
        }

        Socket s = null;
        try {
            s = new Socket();
            s.connect(new InetSocketAddress(this.host, port), 500);
            s.getOutputStream().close();

            if (verbose) {
                System.out.println("[] NOT DISCONNECTED AFTER ( " + (this.tries - tries) + " ATTEMPTS)");
            }

            if (tries < 2) {
                //Give up
                return false;
            } else {
                try {
                    Thread.sleep(1000);
                } catch (final Exception e2) {
                    e2.printStackTrace();
                }

                return disconnect(port, --tries);
            }

        } catch (final IOException e) {
            //This is what we want
        } finally {
            if (s != null) {
                try {
                    s.close();
                } catch (final Exception ignored) {
                    // no-op
                }
            }
        }

        return true;
    }

    public void setAdditionalClasspath(final String additionalClasspath) {
        this.additionalClasspath = additionalClasspath;
    }

    public void killOnExit() {
        final Process p = this.server.get();
        if (!serverHasAlreadyBeenStarted && kill.contains(p)) {
            return;
        }

        killOnExit(p);
    }

    private static void killOnExit(final Process p) {
        kill.add(p);
    }

    // Shutdown hook for processes
    private static final List<Process> kill = new ArrayList<Process>();

    static {
        Runtime.getRuntime().addShutdownHook(new CleanUpThread());
    }

    public static class CleanUpThread extends Thread {
        @Override
        public void run() {
            for (final Process server : kill) {
                try {
                    if (server != null) {
                        server.destroy();
                        server.waitFor();
                    }
                } catch (final Throwable e) {
                    //Ignore
                }
            }
        }
    }
}
