// skills.js

/*
  3EProfiler character sheet source file.
  Copyright (C) 2007 Myth-Weavers Games
  **
*/

// void SkillCalc(node)
// Recalculates the skill modifier for a skill. Function expects one of
// the input nodes for the skill row to be passed to it.
function SkillCalc(node)
{

	// Determine which skill is being adjusted (the first 7 chars of the
	// node name are always "SkillXX", regardless of which row the input is
	// from.
	var skill = String(node.name).substr(0, 7);
	var trained = 0;
	
	if (sheet()[skill + "Trained"].checked) {
		trained = 5;
	}

	ZeroFill(
		sheet()[skill + "AbModPlusHalfLevel"],
		sheet()[skill + "ArmorPenalty"],
		sheet()[skill + "MiscMod"],
		sheet()[skill + "TempMod"]);

	sheet()[skill + "Mod"].value = Add(
		sheet()[skill + "AbModPlusHalfLevel"].value,
		sheet()[skill + "ArmorPenalty"].value,
		sheet()[skill + "MiscMod"].value,
		trained,
		sheet()[skill + "TempMod"].value);
	
			
		// Passive Skills
		
	if (sheet()[skill].value == "Insight") {
			//sheet().PISkillMod.value = Clean(sheet()[skill + "Mod"].value);
			sheet().PassiveInsight.value = parseInt(sheet()[skill + "Mod"].value) + 10;
	}
			
	if (sheet()[skill].value == "Perception") {
			//sheet().PPSkillMod.value = Clean(sheet()[skill + "Mod"].value);
			sheet().PassivePerception.value = parseInt(sheet()[skill + "Mod"].value) + 10;
	}
}

// void SkillLookUp(node)
// Performs a lookup of the skill name to try to find the skill's
// primary ability. If the skill is found, the ability is set then the
// onchange events for the ability modifier is triggered.
function SkillLookUp(node, extended)
{

	// Parse the info from the node.
	var skill = node.value;

	if (typeof skillKeys[skill] == "undefined")
	{
		return;
	}

	sheet()[node.name + "Ab"].value = abilityKeys[skillKeys[skill][0]];

	SkillLookUpKeyAb(sheet()[node.name + "Ab"]);
}

// void SkillLookUpKeyAb(node)
// Retrieves the skills key ability modifier and recalculates the skill
// modifier accordingly. The node passed to this function should be the
// Key Ability node.
function SkillLookUpKeyAb(node)
{

	// Can't make any assumptions about the node value, since the user may
	// have written anything.
	var ability = GetText(node);
  
	if (ability == "str") ability = "Str";
	else if (ability == "con") ability = "Con";
	else if (ability == "dex") ability = "Dex";
	else if (ability == "int") ability = "Int";
	else if (ability == "wis") ability = "Wis";
	else if (ability == "cha") ability = "Cha";
	else
	{
		// Not a valid ability name.
		return;
	}

	// If we don't have a modifier, return without doing anything else.
	if (!(sheet()[ability + "Mod"].value.length))
		return;
		
		var halfLevel = _calcHalfLevel();

		sheet()[node.name + "ModPlusHalfLevel"].value = GetNum(sheet()[ability + "Mod"]) + parseInt(halfLevel);

	SkillCalc(node);
}

// void SkillSort(sortfunc)
// Sorts the skill table according to the sorting function that is passed
// to sortfunc. SkillSort contains members that can act as sorting
// functions for the Array.sort() member.
function SkillSort(sortfunc)
{
	// Create a shortcut to the rows of the skills table.
	var rows = document.getElementById("skills").rows;

	// Now copy all the data in each row (the first two are headers and
	// the last is a footer).
	var rows_c = new Array();
	for (var i = 2; i < rows.length; i++)
	{
		r = new Object();
		r.mod = rows[i].cells[0].firstChild.value;
		r.skill = rows[i].cells[1].firstChild.value;
		r.ab = rows[i].cells[2].firstChild.value;
		r.trained = rows[i].cells[3].firstChild.checked;
		r.half = rows[i].cells[4].firstChild.value;
		r.armor = rows[i].cells[5].firstChild.value;
		r.misc = rows[i].cells[6].firstChild.value;
		r.temp = rows[i].cells[7].firstChild.value;
		rows_c.push(r);
	}

	// Sort the data.
	rows_c.sort(sortfunc);

	// Now, restore the sorted data.
	for (var i = 2; i < rows.length; i++)
	{
		var r = rows_c.shift();
		rows[i].cells[0].firstChild.value = r.mod;
		rows[i].cells[1].firstChild.value = r.skill;
		rows[i].cells[2].firstChild.value = r.ab;
		rows[i].cells[3].firstChild.checked = r.trained;
		rows[i].cells[4].firstChild.value = r.half;
		rows[i].cells[5].firstChild.value = r.armor;
		rows[i].cells[6].firstChild.value = r.misc;
		rows[i].cells[7].firstChild.value = r.temp;
	}

}

SkillSort.ByName = function(a, b)
{
	if ((a.skill.length == 0) && (b.skill.length == 0))
		return 0;
	else if (a.skill.length == 0)
		return 1;
	else if (b.skill.length == 0)
		return -1;
	return a.skill.localeCompare(b.skill);
}

SkillSort.ByAbility = function(a, b)
{
	if ((a.ab.length == 0) && (b.ab.length == 0))
		return SkillSort.ByName(a, b);
	else if (a.ab.length == 0)
		return 1;
	else if (b.ab.length == 0)
		return -1;

	// Custom order:
	var key = {'str': 1, 'dex': 2, 'con': 3, 'int': 4, 'wis': 5, 'cha': 6};
	var comp = key[a.ab.toLowerCase()] - key[b.ab.toLowerCase()];
	if (comp)
		// If different, return the comparison.
		return comp;
	else
		// If equal, return the result of sorting by name.
		return SkillSort.ByName(a, b);
}

SkillSort.ByTrained = function(a, b)
{
	if (a.trained && b.trained)
		return SkillSort.ByName(a, b);
	else if (!a.trained && !b.trained)
		return SkillSort.ByName(a, b);
	else
		return a.trained ? -1 : 1;
}

SkillSort.ByMod = function(a, b)
{
	return SkillSort._ByNumber(a, b, "mod");
}

SkillSort.ByHalf = function(a, b)
{
	return SkillSort._ByNumber(a, b, "half");
}

SkillSort.ByArmor = function(a, b)
{
	return SkillSort._ByNumber(a, b, "armor");
}

SkillSort.ByMisc = function(a, b)
{
	return SkillSort._ByNumber(a, b, "misc");
}
SkillSort.ByTemp = function(a, b)
{
	return SkillSort._ByNumber(a, b, "temp");
}

SkillSort._ByNumber = function(a, b, prop)
{
	numa = parseFloat(a[prop]);
	numb = parseFloat(b[prop]);
	if ((isNaN(numa)) && (isNaN(numb)))
		return SkillSort.ByName(a, b);
	else if (isNaN(numa))
		return 1;
	else if (isNaN(numb))
		return -1;
	if (numa == numb)
		return SkillSort.ByName(a, b);
	else
		return (numa > numb) ? -1 : 1;
}

// Fill the skill table with the core SWRPG skill set.
function SkillAutoFill()
{

	// Verify before continuing.
	if (!confirm("AutoFill will initialize the skill table with the core D&D 4th edition skill set. This will clear any existing data.\n\nAre you sure you want to continue?"))
		return;

	// First clear the table.
	_skillClear();
	_skillFill();
}

// Clear the entire skill table.
function SkillClear()
{

	// Verify before actually clearing.
	if (!confirm("Clearing the skill table will remove ALL skill data.\n\nAre you sure you want to continue?"))
		return;

	_skillClear();

}

//////////////////////////////////////////////////////////////////////////
// Internal functions

// Clear the skill table.
function _skillClear()
{
	var rows = document.getElementById("skills").rows;
	for (var i = 2; i < rows.length; i++)
	{
		rows[i].cells[0].firstChild.value = '';
		rows[i].cells[1].firstChild.value = '';
		rows[i].cells[2].firstChild.value = '';
		rows[i].cells[3].firstChild.checked = false;
		rows[i].cells[4].firstChild.value = '';
		rows[i].cells[5].firstChild.value = '';
		rows[i].cells[6].firstChild.value = '';
		rows[i].cells[7].firstChild.value = '';
	}

}

// Fill the skill table with the D&D4th ed. skillset.
function _skillFill()
{
	var row = 2;
	var skilltable = document.getElementById("skills");
	row = 2;
	for (var skill in skillKeys)
	{

		// Don't alter if we already have some data.
		// (Can happen from an legacy character on first load).
		if (skilltable.rows[row].cells[1].firstChild.value)
			continue;

		// Set the skill and the key ability.
		skilltable.rows[row].cells[1].firstChild.value = skill;
		SkillLookUp(skilltable.rows[row].cells[1].firstChild, false);
		row++;
	}
}

// void _calcSkills(ability)
// Resets the ability modifier and recalculates the skills whose key
// ability match skillname.
function _calcSkills(ability)
{
	var numskills = document.getElementById("skills").rows.length - 2;
	for (var i = 1; i <= numskills; i++)
	{
		var num = FormatNumber(i);
	// armor penalty
		if (
			sheet()["Skill" + num].value == "Acrobatics" || 
			sheet()["Skill" + num].value == "Athletics" ||
			sheet()["Skill" + num].value == "Endurance" ||
			sheet()["Skill" + num].value == "Stealth" ||
			sheet()["Skill" + num].value == "Thievery")
		{
			ZeroFill(sheet().ArmorCheckPenalty);
			sheet()["Skill" + num + "ArmorPenalty"].value = sheet().ArmorCheckPenalty.value;
		} else {
			ZeroFill(sheet().ArmorCheckPenalty);
			sheet()["Skill" + num + "ArmorPenalty"].value = "-";
		}
		
		// Check Key ability and look up.
		if (String(sheet()["Skill" + num + "Ab"].value).toLowerCase() == ability)
			SkillLookUpKeyAb(sheet()["Skill" + num + "Ab"]);
	}
}