$(function() {
    var connection = null;
    var nick = null;
    var self_player = null;

    
    // when creating a word
    var question = null;
    var char_list = null;


    // when guessing results
    var wordlist = null;
    var questionlist = null;


    function validate_word(word) {
        var allowedChars = [" ", "-", "'"];
        var countmap = {};
        for (var i = 0; i < char_list.length; i++) {
            var upper = char_list[i].toUpperCase();
            if (countmap[upper] == null) {
                countmap[upper] = 0;
            }
            countmap[upper] += 1;
        }

        var uppercase_word = word.toUpperCase();
        for (var i = 0; i < uppercase_word.length; i++) {
            var upper = uppercase_word.charAt(i);
            var count = countmap[upper];
            if (allowedChars.includes(upper))
                continue;
            if (count != null) {
                if (count <= 0) {
                    return false;
                }
                countmap[upper] = count - 1;
            }
            else {
                return false;
            }
        }
        return word.length > 0;
    }

    $('#join').click(function() {
        var game_id = $('#gameId').val();
        nick = $('#nick').val();
        var msg = {
            join: {
                game_id: game_id,
                nick: nick,
            }
        };

        send(msg);
    });

    $('#create').click(function() {
        var game_id = $('#gameId').val();
        nick = $('#nick').val();
        var msg = {
            create_game: {
                game_id: game_id,
                nick: nick,
            }
        };

        send(msg);
    });

    $('#leave-lobby').click(function() {
        if (window.confirm("Are you sure you want to leave?")) {
            var msg = "leave_lobby";
            send(msg);
        }
    });

    $('#ready-button').click(function() {
        var msg = "ready";
        if (self_player != null && self_player.ready) {
            msg = "unready";
        }
        send(msg);
    });

    $('#createform').submit(function(ev) {
        ev.preventDefault();
        var word = $('#word').val();
        if (validate_word(word)) {
            var msg = {
                submit_word: {
                    word: word
                }
            };
            send(msg);
        }
        else {
            statusMessage("Please use only given characters");
        }
    });

    $('#guessingform').submit(function(ev) {
        ev.preventDefault();
        var list = getDragAnswers();
        var msg = {
            submit_guess: {
                guesses: list
            }
        };
        send(msg);
    });
    $(document).on("click", "#reveal-button", function() {
        var msg = "reveal";
        send(msg);
    });

    function connect(initial_message) {
        if (connection != null) {
            disconnect();
        }

        var prot = document.location.protocol == 'https:' ? 'wss://' : 'ws://';

        var uri = prot + window.location.host + '/ws/';
        connection = new WebSocket(uri);

        connection.onopen = function() {
            connection.send(JSON.stringify(initial_message));
        };
        connection.onmessage = function(e) {
            onReceive(e);
        };
        connection.onclose = function() {
            connection = null;
        };
    }

    function send(message) {
        if (connection != null) {
            connection.send(JSON.stringify(message));
        }
        else {
            connect(message);
        }
    }

    function disconnect() {
        connection.close();
        connection = null;
    }

    function onReceive(msg) {
        var obj = JSON.parse(msg.data);
        if (obj.game_not_found != null) {
            statusMessage("Game \"" + obj.game_not_found.game_id + "\" not found");
        }
        else if (obj.game_already_started != null) {
            statusMessage("Game \"" + obj.game_already_started.game_id + "\" has already started.");
        }
        else if (obj.game_already_exists != null) {
            statusMessage("Game \"" + obj.game_already_exists.game_id + "\" already exists.");
        }
        else if (obj.nick_already_exists != null) {
            statusMessage("There is already a player called \"" + obj.nick_already_exists.nick +
                          "\" in this game lobby (" + obj.nick_already_exists.game_id + ").");
        }
        else if (obj.left_lobby != null) {
            setView('login');
            $('#lobby-control').hide();
        }
        else if (obj.player_list != null) {
            updatePlayerList(obj.player_list);
            
        }
        else if (obj.game_state != null) {
            updatePlayerList(obj.game_state.players);
            var gs = obj.game_state;
            if (gs.state_data === "starting") {
                setView('starting');
            }
            else if (gs.state_data.creating != null) {

                var creating = gs.state_data.creating;
                var chars = creating.available_chars;

                question = creating.question;
                char_list = chars;
                $('#question-box').html(creating.question);
                $('#letter-box').html(chars.join(" "));
                $('#word').val("");

                setView('creating');
            }
            else if (gs.state_data.guessing != null) {
                var guesses = gs.state_data.guessing;
                displayGuessing(guesses);
            }
            else if (gs.state_data.revealing != null) {
                displayResult(gs.state_data.revealing.round_result, gs.state_data.players);
            }
        }
        else {
            statusMessage("Unknown message recieved: " + msg);
        }
    }

    function displayGuessing(guesses) {
        var sub_words = guesses.submitted_words;
        var questions = guesses.questions;
        questionlist = questions;
        wordlist = sub_words.map(pair => pair[0]);

        setupDraggame(questionlist, wordlist);
        setView('guessing');
    }

    function displayResult(result) {
        var sol = result.solutions;
        var solution_dict = {};
        for (var i = 0; i < sol.length; i++) {
            solution_dict[sol[i][0]] = sol[i][1];
        }
        var $table = $('<table/>');
        $table.addClass('result-table');

        var row_shows = result.words.map(w => w[2]);
        var $row = $("<tr/>");
        $row.append($("<th/>"));
        for(var i = 0; i < result.words.length; i++) {
            var $wordline = $("<th/>");
            var $word = $("<p/>");
            $word.text(result.words[i][1]);
            $wordline.append($word);
            if (!row_shows[i] && result.words[i][0] == nick) {
                var $butt = $("<button/>");
                $butt.attr("id", "reveal-button");
                $butt.attr("class", "mini-button");
                $butt.text("Reveal");
                $wordline.append($butt);
            }
            else if (row_shows[i]) {
                var $creator = $("<small/>");
                $creator.text(result.words[i][0]);
                $wordline.append($creator);
            }
            $row.append($wordline);
        }
        $table.append($row);

        for(var i = 0; i < result.questions.length; i++) {
            var $row = $("<tr/>");
            var $header = $("<th/>");
            $header.text(result.questions[i]);
            $row.append($header);
            for(var j = 0; j < result.words.length; j++) {
                var $cell = $("<td/>");
                if (row_shows[j]) {
                    if (solution_dict[result.words[j][1]] == result.questions[i]) {
                        $cell.addClass("result-correct");
                    }
                    else {
                        $cell.addClass("result-wrong");
                    }
                    for (var k = 0; k < result.guesses[j][i].length; k++) {
                        var $p = $('<p>');
                        $p.text(result.guesses[j][i][k]);
                        $cell.append($p);
                    }
                    $cell.text(result.guesses[j][i].join(", "));
                }
                $row.append($cell);
            }
            $table.append($row);
        }

        $('#guesses-table').html("");
        $('#guesses-table').append($table);
        $('#points-table').html("");

        var $header = $("<tr/>");
        var $points = $("<tr/>");
        var pl = result.point_list;
        for(var i = 0; i < pl.length; i++) {
            var $htd = $("<th/>"); $htd.text(pl[i][0]);
            var $ptd = $("<td/>"); $ptd.text(pl[i][1]);
            $header.append($htd);
            $points.append($ptd);
        }
        $('#points-table').append($header);
        $('#points-table').append($points);

        setView('results');
    }

    function updateReadyStates(player) {
        self_player = player;
        if (player.ready) {
            $("#ready-button").addClass("button-unready");
            $("#ready-button").removeClass("button-ready");
            $("#submit-word").addClass("button-unready");
            $("#submit-word").removeClass("button-ready");
            $("#submit-guess").addClass("button-unready");
            $("#submit-guess").removeClass("button-ready");
        } else {
            $("#ready-button").addClass("button-ready");
            $("#ready-button").removeClass("button-unready");
            $("#submit-word").addClass("button-ready");
            $("#submit-word").removeClass("button-unready");
            $("#submit-guess").addClass("button-ready");
            $("#submit-guess").removeClass("button-unready");
        }
    }

    function updatePlayerList(players) {
        $('#player-list').text("");
        for (var i = 0; i < players.length; i++) {
            var playerclass = players[i].ready ? "player-ready" : "player-unready";
            var $pitem = $('<p/>');
            $pitem.addClass(playerclass);
            $pitem.text(players[i].nick + " (" + players[i].points + ")");
            $('#player-list').append($pitem);

            if (players[i].nick == nick) {
                updateReadyStates(players[i]);
            }
        }
        $('#lobby-control').show();
    }

    function setView(view) {
        $('#loginform').hide();
        $('#startingform').hide();
        $('#creating').hide();
        $('#guessing').hide();
        $('#results').hide();

        switch (view) {
            case 'login':
                $('#loginform').show();
                break;
            case 'starting':
                $('#startingform').show();
                $('#results').show();
                break;
            case 'creating':
                $('#creating').show();
                break;
            case 'guessing':
                $('#guessing').show();
                break;
            case 'results':
                $('#results').show();
                break;
        }
    }

    function statusMessage(message) {
        $('#status').html(message);
        setTimeout(function () {
            $('#status').html("");
        }, 4000);
    }
});