package edu.utexas.ee360p_teamproject.ClientRequestHandler;

import android.util.Log;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import static edu.utexas.ee360p_teamproject.ClientRequestHandler.TCPConnection.ConnectionStatus.*;


/**
 * Created by aria on 4/21/17.
 */

class TCPConnection {
    private static final String TAG = "TCPConnection";
    private static int port   = 8080;
    private final static String ip  = "10.0.2.2";
    private String command, tag;
    private boolean isReady;
    private List<String> resposne;

    enum ConnectionStatus{
        CONNECTING,
        ERROR,
        DONE,
        SENDING,
        SENT
    }

    TCPConnection(String tag, String command) {
        this.tag = tag;
        this.command  = command;
        this.isReady = false;
    }

    public List<String> responseIfAvailable(){
        while (!isReady) {}

        return resposne;
    }

    void run() {
        log(CONNECTING);

        List<String> serverResponse = new ArrayList<>();
        ClientSocket clientSocket;

        try {
            log(SENDING);

            clientSocket = new ClientSocket(ip, port);
            switch (tag) {
                case ClientTask.INIT:
                    Log.d(TAG, "Initializing...");
                    serverResponse = initializeServer(clientSocket);
                    break;
                case ClientTask.ROOM:
                    Log.d(TAG, "Selecting room: " + command);
                    selectChatroom(clientSocket);
                    Log.d(TAG, "Changed port to " + port);
                    log(SENT);
                    break;
                case ClientTask.SEND:
                    if (port==8080) {
                        Log.e(TAG, "have not entered a chatroom yet");
                        return;
                    }

                    Log.d(TAG, "Sending new message: " + command);
                    sendMessage(command,
                                clientSocket.outStream());
                    Log.d(TAG, "message was sent");
                    break;
                case ClientTask.UPDATE:
                    if (port==8080) {
                        Log.e(TAG, "have not entered a chatroom yet");
                        return;
                    }

                    Log.d(TAG, "checking for notifications, current count: " + command);
                    serverResponse = getNotifications(clientSocket);

                    if (serverResponse!=null && !serverResponse.isEmpty())
                        Log.d(TAG, serverResponse.get(0) + "new notifications received");
                    break;
            }
            log(DONE);
        }
        catch (Exception e) {
            log(ERROR);
            e.printStackTrace();

        } finally {
            Log.d(TAG, "Socket Closed");
        }

        resposne = serverResponse;
        isReady = true;
    }

    private List<String> initializeServer(ClientSocket clientSocket) throws IOException {
        List<String> serverResponse = new ArrayList<>();

        Log.d(TAG, "Getting count of avail rooms...");
        String response = clientSocket.inStream()
                                      .readLine();

        int roomCount = Integer.parseInt(response);

        Log.d(TAG, "there are " + roomCount + " rooms available");

        for (int i = 0; i < roomCount; i++) {
            Log.d(TAG, "Getting name of room #" + (i+1));

            serverResponse.add(clientSocket.inStream()
                                           .readLine());
        }

        return serverResponse;
    }

    private void selectChatroom(ClientSocket clientSocket) throws IOException {
        sendMessage(command,
                    clientSocket.outStream());

        //Update port to desired chat-room
        port = Integer.parseInt(clientSocket.inStream()
                                            .readLine());
    }

    private void sendMessage(String message, PrintWriter socket_out) {
        if (socket_out == null || socket_out.checkError())
            return;

        socket_out.println(message);
        socket_out.flush();
        log(SENDING);
        Log.d(TAG, "Sent Message: " + message);
    }

    private List<String> getNotifications(ClientSocket clientSocket) throws IOException {
        List<String> serverResponse = new ArrayList<>();

        sendMessage(command, clientSocket.outStream());
        sendMessage("GetALL", clientSocket.outStream());

        String response = clientSocket.inStream()
                                      .readLine();

        serverResponse.add(response);
        int newPostsCount = Integer.parseInt(response);

        for (int i = 0; i < newPostsCount; i++) {
            String timeStamp = clientSocket.inStream()
                                           .readLine();
            String author    = clientSocket.inStream()
                                           .readLine();
            String msg       = clientSocket.inStream()
                                           .readLine();
            serverResponse.add(timeStamp);
            serverResponse.add(author);
            serverResponse.add(msg);
        }

        return serverResponse;
    }

    private void log(ConnectionStatus tag){
        switch (tag) {
            case CONNECTING: Log.d(TAG, "Connecting..."); break;
            case SENDING:    Log.d(TAG, "Sending...");    break;
            case SENT:       Log.d(TAG, "Sent...");       break;
            case DONE:       Log.d(TAG, "Done...");       break;
            case ERROR:      Log.d(TAG, "Error...");      break;
            default:         Log.d(TAG, "Default value... ERROR");
        }
    }
}

@@ -406,16 +406,61 @@
 ction%22;%0A
+    private static ClientSocket coordinator;%0A
     priv
@@ -489,16 +489,16 @@
 = 8080;%0A
-
     priv
@@ -592,23 +592,25 @@
 boolean 
-isR
+r
 eady
+Flag
 ;%0A    pr
@@ -870,23 +870,25 @@
    this.
-isR
+r
 eady
+Flag
  = false
@@ -900,116 +900,8 @@
  %7D%0A%0A
-    public List%3CString%3E responseIfAvailable()%7B%0A        while (!isReady) %7B%7D%0A%0A        return resposne;%0A    %7D%0A%0A
     
@@ -1099,16 +1099,115 @@
 Socket =
+ tag.equals(ClientTask.ROOM) ? coordinator%0A                                                       :
  new Cli
@@ -1404,32 +1404,80 @@
 (clientSocket);%0A
+                    coordinator = clientSocket;%0A
                 
@@ -1727,16 +1727,93 @@
 (SENT);%0A
+                    // TODO: 4/23/17 kill coordinator connection connection?%0A
         
@@ -2985,24 +2985,78 @@
 %7D finally %7B%0A
+            // TODO: 4/23/17 should socket be closed?%0A
             
@@ -3142,21 +3142,405 @@
     
-isReady = tru
+setReadyFlag();%0A    %7D%0A%0A    public List%3CString%3E responseIfAvailable()%7B%0A        while (!isResultReady()) %7B%7D%0A%0A        unsetReadyFlag();%0A        return resposne;%0A    %7D%0A%0A    private synchronized boolean isResultReady()%7B%0A        return readyFlag;%0A    %7D%0A%0A    private synchronized void setReadyFlag()%7B%0A        readyFlag =true;%0A    %7D%0A%0A    private synchronized void unsetReadyFlag()%7B%0A        readyFlag =fals
 e;%0A 

fix bug where room selection was being done with a different coordinator on the server, leaving the original coordinator hanging