package com.mygdx.game.controllers;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Net;
import com.badlogic.gdx.utils.JsonValue;
import com.mygdx.game.Battleship;
import com.mygdx.game.Constants;
import com.mygdx.game.models.*;

import java.util.Arrays;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import json.JsonHelper;
import network.NetworkHelper;

/**
 * Created by esso on 16.03.15.
 */
public class PlayerNetworkController {
    private Player player, opponent;
    private boolean playersTurn;
    private Battleship battleshipGame;

    public PlayerNetworkController(Battleship battleshipGame){
        opponent = null;
        player = null;
        playersTurn = false;
        this.battleshipGame = battleshipGame;
    }

    public Player getPlayer() {
        return player;
    }

    public void setPlayer(Player player){
        this.player = player;
    }

    public boolean isPlayersTurn() {
        return playersTurn;
    }

    public void setPlayersTurn(boolean b){playersTurn = b; }

    /**
     * waitForTurn
     * @description Checks regularly if it's this players turn or not, and if so,
     * retrieves the coordinates for the last shot from the opponent
     */
    public void waitForTurn() {
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                NetworkHelper.sendGetRequest("/turn/" + getPlayer().getUsername(), new Net.HttpResponseListener() {
                    @Override
                    public void handleHttpResponse(Net.HttpResponse httpResponse) {
                        JsonValue jsonResponse = JsonHelper.parseJson(httpResponse.getResultAsString());

                        if (jsonResponse.get("username").asString().equals(getPlayer().getUsername())) {
                            // Handle the response when the opponent fires at your board
                            String str = jsonResponse.get("lastMove").asString();
                            List<String> coordinates = Arrays.asList(str.split(","));
                            int x = Integer.valueOf(coordinates.get(0));
                            int y = Integer.valueOf(coordinates.get(1));
                            fireAtThisBoard(x, y);
                            Gdx.app.postRunnable(new Runnable() {
                                @Override
                                public void run() {battleshipGame.getGameScreen().myTurn();}
                            });
                            setPlayersTurn(true);
                            cancel();
                        } else {
                            setPlayersTurn(false);
                        }
                    }

                    @Override
                    public void failed(Throwable t) {}

                    @Override
                    public void cancelled() {}
                });
            }
        }, 0, Constants.REGULAR_REQUEST_TIME);
    }

    private void fireAtThisBoard(int x, int y) {
        // Coordinates are -1, -1 at the start of the game, when no shots have been fired.
        if (x == -1 || y == -1) {
            return;
        }
        player.getBoard().getCell(x,y).setHit(true);
        Gdx.app.postRunnable(new Runnable() {
            @Override
            public void run() {
                battleshipGame.getGameScreen().getMainBoard().setBoard(player.getBoard());
            }
        });
    }

    private void fireAtOpponentBoard(int x, int y, boolean shipHit) {
        opponent.getBoard().getCell(x,y).setHit(true);
        Gdx.app.postRunnable(new Runnable() {
            @Override
            public void run() {
                battleshipGame.getGameScreen().getOpponentBoard().setBoard(opponent.getBoard());
                battleshipGame.getGameScreen().waitForTurn();
            }
        });
    }

    /**
     * fireAtLocation
     * @param x
     * @param y
     * @description Takes coordinates and calls to the server that he has fired on that location
     */
    public void fireAtLocation(int x, int y){
        class JsonData {
            private int x, y;
            private String username;
            public void setX(int x) { this.x = x; }
            public void setY(int y) {this.y = y;}
            public int getX() {return x;}
            public int getY() {return y;}
            public void setUsername(String username) {this.username = username;}
        }

        final JsonData jsonData = new JsonData();
        jsonData.setX(x);
        jsonData.setY(y);
        jsonData.setUsername(getPlayer().getUsername());

        NetworkHelper.sendPostRequest("/fire", JsonHelper.buildJson(jsonData), new Net.HttpResponseListener() {
            @Override
            public void handleHttpResponse(Net.HttpResponse httpResponse) {
                // Res: {shipWasHit: BOOLEAN, message: "No game was found" OR "Ongoing game" OR "You lost" OR "You won"}

                JsonValue jsonResponse = JsonHelper.parseJson(httpResponse.getResultAsString());
                if (jsonResponse.get("message").equals("No game was found")){
                    // @todo What are we supposed to do with this message?
                    // nothing for know
                } else if (jsonResponse.get("message").equals("Ongoing game")){
                    if (jsonResponse.get("shipWasHit").asBoolean() == true) {
                        fireAtOpponentBoard(jsonData.getX(), jsonData.getY(), true);
                    } else if (jsonResponse.get("shipWasHit").asBoolean() == false){
                        fireAtOpponentBoard(jsonData.getX(), jsonData.getY(), false);
                    }
                } else if (jsonResponse.get("message").equals("You lost")) {
                    Gdx.app.postRunnable(new Runnable() {
                        @Override
                        public void run() {
                            battleshipGame.setGameOver(false);
                        }
                    });
                } else if (jsonResponse.get("message").equals("You won")) {
                    fireAtOpponentBoard(jsonData.getX(), jsonData.getY(), true);
                    Gdx.app.postRunnable(new Runnable() {
                        @Override
                        public void run() {
                            battleshipGame.setGameOver(true);
                        }
                    });
                }
            }

            @Override
            public void failed(Throwable t) {}

            @Override
            public void cancelled() {}
        });
    }

    public Player getOpponent() {
        return opponent;
    }

    public void setOpponent(Player opponent) {
        if (this.opponent  == null){
            this.opponent = opponent;
        }
    }
}

@@ -5311,32 +5311,43 @@
 .get(%22message%22).
+asString().
 equals(%22Ongoing 
@@ -5758,32 +5758,43 @@
 .get(%22message%22).
+asString().
 equals(%22You lost
@@ -6095,32 +6095,43 @@
 .get(%22message%22).
+asString().
 equals(%22You won%22

Parse response as string