$(function() {
    var connection = 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 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 (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();
        var nick = $('#nick').val();
        var msg = {
            join: {
                game_id: game_id,
                nick: nick,
            }
        };

        send(msg);
    });

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

        send(msg);
    });

    $('#leave-lobby').click(function() {
        var msg = "leave_lobby";
        send(msg);
    });

    $('#ready').click(function() {
        var game_id = $('#gameId').val();
        var nick = $('#nick').val();
        var msg = "ready";
        send(msg);
    });

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

    $('#submitGuess').click(function() {
        var list = [];
        for(var i = 0; i < wordlist.length; i++) {
            var field = "#g" + i;
            var numTxt = $(field).val();
            var number = parseInt(numTxt);
            if (number > 0 && number <= questionlist.length) {
                list.push([wordlist[i], questionlist[number - 1]]);
            }
            else {
                statusMessage("Please enter a valid number");
                return;
            }
        }
        var msg = {
            submit_guess: {
                guesses: list
            }
        };
        send(msg);
    });

    function connect(initial_message) {
        if (connection != null) {
            disconnect();
        }
        var uri = 'ws://' + 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() {
        };
    }

    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_exists != null) {
            statusMessage("Game \"" + obj.game_already_exists.game_id + "\" already exists");
        }
        else if (obj.left_lobby != null) {
            setView('login');
            $('#lobby-control').hide();
        }
        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(" "));

                setView('creating');
            }
            else if (gs.state_data.guessing != null) {
                var guesses = gs.state_data.guessing;
                displayGuessing(guesses);
            }
        }
        else if (obj.round_result != null) {
            displayResult(obj.round_result);
        }
        else {
            statusMessage("Unknown message retrieved");
        }
    }

    function displayGuessing(guesses) {
        var sub_words = guesses.submitted_words;
        var questions = guesses.questions;
        var questionsHtml = "";
        for (var i = 0; i < questions.length; i++) {
            questionsHtml += (i + 1) + ": " + questions[i] + "<br>";
        }
        $('#guessingDynTable').html(questionsHtml);
        $('#guessingDyn').html("");
        for (var i = 0; i < sub_words.length; i++) {
            var $label = $("<label to='g" + i + "'>" + sub_words[i][0] + "</label>");
            var $field = $("<input id='g" + i + "' type='text' /><br>");
            $('#guessingDyn').append($label);
            $('#guessingDyn').append($field);
        }

        questionlist = questions;
        wordlist = sub_words.map(pair => pair[0]);

        
        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 wordline = "<tr><th></th>";
        for(var i = 0; i < result.words.length; i++) {
            wordline += "<th>" + result.words[i] + "</th>";
        }
        wordline += "</tr>";
        $table.append(wordline);

        for(var i = 0; i < result.questions.length; i++) {
            var wordline = "<tr><th>" + result.questions[i] + "</th>";
            for(var j = 0; j < result.words.length; j++) {
                if (solution_dict[result.words[j]] == result.questions[i]) {
                    wordline += "<td class='result-correct'>";
                }
                else {
                    wordline += "<td class='result-wrong'>";
                }
                wordline += result.guesses[j][i] + "</td>";
            }
            wordline += "</tr>";
            $table.append(wordline);
        }

        $('#results').html($table);

        setView('results');
    }

    function updatePlayerList(players) {
        playerlist = "";
        for (var i = 0; i < players.length; i++) {
            playerlist += players[i].nick + "(" + players[i].points + ")";
            if (i + 1 < players.length)
                playerlist += "<br>";
        }
        $('#player-list').html(playerlist);
        $('#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);
    }
});