// The total number of discipline points per level for a mage.
var disciplinePointsMage = new Array(0,0,1,3,6,10,15,21,35,45,56,68,81,96,112,129,147,166,187,210,234,259,286,314,343,374,406,439,474,511,549,588,629,671,714,758,803,849,896,944,993,1043,1094,1147,1201,1256,1312,1369,1427,1486,1546);

// The total number of discipline points per level for an archer or a warrior.
var disciplinePointsArcherWarrior = new Array(0,0,1,3,6,10,15,21,28,36,45,56,68,81,96,112,129,148,168,189,211,234,258,283,309,336,364,393,423,454,486,519,553,588,624,661,700,740,781,823,866,910,955,1001,1048,1096,1145,1195,1246,1298,1351);

// The total number of power points per level for a mage.
var powerPointsMage = new Array(0,0,0,0,0,0,0,0,1,1,3,3,4,4,6,6,7,7,10,10,11,11,14,14,15,15,18,18,20,20,23,23,25,25,28,28,30,30,33,33,35,35,38,38,40,40,43,43,46,46,50);

// The total number of power points per level for an archer or a warrior.
powerPointsArcherWarrior = new Array(0,0,0,0,0,0,0,0,1,1,2,2,3,3,5,5,6,6,8,8,9,9,11,11,12,12,15,15,17,17,20,20,22,22,25,25,27,27,30,30,32,32,35,35,37,37,40,40,42,42,45);
var disciplineCost = new Array(0,1,1,3,3,6,6,10,10,15,15,21,21,28,28,36,36,45,45,55,'MAX');

// The required discipline level for each power level.
var powerRequirement = new Array(0,0,0,11,15,19);


/**
 * This function is run when the DOM is loaded, replacing window.onload().
 */
$(function() {
    /**
     * Increases the character's level.
     */
    $("#ro_level_up_button").click(function() {
        var characterSubclassName = $("#ro_character_subclass").html();
        var characterLevel = regnum.characterLevel();
        var disciplinePoints = regnum.disciplinePoints();
        var powerPoints = regnum.powerPoints();

        $("#ro_errors").html("");
        
        // Make sure a subclass has been chosen.
        if (!characterSubclassName) {
            $("#ro_errors").append(msgSubclass + "<br />");
        }
        
        if (characterLevel < 50) {
            characterLevel += 1;
            if (characterSubclassName == "Conjurer" || characterSubclassName == "Warlock" || characterSubclassName == "Beschwörer" || characterSubclassName == "Hexenmeister" || characterSubclassName == "Szellemidéz?" || characterSubclassName == "Boszorkánymester") {
                disciplinePoints += disciplinePointsMage[characterLevel] - disciplinePointsMage[characterLevel - 1];
                powerPoints += powerPointsMage[characterLevel] - powerPointsMage[characterLevel - 1];
            }
            else {
                disciplinePoints += disciplinePointsArcherWarrior[characterLevel] - disciplinePointsArcherWarrior[characterLevel - 1];
                powerPoints += powerPointsArcherWarrior[characterLevel] - powerPointsArcherWarrior[characterLevel - 1];
            }
        }
        else {
            $("#ro_errors").append(msgMaxLevel + "<br />");
        }
        
        regnum.characterLevel(characterLevel);
        regnum.disciplinePoints(disciplinePoints);
        regnum.powerPoints(powerPoints);
        
        regnum.validateSetup();
    });
    
    /**
     * Decreases the character's level.
     */
    $("#ro_level_down_button").click(function() {
        var characterSubclassName = $("#ro_character_subclass").html();
        var characterLevel = regnum.characterLevel();
        var disciplinePoints = regnum.disciplinePoints();
        var powerPoints = regnum.powerPoints();

        $("#ro_errors").html("");
        
        // Make sure a subclass has been chosen.
        if (!characterSubclassName) {
            $("#ro_errors").append(msgSubclass + "<br />");
        }
        
        if (characterLevel > 1) {
            characterLevel -= 1;
            if (characterSubclassName == "Conjurer" || characterSubclassName == "Warlock" || characterSubclassName == "Beschwörer" || characterSubclassName == "Hexenmeister" || characterSubclassName == "Szellemidéz?" || characterSubclassName == "Boszorkánymester") {
                disciplinePoints -= disciplinePointsMage[characterLevel + 1] - disciplinePointsMage[characterLevel];
                powerPoints -= powerPointsMage[characterLevel + 1] - powerPointsMage[characterLevel];
            }
            else {
                disciplinePoints -= disciplinePointsArcherWarrior[characterLevel + 1] - disciplinePointsArcherWarrior[characterLevel];
                powerPoints -= powerPointsArcherWarrior[characterLevel + 1] - powerPointsArcherWarrior[characterLevel];
            }
        }
        else {
            $("#ro_errors").append(msgMinLevel + "<br />");
        }
        
        regnum.characterLevel(characterLevel);
        regnum.disciplinePoints(disciplinePoints);
        regnum.powerPoints(powerPoints);
        
        regnum.validateSetup();
    });
    
    /**
     * Show the table of disciplines and powers.
     */
    $("#ro_character_form").submit(function(event) {
        var character_form = $("#ro_character_form").get(0);
        var subclass = character_form.subclass;
        var level = parseInt(character_form.level.value);
        
        if (isNaN(level)) level = 1;
        if (level < 1) level = 1;
        if (level > 50) level = 50;
        
        var selectedSubclass = subclass.options[subclass.selectedIndex];
        var subclassName = selectedSubclass.text;
        var subclassId = selectedSubclass.value;
        
        var disciplinePoints = 0;
        var powerPoints = 0;
        switch (subclassName) {
            case "Conjurer":
            case "Warlock":
            case "Beschwörer":
            case "Hexenmeister":
            case "Szellemidéz?":
            case "Boszorkánymester":
                disciplinePoints = disciplinePointsMage[level];
                powerPoints = powerPointsMage[level];
                break;
            
            default:
                disciplinePoints = disciplinePointsArcherWarrior[level];
                powerPoints = powerPointsArcherWarrior[level];
                break;
        }
        
        $("#ro_character_subclass_id").html(subclassId);
        $("#ro_character_subclass").html(subclassName);
        regnum.characterLevel(level);
        regnum.disciplinePoints(disciplinePoints);
        regnum.powerPoints(powerPoints);
        $("#ro_power_descriptions").html("");
        $("#ro_errors").html("");
        
        $("#ro_ajax_target").html("<div class='loading'>" + msgLoading + "</div>");
        $.get(ajaxSubclassUrl, {"subclass": subclass.value}, function(data) {
            $("#ro_ajax_target").html(data);
            regnum.addSetupTableEvents();
        });
        
        event.preventDefault();
    });
    
    /**
     * Show the list of saved setups.
     */
    $("#ro_load_setups_button").click(function() {
        regnum.showSetups();
    });
    
    /**
     * Hide the spell descriptions.
     */
    $("#ro_power_descriptions_button").click(function() {
        $("#ro_power_descriptions").html('');
        $("#ro_power_descriptions_button").css("visibility", "hidden");
    });
});


/**
 * Custom class for defining helper methods and functions.
 */
var regnum = {
    /**
     * Gets or sets the character's level.
     */
    characterLevel: function(level) {
        if (level != undefined) {
            $("#ro_character_level").html(level);
            $("#ro_character_form").get(0).level.value = level;
        }
        else {
            return parseInt($("#ro_character_level").html());
        }
    },
    
    /**
     * Gets or sets the number of discipline points.
     */
    disciplinePoints: function(points) {
        if (points != undefined) {
            $("#ro_discipline_points").html(points);
        }
        else {
            return parseInt($("#ro_discipline_points").html());
        }
    },
    
    /**
     * Gets or sets the number of power points.
     */
    powerPoints: function(points) {
        if (points != undefined) {
            $("#ro_power_points").html(points);
        }
        else {
            return parseInt($("#ro_power_points").html());
        }
    },
    
    /**
     * Gets or sets the level of the specified discipline.
     */
    disciplineLevel: function(disciplineId, level) {
        var elements = $("span.discipline_level");
        if (level != undefined) {
            for (var i = 0; i < elements.length; i++) {
                if (elements[i].id == disciplineId) {
                    elements[i].innerHTML = level;
                    break;
                }
            }
        }
        else {
            for (var i = 0; i < elements.length; i++) {
                if (elements[i].id == disciplineId) {
                    return parseInt(elements[i].innerHTML);
                }
            }
        }
    },
    
    /**
     * Gets or sets the level of the specified power.
     */
    powerLevel: function(powerId, level) {
        var elements = $("td.power_level");
        if (level != undefined) {
            for (var i = 0; i < elements.length; i++) {
                if (elements[i].id == powerId) {
                    var max = elements[i].innerHTML.split("/")[1];
                    elements[i].innerHTML = level + "/" + max;
                    break;
                }
            }
        }
        else {
            for (var i = 0; i < elements.length; i++) {
                if (elements[i].id == powerId) {
                    return parseInt(elements[i].innerHTML.split("/")[0]);
                }
            }
        }
    },
    
    /**
     * Gets or sets the maximum level of the specified power.
     */
    powerMaxLevel: function(powerId, maxLevel) {
        var elements = $("td.power_level");
        if (maxLevel != undefined) {
            for (var i = 0; i < elements.length; i++) {
                if (elements[i].id == powerId) {
                    var level = elements[i].innerHTML.split("/")[0];
                    elements[i].innerHTML = level + "/" + maxLevel;
                    break;
                }
            }
        }
        else {
            for (var i = 0; i < elements.length; i++) {
                if (elements[i].id == powerId) {
                    return parseInt(elements[i].innerHTML.split("/")[1]);
                }
            }
        }
    },
    
    /**
     * Sets the cost of the specified discipline.
     */
    setDisciplineCost: function(disciplineId, cost) {
        var elements = $("span.discipline_cost");
        for (var i = 0; i < elements.length; i++) {
            if (elements[i].id == disciplineId) {
                elements[i].innerHTML = cost;
                break;
            }
        }
    },
    
    /**
     * Validates the current setup.
     */
    validateSetup: function() {
        var characterLevel = regnum.characterLevel();
        var disciplinePoints = regnum.disciplinePoints();
        var powerPoints = regnum.powerPoints();
        
        // Make sure there are enough points.
        if (disciplinePoints < 0) {
            $("#ro_errors").append(msgDiscPoints + "<br />");
        }
        if (powerPoints < 0) {
            $("#ro_errors").append(msgPowerPoints + "<br />");
        }
        
        disciplineRows = $("#ro_subclass_table tr.discipline");
        for (var i = 0; i < disciplineRows.length; i++) {
            // Make sure the discipline levels are allowed.
            var disciplineLevel = regnum.disciplineLevel(disciplineRows[i].id);
            if (disciplineLevel > (characterLevel + 1) / 2) {
                $("#ro_errors").append(msgDiscLevel + "<br />");
                break;
            }
            
            // Make sure the power levels are allowed.
            var powerCounter = 1;
            var powerCells = disciplineRows[i].getElementsByTagName("td");
            for (var j = 0; j < powerCells.length; j++) {
                if (powerCells[j].className == "power_level") {
                    var powerLevel = regnum.powerLevel(powerCells[j].id);
                    if (disciplineLevel < powerRequirement[powerLevel]) {
                        $("#ro_errors").append(msgPowerLevel + "<br />");
                        break;
                    }
                    else if (powerLevel > 1 && disciplineLevel <= (powerCounter * 2 - 2)) {
                        $("#ro_errors").append(msgPowerLevel + "<br />");
                        break;
                    }
                    
                    powerCounter++;
                }
            }
        }
        
        // Enable the save button.
        $("#ro_save_button").removeAttr("disabled");
    },
    
    /**
     * Show the list of save setups.
     * @param {String} subclass: The subclass to filter by or undefined for no filtering.
     */
    showSetups: function(subclass) {
        $("#ro_errors").html("");
        $("#ro_ajax_target").html("<div class='loading'>" + msgLoading + "</div>");
        $("#ro_power_descriptions").html("");
        $.get(ajaxSetupsUrl, {"subclass": subclass}, function(data) {
            $("#ro_ajax_target").html(data);
            
            /**
             * Filter the displayed setups.
             */
            $("#ro_subclass_filter").change(function() {
                regnum.showSetups(this.options[this.selectedIndex].value)
            });
            
            /**
             * Show a setup when a setup link is clicked.
             */
            $("#ro_setup_table a").click(function(event) {
                $("#ro_errors").html("");
                $("#ro_ajax_target").html("<div class='loading'>" + msgLoading + "</div>");
                
                var setupId = this.id.slice(this.id.lastIndexOf("_") + 1);
                $.get(ajaxLoadUrl, {'setup': setupId}, function(data) {
                    $("#ro_ajax_target").html(data);
                    
                    // Load the character subclass.
                    subclass = $("#ro_character_form").get(0).subclass;
                    $("#ro_character_subclass_id").html($("#setup_subclass").html());
                    for (var i = 0; i < subclass.length; i++) {
                        if (subclass.options[i].value == parseInt(document.getElementById("setup_subclass").innerHTML)) {
                            $("#ro_character_subclass").html(subclass.options[i].text);
                            break;
                        }
                    }
                    
                    // Load the character level.
                    var characterLevel = $("#setup_level").html();
                    regnum.characterLevel(characterLevel);
                    
                    // Load the discipline and power points.
                    switch ($("#ro_character_subclass").html()) {
                        case "Conjurer":
                        case "Warlock":
                        case "Beschwörer":
                        case "Hexenmeister":
                        case "Szellemidéz?":
                        case "Boszorkánymester":
                            disciplinePoints = disciplinePointsMage[characterLevel];
                            powerPoints = powerPointsMage[characterLevel];
                            break;
                        
                        default:
                            disciplinePoints = disciplinePointsArcherWarrior[characterLevel];
                            powerPoints = powerPointsArcherWarrior[characterLevel];
                            break;
                    }
                    regnum.disciplinePoints(disciplinePoints);
                    regnum.powerPoints(powerPoints);
                    
                    // Load the disciplines and powers.
                    disciplineRows = $("#ro_subclass_table tr.discipline");
                    for (var i = 0; i < disciplineRows.length; i++) {
                        // Determine the discipline level.
                        disciplineLevel = regnum.disciplineLevel(disciplineRows[i].id);
                        
                        // Determine the discipline cost.
                        regnum.setDisciplineCost(disciplineRows[i].id, disciplineCost[disciplineLevel + 1]);
                        
                        // Subtract the used discipline points.
                        cost = 0;
                        for (var j = 1; j < disciplineLevel; j++) {
                            cost += disciplineCost[j + 1];
                        }
                        regnum.disciplinePoints(regnum.disciplinePoints() - cost);
                        
                        // Subtract the used power points.
                        cost = 0;
                        powerCells = disciplineRows[i].getElementsByTagName("td");
                        for (var j = 1; j < powerCells.length; j++) {
                            if (powerCells[j].className == "power") {
                                cost += regnum.powerLevel(powerCells[j].id) - 1;
                            }
                        }
                        regnum.powerPoints(regnum.powerPoints() - cost);
                        
                        // Highlight the appropriate power images.
                        maxPower = ((disciplineLevel) / 2) - 0.3;
                        images = disciplineRows[i].getElementsByTagName("img");
                        for (var j = 1; j < images.length; j += 3) {
                            if (j <= (maxPower * 3) + 1) {
                                changeOpacity(images[j], 100);
                            }
                            else {
                                changeOpacity(images[j], 30);
                            }
                        }
                        
                        // Update power max levels.
                        powers = disciplineRows[i].getElementsByTagName("td");
                        powerCounter = 1;
                        for (var j = 1; j < powers.length; j++) {
                            if (powers[j].className == "power_level") {
                                maxPowerLevel = 1;
                                for (var x = 1; x < 6; x++) {
                                    if (disciplineLevel >= powerRequirement[x] && disciplineLevel > (powerCounter * 2 - 2)) {
                                        maxPowerLevel = x;
                                    }
                                }
                                regnum.powerMaxLevel(powers[j].id, maxPowerLevel);
                                powerCounter++;
                            }
                        }
                    }
                    
                    // Validate the setup and show any errors.
                    regnum.validateSetup();
                    regnum.addSetupTableEvents();
                });

                event.preventDefault();
            });
        });
    },
    
    /**
     * Adds the event handlers for the setup table.
     */
     addSetupTableEvents: function() {
        /**
         * Shows the descriptions for the power.
         */
        $(".ro_power_descriptions_link").click(function(event) {
            $("#ro_power_descriptions_button").css("visibility", "visible");
            $("#ro_power_descriptions").html("<div class='loading'>" + msgLoading + "</div>");
            var power = this.id.slice(this.id.lastIndexOf("_") + 1);
            var level = regnum.powerLevel(power);
            $.get(ajaxPowerUrl, {"power": power, "level": level}, function(data) {
                $("#ro_power_descriptions").html(data)
            });
            event.preventDefault();
        });
        
        /**
         * Changes the discipline's level.
         */
        $(".ro_discipline_level_button").click(function() {
            var discipline = this.id.slice(this.id.lastIndexOf("_") + 1);
            var characterLevel = regnum.characterLevel();
            var disciplinePoints = regnum.disciplinePoints();
            var disciplineLevel = regnum.disciplineLevel(discipline);
            
            $("#ro_errors").html("");
            
            if (this.value == "+") {
                if (disciplineLevel < 19 && disciplineLevel + 1 <= (characterLevel + 1) / 2) {
                    var cost = disciplineCost[disciplineLevel + 1];
                    if (cost <= disciplinePoints) {
                        disciplineLevel += 1;
                        disciplinePoints -= cost;
                    }
                    else {
                        $("#ro_errors").append(msgDiscPoints + "<br />");
                    }
                }
                else {
                    $("#ro_errors").append(msgDiscMaxLevel + "<br />");
                }
            }
            else {
                if (disciplineLevel > 1) {
                    var cost = disciplineCost[disciplineLevel];
                    disciplineLevel -= 1;
                    disciplinePoints += cost;
                }
                else {
                    $("#ro_errors").append(msgDiscMinLevel + "<br />");
                }
            }
            
            // Find the discipline element.
            var element = $("#ro_subclass_table tr.discipline")
            for (var i = 0; i < element.length; i++) {
                if (element[i].id == discipline) {
                    disciplineElement = element[i];
                    break;
                }
            }
            
            // Highlight available power images.
            var images = disciplineElement.getElementsByTagName("img");
            var maxPower = ((disciplineLevel) / 2) - 0.3;
            for (var i = 1; i < images.length; i += 3) {
                if (i <= (maxPower * 3) + 1) {
                    changeOpacity(images[i], 100);
                }
                else {
                    changeOpacity(images[i], 30);
                }
            }
            
            // Update power max levels.
            var powers = disciplineElement.getElementsByTagName("td");
            var powerCounter = 1;
            for (var i = 1; i < powers.length; i++) {
                if (powers[i].className == "power_level") {
                    var maxPowerLevel = 1;
                    for (var x = 1; x < 6; x++) {
                        if (disciplineLevel >= powerRequirement[x] && disciplineLevel > (powerCounter * 2 - 2)) {
                            maxPowerLevel = x;
                        }
                    }
                    regnum.powerMaxLevel(powers[i].id, maxPowerLevel);
                    powerCounter++;
                }
            }
            
            regnum.disciplineLevel(discipline, disciplineLevel);
            regnum.setDisciplineCost(discipline, disciplineCost[disciplineLevel + 1]);
            regnum.disciplinePoints(disciplinePoints);
            
            regnum.validateSetup();
        });
        
        /**
         * Increases the power's level.
         */
        $(".ro_power_level_up_link").click(function(event) {
            var linkId = this.id.slice(this.id.lastIndexOf("_") + 1);
            var discipline = linkId.slice(0, linkId.indexOf("-"));
            var power = linkId.slice(linkId.indexOf("-") + 1);
            
            var disciplineLevel = regnum.disciplineLevel(discipline);
            var powerPoints = regnum.powerPoints();
            var powerLevel = regnum.powerLevel(power);
            
            $("#ro_errors").html("");
            
            if (powerPoints > 0) {
                if (powerLevel < 5 && powerRequirement[powerLevel + 1] <= disciplineLevel && powerLevel + 1 <= regnum.powerMaxLevel(power)) {
                    powerPoints -= 1;
                    powerLevel += 1;
                }
                else {
                    $("#ro_errors").append(msgPowerMaxLevel + "<br />");
                }
            }
            else {
                $("#ro_errors").append(msgPowerPoints + "<br />");
            }
            
            regnum.powerPoints(powerPoints);
            regnum.powerLevel(power, powerLevel);
            
            regnum.validateSetup();
            
            // Highlight the appropriate power level if the descriptions are dislayed.
            var powerLevel = regnum.powerLevel(power);
            var levels = $("#power_description_" + power + " td")
            for (var i = 0; i < levels.length; i++) {
                if (i == powerLevel - 1) {
                    levels[i].className = "highlighted";
                }
                else {
                    levels[i].className = "none";
                }
            }
            event.preventDefault();
        });
        
        /**
         * Decreases the power's level.
         */
        $(".ro_power_level_down_link").click(function(event) {
            var linkId = this.id.slice(this.id.lastIndexOf("_") + 1);
            var discipline = linkId.slice(0, linkId.indexOf("-"));
            var power = linkId.slice(linkId.indexOf("-") + 1);
            
            var disciplineLevel = regnum.disciplineLevel(discipline);
            var powerPoints = regnum.powerPoints();
            var powerLevel = regnum.powerLevel(power);
            
            $("#ro_errors").html("");
            
            if (powerLevel > 1) {
                powerPoints += 1;
                powerLevel -= 1;
            }
            else {
                $("#ro_errors").append(msgPowerMinLevel + "<br />");
            }
            
            regnum.powerPoints(powerPoints);
            regnum.powerLevel(power, powerLevel);
            
            regnum.validateSetup();
            
            // Highlight the appropriate power level if the descriptions are dislayed.
            var powerLevel = regnum.powerLevel(power);
            var levels = $("#power_description_" + power + " td")
            for (var i = 0; i < levels.length; i++) {
                if (i == powerLevel - 1) {
                    levels[i].className = "highlighted";
                }
                else {
                    levels[i].className = "none";
                }
            }
            event.preventDefault();
        });
        
        /**
         * Saves the current setup.
         */
        $("#ro_save_form").submit(function(event) {
            var setupName = this.setup_name.value;
            var setupDescription = this.setup_description.value;
            
            // Make sure a name was entered.
            if (setupName == "") {
                alert(msgEnterName);
                return false;
            }
            
            // Disable the save button.
            $("#ro_save_button").attr("disabled", "disabled");
            
            // Create an array representing the disciplines and powers and their levels.
            var disciplines = [];
            var disciplineIndex = 0;
            var disciplineRows = $("#ro_subclass_table tr");
            for (var i = 0; i < disciplineRows.length; i++) {
                if (disciplineRows[i].id) {
                    var disciplineLevel = regnum.disciplineLevel(disciplineRows[i].id);
                    
                    var powers = [];
                    var powerIndex = 0;
                    var powerCells = disciplineRows[i].getElementsByTagName("td");
                    for (var j = 0; j < powerCells.length; j++) {
                        if (powerCells[j].id && powerCells[j].className == "power") {
                            var powerLevel = regnum.powerLevel(powerCells[j].id);
                            powers[powerIndex] = [powerCells[j].id, powerLevel]
                            powerIndex++;
                        }
                    }
                    
                    disciplines[disciplineIndex] = [disciplineRows[i].id, disciplineLevel, powers.join("-")].join("|")
                    disciplineIndex++;
                }
            }
            var subclass = $("#ro_character_subclass_id").html();
            var level = regnum.characterLevel();
            var setupString = disciplines.join("~");
            
            // Send the setup-string to the server.
            $.get(ajaxSaveUrl, {"name": setupName, "description": setupDescription, "subclass": subclass, "level": level, "setupString": setupString}, function(data) {
                alert(msgSetupSaved);
            });
            event.preventDefault();
        });
    },
}


function changeOpacity(image, opacity) {
    image.style.opacity = (opacity / 100);
    image.style.MozOpacity = (opacity / 100);
    image.style.KhtmlOpacity = (opacity / 100);
    image.style.filter = "alpha(opacity=" + opacity + ")";
}

