package com.server;

import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.*;
import org.jboss.netty.handler.codec.http.*;
import org.jboss.netty.handler.codec.http.websocketx.*;
import org.jboss.netty.util.CharsetUtil;
import org.json.JSONObject;

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

/**
 * Created by alec.ferguson on 4/20/2017.
 */
public class ServerHandler extends SimpleChannelUpstreamHandler {
    static Map<String, Client> connectedClients = new HashMap<>();
    private static final String PATH = "/ws";
    private static final String USERS = "/users";
    private static final String KEY_HEADER = "X-CLIENT-KEY";
    private static final String USER_HEADER = "X-USER";

    @Override
    public void messageReceived(ChannelHandlerContext context,
                                MessageEvent evt)
    {
        Object message = evt.getMessage();
        if (message instanceof WebSocketFrame)
        {
            handleWebsocketFrame(context, (WebSocketFrame) message);
        } else if (message instanceof HttpRequest)
        {
            handleHttpRequest(context, (HttpRequest) message);
        }
    }

    private void handleWebsocketFrame(ChannelHandlerContext context,
                                      WebSocketFrame frame)
    {
        if (frame instanceof TextWebSocketFrame)
        {
            // Parse json frame
            JSONObject object = new JSONObject(frame.toString());
            String to = object.getString("to");

            // Get the target channel
            Client receiver = connectedClients.get(to);
            // Write the message to the receiver's channel
            if (receiver != null)
            {
                receiver.getChannel().write(frame);
            }
        } else if (frame instanceof CloseWebSocketFrame)
        {
            // Remove client from table
            for (Map.Entry<String, Client> entry :
                    connectedClients.entrySet()) {
                String username = entry.getKey();
                if (entry.getValue().getChannel() ==
                        context.getChannel()){
                    connectedClients.remove(username);
                    System.out.println("User " + username + "disconnected!");
                }
            }
        }
    }

    private void handleHttpRequest(ChannelHandlerContext context,
                                   HttpRequest request)
    {
        final Channel channel = context.getChannel();
        boolean success = false;

        // Handle websocket connection request.
        if (request.getUri().equals(PATH))
        {
            String username = request.getHeader(USER_HEADER);
            String key = request.getHeader(KEY_HEADER);
            ChannelFuture handshake;

            // Close connection if user did not send expected headers
            if (username != null && key != null) {
                // Build upgrade response
                WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
                        request.getUri(),
                        null,
                        false);
                final WebSocketServerHandshaker handshaker = wsFactory.newHandshaker(request);

                // Wait for handshake
                handshake = handshaker.handshake(channel, request);
                handshake.awaitUninterruptibly(5);

                if (handshake.isDone()) {
                    System.out.println(
                            "Client connected with name <" + username +
                                    "> and key <" + key + ">");
                    connectedClients.put(username,
                            new Client(username, key, channel));
                }
                success = true;
            }
        } else if (request.getUri().equals(USERS))
        {
            // Display all connected users
            JSONObject json = new JSONObject();
            // Iterate over usermap and get all public keys
            for (Map.Entry<String, Client> entry :
                    connectedClients.entrySet()) {
                json.put(entry.getKey(), entry.getValue().getPublicKey());
            }
            // Build response object
            HttpResponse response = new DefaultHttpResponse(
                    HttpVersion.HTTP_1_1,
                    HttpResponseStatus.OK);
            // Set body to json object
            response.setContent(
                    ChannelBuffers.copiedBuffer(json.toString(), CharsetUtil.UTF_8));
            // Send response
            httpResponse(context,
                    response,
                    request);
            success = true;
        }
        // Error response on fail
        if (!success) {
            httpResponse(context,
                    new DefaultHttpResponse(
                        HttpVersion.HTTP_1_1,
                        HttpResponseStatus.BAD_REQUEST),
                    request);
            return;
        }
    }

    public void httpResponse(ChannelHandlerContext context,
                             HttpResponse response,
                             HttpRequest request)
    {
        Channel channel = context.getChannel();
        ChannelFuture future;
        // Write response to channel
        future = channel.write(response);
        // Close channel on non-200
        if (response.getStatus().getCode() != 200){
            future.addListener(ChannelFutureListener.CLOSE);
        }
    }
}

@@ -2488,41 +2488,8 @@
 l();
-%0A        boolean success = false;
 %0A%0A  
@@ -3727,38 +3727,30 @@
             
-success = true
+return
 ;%0A          
@@ -4637,22 +4637,14 @@
     
-success = true
+return
 ;%0A  
@@ -4689,36 +4689,8 @@
 ail%0A
-        if (!success) %7B%0A    
     
@@ -4727,28 +4727,24 @@
             
-    
 new DefaultH
@@ -4768,36 +4768,32 @@
                 
-    
 HttpVersion.HTTP
@@ -4810,36 +4810,32 @@
                 
- 
-   
 HttpResponseStat
@@ -4859,36 +4859,32 @@
                 
-    
 request);%0A      
@@ -4881,38 +4881,8 @@
 t);%0A
-            return;%0A        %7D%0A
     
@@ -5213,100 +5213,8 @@
 e);%0A
-        // Close channel on non-200%0A        if (response.getStatus().getCode() != 200)%7B%0A    
     
@@ -5266,26 +5266,16 @@
 CLOSE);%0A
-        %7D%0A
     %7D%0A%7D%0A

Fix issue with users endpoint not returning