package com.ocdsoft.bacta.swg.cu.connection;

import com.google.inject.Inject;
import com.ocdsoft.bacta.engine.conf.BactaConfiguration;
import com.ocdsoft.bacta.engine.network.client.ConnectionState;
import com.ocdsoft.bacta.soe.client.ClientConnection;
import com.ocdsoft.bacta.soe.connection.ConnectionServerAgent;
import com.ocdsoft.bacta.soe.io.udp.game.GameServerState;
import com.ocdsoft.bacta.soe.service.SessionKeyService;
import com.ocdsoft.bacta.swg.cu.message.game.server.GameServerStatus;
import com.ocdsoft.bacta.swg.cu.object.login.ClusterEntry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Singleton;
import java.net.InetSocketAddress;

/**
 * Created by kburkhardt on 1/26/15.
 */

@Singleton
public class CuConnectionServerAgent implements ConnectionServerAgent {

    private static final Logger logger = LoggerFactory.getLogger(CuConnectionServerAgent.class);

    private final GameServerState<ClusterEntry> serverState;
    private final ClientConnection clientConnection;

    private final SessionKeyService sessionKeyService;

    private final Thread agentThread;

    @Inject
    public CuConnectionServerAgent(final SessionKeyService sessionKeyService,
                                   final GameServerState<ClusterEntry> serverState,
                                   final ClientConnection clientConnection,
                                   final BactaConfiguration configuration) {
        this.sessionKeyService = sessionKeyService;
        this.serverState = serverState;
        this.clientConnection = clientConnection;

        agentThread = new Thread(clientConnection);

        String address = configuration.getStringWithDefault("Bacta/LoginServer", "BindIp", "127.0.0.1");
        int port = configuration.getIntWithDefault("Bacta/LoginServer", "Port", 44463);

        this.clientConnection.setRemoteAddress(new InetSocketAddress(address, port));
        this.clientConnection.setConnectCallback(this::onConnect);
    }

    @Override
    public void run() {

        agentThread.start();

        try {
            while (true) {

                // 30 Seconds between status updates
                Thread.sleep(1000 * 30);
                update();
            }

        } catch(InterruptedException e) {
            logger.warn("Updater thread interrupted", e);
        }
    }

    @Override
    public void update() {

        clientConnection.connect(sessionKeyService.getNextKey());

    }

    private Void onConnect(Void aVoid) {

        GameServerStatus gameServerStatus = new GameServerStatus(serverState);
        clientConnection.sendMessage(gameServerStatus);

        clientConnection.setState(ConnectionState.DISCONNECTED);

        return null;
    }


}

@@ -72,16 +72,51 @@
 Inject;%0A
+import com.google.inject.Injector;%0A
 import c
@@ -399,24 +399,78 @@
 erverState;%0A
+import com.ocdsoft.bacta.soe.router.SoeMessageRouter;%0A
 import com.o
@@ -1254,24 +1254,84 @@
 Agent(final 
+Injector injector,%0A                                   final 
 SessionKeySe
@@ -1443,84 +1443,8 @@
 te,%0A
-                                   final ClientConnection clientConnection,%0A
     
@@ -1512,24 +1512,33 @@
 guration) %7B%0A
+        %0A
         this
@@ -1617,24 +1617,25 @@
 rState;%0A
+%0A
         
 this.cli
@@ -1630,104 +1630,558 @@
     
-this.clientConnection = clientConnection;%0A%0A        agentThread = new Thread(clientConnection
+final SoeMessageRouter soeMessageRouter = new SoeMessageRouter(%0A                injector,%0A                configuration.getStringWithDefault(%22Bacta/GameServer/Client%22, %22SoeControllerList%22, %22clientsoecontrollers.lst%22),%0A                configuration.getStringWithDefault(%22Bacta/GameServer/Client%22, %22SwgControllerList%22, %22clientswgcontrollers.lst%22)%0A        );%0A%0A        int udpSize = configuration.getIntWithDefault(%22Bacta/Network%22, %22UdpMaxSize%22, 496);%0A        int protocolVersion = configuration.getIntWithDefault(%22Bacta/Network%22, %22ProtocolVersion%22, 2
 );%0A
-%0A
     
@@ -2368,16 +2368,123 @@
  44463);
+%0A        %0A        this.clientConnection = new ClientConnection(soeMessageRouter, udpSize, protocolVersion);
 %0A%0A      
@@ -2629,16 +2629,69 @@
 onnect);
+%0A%0A        agentThread = new Thread(clientConnection);
 %0A    %7D%0A%0A

Update client