package net.zoldar.ldap.testserver;

import org.apache.commons.cli.*;
import com.github.trevershick.test.ldap.LdapServerResource;
import com.github.trevershick.test.ldap.annotations.LdapConfiguration;
import py4j.GatewayServer;

import java.util.HashMap;
import java.util.Map;

public class Server {
    private static GatewayServer gateway;

    private Map<Integer, LdapServerResource> servers = new HashMap<Integer, LdapServerResource>();

    public static void main(String[] args) throws Exception {

        Options options = new Options();

        Option port = new Option("p", "port", true, "GatewayServer port");
        options.addOption(port);

        CommandLineParser parser = new DefaultParser();
        HelpFormatter formatter = new HelpFormatter();
        CommandLine cmd;

        try {
            cmd = parser.parse(options, args);
        } catch (ParseException e) {
            System.out.println(e.getMessage());
            formatter.printHelp("ldap-test-server", options);

            System.exit(1);
            return;
        }

        int gatewayPort = GatewayServer.DEFAULT_PORT;
        if (cmd.hasOption("port")) {
          String gatewayPortStr = cmd.getOptionValue("port");
          gatewayPort = Integer.parseInt(gatewayPortStr);
        }
        gateway = new GatewayServer(new Server(), gatewayPort);
        gateway.start();
        System.out.println("Gateway server started on port "+gateway.getPort()+"!");
    }

    private Server() {}

    public int create(LdapConfiguration config) throws Exception {
        int port = config.port();

        if (servers.containsKey(port)) {
            if (servers.get(port).isStarted()) {
                throw new IllegalStateException("LDAP server already running on port " + port);
            }
        }

        LdapServerResource newServer = new LdapServerResourceCreator(config).getResource();
        servers.put(port, newServer);
        return port;
    }

    public void destroy() {
        for (int serverId : servers.keySet()) {
            destroy(serverId);
        }
    }

    public void destroy(int serverId) {
        if (servers.containsKey(serverId)) {
            servers.get(serverId).stop();
        }

        servers.remove(serverId);
    }

    public void start() throws Exception {
        for (int serverId : servers.keySet()) {
            if (!servers.get(serverId).isStarted()) {
                servers.get(serverId).start();
            }
        }
    }

    public void start(int serverId) throws Exception {
        if (!servers.get(serverId).isStarted()) {
            servers.get(serverId).start();
        }
    }

    public void stop() {
        for (int serverId : servers.keySet()) {
            servers.get(serverId).stop();
        }
    }

    public void stop(int serverId) {
        if (servers.containsKey(serverId)) {
            servers.get(serverId).stop();
        }
    }

    /* functions provided for backwards compatability */
    public void start(LdapConfiguration config) throws Exception {
        LdapServerResource newServer = new LdapServerResourceCreator(config).getResource();
        newServer.start();

        // destroy any existing servers running
        destroy();

        servers.put(newServer.port(), newServer);
    }

    public int port() {
        return servers.values().iterator().next().port();
    }
}

@@ -293,16 +293,71 @@
 erver %7B%0A
+    private static final String PORT_OPTION = %22port%22;%0A%0A
     priv
@@ -634,22 +634,27 @@
 on(%22p%22, 
-%22port%22
+PORT_OPTION
 , true, 
@@ -1195,22 +1195,27 @@
 sOption(
-%22port%22
+PORT_OPTION
 )) %7B%0A   
@@ -1264,22 +1264,27 @@
 onValue(
-%22port%22
+PORT_OPTION
 );%0A     

Move port option string under static class variable