package com.apixandru.games.rummikub.server;

import com.apixandru.games.rummikub.api.CompoundCallback;
import com.apixandru.games.rummikub.api.Player;
import com.apixandru.games.rummikub.brotocol.SocketWrapper;
import com.apixandru.games.rummikub.model.Rummikub;
import com.apixandru.games.rummikub.model.RummikubFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Alexandru-Constantin Bledea
 * @since March 31, 2016
 */
public class ConnectionHandler {

    private static final Logger log = LoggerFactory.getLogger(RummikubServer.class);

    private final Rummikub<Integer> game = RummikubFactory.newInstance();

    private final Map<String, SocketWrapper> activeConnections = new HashMap<>();

    public synchronized void attemptToJoin(final SocketWrapper wrapper) throws IOException {
        final String playerName = wrapper.readString();
        log.info("{} is attempting to join.", playerName);
        if (accept(wrapper, playerName)) {
            activeConnections.put(playerName, wrapper);
            log.info("Accepted {}", playerName);

            log.debug("Registering {}...", playerName);
            final CompoundCallback<Integer> callback = new ClientCallback(playerName, wrapper);

            final Player<Integer> player = game.addPlayer(playerName, callback);
            log.debug("{} registered.", playerName);
            final ClientRunnable runnable = new ClientRunnable(wrapper, player, game);
            new Thread(runnable, playerName).start();
        }
    }

    private boolean accept(final SocketWrapper wrapper, final String playerName) {
        if (!activeConnections.containsKey(playerName)) {
            wrapper.write(true);
            return true;
        }
        wrapper.write(false);
        wrapper.write("Username is already taken.");
        log.info("Rejected {} because there's already a {}.", playerName, playerName);
        return false;
    }

}

@@ -962,20 +962,21 @@
     log.
-info
+debug
 (%22%7B%7D is 
@@ -1026,24 +1026,22 @@
 if (
-accept(wrapper, 
+usernameTaken(
 play
@@ -1067,86 +1067,107 @@
     
-activeConnections.put(playerName, wrapper);%0A            log.info(%22Accepted %7B%7D%22
+reject(wrapper, %22Username is already taken.%22);%0A            return;%0A        %7D%0A        accept(wrapper
 , pl
@@ -1178,36 +1178,32 @@
 Name);%0A%0A        
-    
 log.debug(%22Regis
@@ -1222,36 +1222,32 @@
 %22, playerName);%0A
-    
         final Co
@@ -1319,28 +1319,24 @@
  wrapper);%0A%0A
-    
         fina
@@ -1404,28 +1404,24 @@
 k);%0A        
-    
 log.debug(%22%7B
@@ -1445,28 +1445,24 @@
 layerName);%0A
-    
         fina
@@ -1540,20 +1540,16 @@
         
-    
 new Thre
@@ -1582,26 +1582,16 @@
 tart();%0A
-        %7D%0A
     %7D%0A%0A 
@@ -1613,44 +1613,22 @@
 ean 
-accept(final SocketWrapper wrapper, 
+usernameTaken(
 fina
@@ -1662,13 +1662,15 @@
     
-if (!
+return 
 acti
@@ -1710,79 +1710,93 @@
 ame)
-) %7B
+;
 %0A    
- 
+%7D%0A%0A
     
-   wrapper.write(true);%0A            return true;%0A        %7D
+private void reject(final SocketWrapper socketWrapper, String message) %7B
 %0A   
@@ -1792,33 +1792,39 @@
 sage) %7B%0A        
-w
+socketW
 rapper.write(fal
@@ -1836,17 +1836,23 @@
         
-w
+socketW
 rapper.w
@@ -1860,36 +1860,15 @@
 ite(
-%22Username is already taken.%22
+message
 );%0A 
@@ -1882,12 +1882,13 @@
 log.
-info
+debug
 (%22Re
@@ -1897,56 +1897,159 @@
 cted
- %7B%7D because there's already a %7B%7D.%22, playerName, 
+.%22);%0A    %7D%0A%0A    private void accept(final SocketWrapper wrapper, final String playerName) %7B%0A        wrapper.write(true);%0A        activeConnections.put(
 play
@@ -2046,32 +2046,41 @@
 s.put(playerName
+, wrapper
 );%0A        retur
@@ -2078,20 +2078,30 @@
     
-return false
+log.debug(%22Accepted.%22)
 ;%0A  
@@ -2105,10 +2105,11 @@
 %0A    %7D%0A%0A
+%0A
 %7D%0A

refactor methods