/*global $:false, data, VLE */

var DataObject = (function () {
    function DataObject() {
        this.allowedAttempts = 3;
        this.attempts = 0;
        this.element = [];
    }

    DataObject.prototype.reset = function (length) {
        while (this.element.length > 0) {
            this.element.pop();
        }
        var i;
        for (i = 0; i < length; ++i) {
            this.element[i] = null;
        }
    };
    return DataObject;
}());

var dataObject = new DataObject();

var selection = null;
var selectForDeletion = null;

function getText(html) {
    return $('<div></div>').html(html).text();
}

function saveDataToVLE() {
    var temp = {
        allowedAttempts: 3,
        attempts: 0,
        element: []
    };

    temp.allowedAttempts = JSON.stringify(dataObject.allowedAttempts);
    temp.attempts = JSON.stringify(dataObject.attempts);
    temp.element = JSON.stringify(dataObject.element);

    VLE.set_server_data(true, temp, function () {
        console.log("set_server_data was successful");
    }, function (msg) {
        console.log("set_server_data has failed");
        if (msg != null) {
            console.log(msg);
        }
    });
}

function retrieveDataFromVLE() {
    var array = [];
    array.push("allowedAttempts");
    array.push("attempts");
    array.push("element");

    dataObject.reset(data.choices.length);

    VLE.get_server_data(true, array, function (savedData) {
        dataObject.allowedAttempts = JSON.parse(savedData.allowedAttempts);
        dataObject.attempts = JSON.parse(savedData.attempts);
        dataObject.element = JSON.parse(savedData.element);

        if (savedData.element.length > 0) {
            var i;
            var text;
            for (i = 0; i < dataObject.element.length; ++i) {
                if (dataObject.element[i] !== null) {
                    $("#choices").find("span").each(function (index, element) {
                        text = getText(element.innerHTML);
                        text = text.replace(',', '');
                        if (dataObject.element[i].text[0] === text) {
                            $(element).appendTo("#" + dataObject.element[i].text[1]);
                        }
                    });
                }
            }

            var correct;
            var $td = $("td");
            $td.find("span").each(function (index, element) {
                correct = false;
                for (i = 0; i < data.answers.length; ++i) {
                    text = getText(element.innerHTML);
                    text = text.replace(',', '');
                    text = text.replace('.', '');

                    if (text === data.answers[i].text[0] && element.parentNode.id === data.answers[i].text[1]) {
                        dataObject.element[index] = {text: [text, element.parentNode.id]};
                        $(element).addClass("green-border").draggable("disable").css('cursor', 'default');
                        correct = true;
                        break;
                    }
                }
                if (!correct) {
                    if (dataObject.attempts >= dataObject.allowedAttempts) {
                        $(element).addClass("red-border").draggable("disable").css('cursor', 'default');
                    } else {
                        $(element).appendTo("#choices");
                    }
                }
            });

            sort();
        }
    }, function (msg) {
        console.log("Failed to get server data.");
        if (msg != null) {
            console.log(msg);
        }
    });
}

function sort() {
    var child,
        len,
        i;
    $(".separator").remove();

    $("td").each(function (index, element) {
        len = element.childElementCount;
        if (len > 1) {
            for (i = 0; i < len; ++i) {
                if (i < (len - 1)) {
                    child = element.children[i];
                }
            }
        }

        if (len > 0) {
            child = element.children[element.childElementCount - 1];
        }
    });
}

function shuffleArray(array) {
    var i, j, temp;
    for (i = array.length - 1; i > 0; i--) {
        j = Math.floor(Math.random() * (i + 1));
        temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
    return array;
}

function showFeedback(message) {
    $("#feedback").remove();
    $("#content").append("<div id='feedback'><p>" + message + "</p></div>");
    }

function getFeedbackMessage(count) {
    var message = "";

    if (count < data.answers.length) {
        if (count == 1) {
            message = count + data.feedback[2].text;
        } else {
            message = count + data.feedback[1].text;
        }
    } else if (count == data.answers.length) {
        message = data.feedback[0].text;
    }

    if (dataObject.attempts >= dataObject.allowedAttempts) {
        message += data.feedback[3].text;
    }

    if (message == "") {
        message = "<br/>Please enter a value!";
    }

    return message;
}

function reveal() {
    dataObject.reset(data.choices.length);
    var $td = $("td");
    $td.find("span").each(function (index, element) {
        $(element).appendTo("#choices");
    });

    var $choices = $("#choices");
    $choices.find("span").removeClass("green-border").removeClass("red-border");

    var text;
    var i;
    for (i = 0; i < data.answers.length; ++i) {
        $choices.find("span").each(function (index, element) {
            text = getText(element.innerHTML);
            if (text === data.answers[i].text[0]) {
                $(element).appendTo("#" + data.answers[i].text[1]);
                dataObject.element[i] = {text: [text, element.parentNode.id]};
            }
        });
    }

    sort();

    $choices.find("span").draggable({ disabled: true }).css('cursor', 'default');
    $choices.droppable("disable");

    $td.find("span").draggable({ disabled: true }).css('cursor', 'default');
    $td.droppable("disable");
    $("#submit").hide();

    saveDataToVLE();
}

function submit() {
    dataObject.attempts++;
    $(".separator").remove();

    var text, correct, count = 0;
    var i;
    var $td = $("td");
    $td.find("span").each(function (index, element) {
        correct = false;
        for (i = 0; i < data.answers.length; ++i) {
            text = getText(element.innerHTML);
            text = text.replace(',', '');
            text = text.replace('.', '');

            if (text === data.answers[i].text[0] && element.parentNode.id === data.answers[i].text[1]) {
                dataObject.element[index] = {text: [text, element.parentNode.id]};
                $(element).addClass("green-border").draggable("disable").css('cursor', 'default');
                correct = true;
                count++;
                break;
            }
        }
        if (!correct) {
            if (dataObject.attempts >= dataObject.allowedAttempts) {
                $(element).addClass("red-border").draggable("disable").css('cursor', 'default');
            } else {
                $(element).appendTo("#choices");
            }
        }
    });

    sort();


    
    var message = getFeedbackMessage(count);
    showFeedback(message);

    if (dataObject.attempts >= dataObject.allowedAttempts) {
        $("#choices").find("span").draggable("disable").css('cursor', 'default');
        $td.droppable("disable").css('cursor', 'default');
            reveal();
        if (count === data.answers.length) {
            $("#submit").hide();
        }
    } else {
        if (count === data.answers.length) {
            $("#choices").find("span").draggable("disable").css('cursor', 'default');
            $td.droppable("disable").css('cursor', 'default');

            $("#submit").hide();
        }
    }

    saveDataToVLE();
}

function reset() {
    $(".separator").remove();
    dataObject.attempts = 0;
    dataObject.reset(data.choices.length);
    showFeedback("");

    var $td = $("td");
    $td.find("span").each(function (index, element) {
        $(element).appendTo("#choices");
    });

    var choices = data.choices;
    shuffleArray(choices);

    var $choices = $("#choices");
    $choices.find("span").each(function (index, element) {
        element.innerHTML = choices[index].text;
    });

    $choices.find("span").removeClass("green-border").removeClass("red-border").draggable("enable").css('cursor', 'pointer');
    $choices.droppable("enable");
    $td.droppable("enable");

    $("#submit").off("click").val("Submit").show().click(function () {
        submit();
    });

    saveDataToVLE();
}

$(function () {
    var $content = $("#content");
    $content.append("<div id='choices'/>");

    var choices = data.choices;
    shuffleArray(choices);

    var $choices = $("#choices");

    var i;
    for (i = 0; i < data.choices.length; ++i) {
        $choices.append("<span>" + choices[i].text + "</span>");
    }

    $content.append("<div style='margin-top: 10px'><table/></div>");

    $("table").append("<tr id='tr0'/>");
    for (i = 0; i < data.colHeaders.length; ++i) {
        $("tr").append("<th/>");
    }

    $("th").each(function (index, element) {
        element.innerHTML = data.colHeaders[index].text;
    });

    $("table").append("<tr id='tr1'/>");

    for (i = 0; i < data.colHeaders.length; ++i) {
        $("#tr1").append("<td id='td" + i + "' tabIndex='1'>");
    }

    $content.append("<input id='submit' type='button' value='Submit'/>");
    $content.append("<input id='reset' type='button' value='Reset'/>");

    $choices.find("span").draggable({
        revert: "invalid",
        zIndex: 100,
        refreshPositions: true,
        containment: "#content",
        drag: function (e, ui) {
            ui.helper.addClass("selected");
        },
        stop: function (e, ui) {
            ui.helper.removeClass("selected");
        }
    }).sortable();

    $choices.droppable({
        drop: function (e, ui) {
            ui.draggable.detach().css({top: 0, left: 0}).appendTo(this);
            sort();
        }
    });

    $choices.on("click", function () {
        if (selection !== null && !$(selection).hasClass("ui-draggable-disabled") &&
            !$(selectForDeletion).parent().hasClass("ui-droppable-disabled")) {
            $(selectForDeletion).appendTo("#choices");

            $("td").removeClass("selected");
            $(selectForDeletion).addClass("selected");

            selection = selectForDeletion;
            selectForDeletion = null;
            sort();
        }
    });

    $choices.find("span").on("click", function (e) {
        if (this.parentNode.nodeName != "td" && this.parentNode.nodeName != "TD") {
            e.stopPropagation();
            $("td").removeClass("selected");

            if ($(this).hasClass("selected")) {
                $(this).removeClass("selected");
                selection = null;
            } else {
                var $divs = $choices.find("span");

                if ($divs.hasClass("selected")) {
                    $divs.removeClass("selected");
                }

                $(this).addClass("selected");
                selection = this;
                selectForDeletion = this;
            }
        }
    });

    var $td = $("td");

    $td.droppable({
        hoverClass: "hover",
        tolerance: "pointer",
        drop: function (e, ui) {
            ui.draggable.detach().css({top: 0, left: 0}).appendTo(this);

            $choices.find("span").removeClass("selected");
            $(this).focus();
            selectForDeletion = this.children[0];
            sort();
        }
    });

    $td.on("click", function () {
        if (selection != null) {
            if (!$(this).hasClass("ui-droppable-disabled")) {
                $(selection).detach().removeClass("selected").css({top: 0, left: 0}).appendTo(this);
                selectForDeletion = selection;
                selection = null;
                sort();
            }
        }

        $choices.find("span").removeClass("selected");
    });

    $td.on("click", "span", function (e) {
        var $parent = $(this).parent();

        if (selection != null) {
            if (!$parent.hasClass("ui-droppable-disabled")) {
                if ($parent.children.length > 0) {
                    $parent.children(0).appendTo("#choices");
                }

                $(selection).detach().removeClass("selected").css({top: 0, left: 0}).appendTo($parent[0]);
                selectForDeletion = selection;
            }
        } else {
            selectForDeletion = this;
        }

        $choices.find("span").removeClass("selected");
        $parent.focus();
        sort();

        e.stopPropagation();
    });

    $("html").on("keyup", function (e) {
        var id = e.target.id;
        var $first,
            parent,
            i;

        if (e.which == 9) {
            $choices.find("span").first().addClass("selected");
        } else if (e.which == 13 || e.which == 32) {
            if ((e.target.nodeName == "TD" || e.target.nodeName == "td") && !$(e.target).hasClass("ui-droppable-disabled")) {
                $first = $choices.find("span").first();
                $first.appendTo("#" + id);
                selectForDeletion = $first[0];

                $first.removeClass("selected");
                $first = $choices.find("span").first();
                selection = $first[0];
                $first.addClass("selected");
                sort();
            } else if (selection != null) {
                parent = $(selection).parent()[0];
                if ((parent.nodeName == "TD" || parent.nodeName == "td") && !$(parent).hasClass("ui-droppable-disabled")) {

                    $(selection).appendTo("#choices");
                    $first = $choices.find("span").first();
                    $first.appendTo(parent);
                    selectForDeletion = selection;
                    selection = $first[0];
                }
            }
        } else if (e.which == 46 || e.which == 8) {
            if ((e.target.nodeName == "TD" || e.target.nodeName == "td") && !$(e.target).hasClass("ui-droppable-disabled")) {
                e.preventDefault();
                if (e.target.children.length > 0) {
                    for (i = 0; i < e.target.children.length; ++i) {
                        if (!$(e.target.children[i]).hasClass("ui-draggable-disabled")) {
                            $(e.target.children[i]).appendTo("#choices");

                            $first = $choices.find("span").first();
                            selection = $first[i];
                            $first.addClass("selected");
                            sort();
                            break;
                        }
                    }
                }
            } else if (selectForDeletion != null) {
                e.preventDefault();
                parent = $(selectForDeletion).parent()[0];
                if ((parent.nodeName == "TD" || parent.nodeName == "td") && !$(parent).hasClass("ui-droppable-disabled")) {
                    $(selectForDeletion).appendTo("#choices");
                    selectForDeletion = null;

                    $first = $choices.find("span").first();
                    selection = $first[0];
                    $first.addClass("selected");
                }
            }
        }
    });

    $("#submit").button().click(function () {
        submit();
    });

    $("#reset").button().click(function () {
        reset();
    });

    retrieveDataFromVLE();
});