var talentData = {};

var currentTooltip = null;

var charSheetActive = false;
var initialWidth, initialHeight;

var charStorageEntries = {
	charName: "name",
	charRace: "race",
	charExp: "exp",
	charSize: "size",
	charStr: "str",
	charDex: "dex",
	charInt: "int",
	charCha: "cha"
};


function insertAfter(referenceNode, newNode) {
    referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}

function replaceElement(element, replacement) {
	element.parentNode.replaceChild(element, replacement);
}

function createTooltip(id) {
	var talent = talents[id];
	var level = talentData[id] ? talentData[id] : 0;

	var element = document.createElement("span");
	element.id = "talent_tooltip"
	element.className = "tooltip";

	if (id == "base") {
		element.style.display = "none";
		return element;
	}

	var title = document.createElement("span");
	title.className = "tooltipTitle";

	title.innerHTML = talent.displayName + " (" + level + "/" + talent.levels.length + ")<br>";

	element.appendChild(title);

	if (!isLocked(id)) {
		if (talentData[id] && talentData[id] > 0) {
			var currentLevel = document.createElement("span");
			currentLevel.className = "tooltipCurrentLevel";
			currentLevel.innerHTML = "Current Level:<br>";
			currentLevel.innerHTML += talent.levels[talentData[id] - 1].description + "<br>";

			element.appendChild(currentLevel);
		} else {
			var unlockable = document.createElement("span");
			unlockable.className = "tooltipCurrentLevel";
			unlockable.innerHTML = "Click to spend a point and unlock this talent.<br>";

			element.appendChild(unlockable);
		}

		if (!talentData[id] || talentData[id] < talent.levels.length) {
			var currentLevel = talentData[id];
			if (currentLevel == undefined) { 
				currentLevel = 0; // save space by ommiting level 0 in the json
			}

			var nextLevel = document.createElement("span");
			nextLevel.className = "tooltipNextLevel";
			nextLevel.innerHTML = "<br>Next Level:<br>";
			nextLevel.innerHTML += talent.levels[currentLevel].description;

			element.appendChild(nextLevel);
		}
	} else {
		var requirements = document.createElement("span");
		requirements.className = "tooltipRequirements";
		requirements.innerHTML = "Requirements:<ul>";

		for (key in talent.requirements) {
			requirements.innerHTML += "<li>" + talents[key].displayName + " at level " + talent.requirements[key] + "</li>";
		}

		requirements.innerHTML += "</ul>";
		element.appendChild(requirements);
	}

	return element;
}

function renderTalentTooltip(talentSpan) {
	if (document.getElementById("talent_tooltip"))
		document.getElementById("talent_tooltip").remove();

	insertAfter(talentSpan, createTooltip(talentSpan.id));

	currentTooltip = talentSpan.id;
}

function deleteTalentTooltip(talentSpan) {
	document.getElementById("talent_tooltip").remove();

	currentTooltip = null;
}

function isLocked(id) {
	var talent = talents[id];

	for (key in talent.requirements) {
		if (!talentData[key] || talentData[key] < talent.requirements[key])
			return true;
	}

	return false;
}

function createTalentElement(id) {
	var talent = talents[id];

	var element = document.createElement("span");
	element.id = id;
	element.onmouseover = function() {
		renderTalentTooltip(document.getElementById(id));

		document.getElementById(id + "_hoverOverlay").style.opacity = 1;
	};
	element.onmouseout = function() {
		deleteTalentTooltip(document.getElementById(id));

		document.getElementById(id + "_hoverOverlay").style.opacity = 0;
	};
	element.onclick = function() {spendPoint(id);};
	element.oncontextmenu = function() {refundPoint(id); return false; };

	var image = document.createElement("img");
	image.src = talent.icon;
	image.onmouseover = null;
	image.onmouseleave = null;
	image.onclick = null;
	image.oncontextmenu = null;
	
	var hoverOverlay = document.createElement("span");
	hoverOverlay.id = id + "_hoverOverlay";
	hoverOverlay.className = "hoverOverlay";
	hoverOverlay.onmouseover = null;
	hoverOverlay.onmouseleave = null;
	hoverOverlay.onclick = null;
	hoverOverlay.oncontextmenu = null;


	element.appendChild(image);
	element.appendChild(hoverOverlay);

	var locked = isLocked(id);

	if (talentData[id]) {
		if (talentData[id] > 0)
			element.className = "unlockedTalent";
		else 
			element.className = "talent";
	} else if (talent.unlockedByDefault) {
		element.className = "unlockedTalent";
	} else {
		if (locked) 
			element.className = "lockedTalent";
		else
			element.className = "talent"
	}

	if (!locked && id != "base") {
		var levelIndicator = document.createElement("span");
		levelIndicator.className = "levelIndicator";
		levelIndicator.innerHTML = talentData[id] ? talentData[id] : 0;

		element.appendChild(levelIndicator);

		if (talentData[id] == talent.levels.length) {
			levelIndicator.style.color = "#F0D700";
		}

		
	}

	return element;
}

function createNoTalentSpan() {
	var element = document.createElement("span");
	element.className = "noTalent";

	return element;
}

function placeTalents() {

	var minX = 0, minY = 0, maxX = 0, maxY = 0;

	for (key in talents) {
		var talent = talents[key];
		minX = Math.min(minX, talent.pos.x);
		maxX = Math.max(maxX, talent.pos.x);

		minY = Math.min(minY, talent.pos.y);
		maxY = Math.max(maxY, talent.pos.y);
	}

	minX--;
	maxX++;

	minY--;
	maxY++;
 
	var xOffset = -minX, yOffset = -minY;

	var xSize = maxX + xOffset + 1, ySize = maxY + yOffset + 1;

	var elements = [];

	for (var i = 0; i < ySize; i++) {
		elements[i] = [];

		for (var j = 0; j < xSize; j++) {
			elements[i][j] = createNoTalentSpan();
		}
	}

	for (key in talents) {
		var talent = talents[key];
		var x = talent.pos.x, y = talent.pos.y;

		elements[y + yOffset][x + xOffset] = createTalentElement(key);
	}

	for (var i = 0; i < elements.length; i++) {
		for (var j = 0; j < elements[i].length; j++) {
			content.appendChild(elements[i][j]);
		}
		content.appendChild(document.createElement("br"));
	}
}

function replaceTalents() {
	var content = document.getElementById("content");

	while (content.hasChildNodes()) {
		content.removeChild(content.lastChild);
	}

	placeTalents();

	if (currentTooltip) {
		insertAfter(document.getElementById(currentTooltip), createTooltip(currentTooltip));
	}
}

function load() {
	function loadInput(id, name) {
		if (localStorage[name])
			document.getElementById(id).value = localStorage[name];
	}

	if (localStorage.talentData) {
		talentData = JSON.parse(localStorage.talentData);
		
		for (key in charStorageEntries) {
			loadInput(key, charStorageEntries[key]);
		}

		placeTalents();
	} else {
		localStorage.talentData = "{}";
		placeTalents();
	}
}

function save() {
	localStorage.talentData = JSON.stringify(talentData);
	localStorage.name = document.getElementById("charName").value;
}

function reset() {
	var resetButton = document.getElementById("resetButton");
	var resetLabel = document.getElementById("resetLabel");
	if (resetLabel) 
		resetLabel.remove();

	resetButton.innerHTML = "Reset";

	resetButton.onclick = askReset;


	talentData = {};
	replaceTalents();

	function resetInput(id, name) {
		document.getElementById(id).value = "";
		localStorage.removeItem(name);
	}

	for (key in charStorageEntries) {
		resetInput(key, charStorageEntries[key]);
	}

	localStorage.removeItem("talentData");
	localStorage.talentData = "{}";
}

function askReset() {
	var resetButton = document.getElementById("resetButton");
	var resetLabel = document.createElement("i");
	resetLabel.id = "resetLabel";
	resetLabel.innerHTML = " Really reset EVERYTHING? (This <u>cannot</u> be undone)"

	insertAfter(resetButton, resetLabel);

	resetButton.innerHTML = "Yes"
	
	resetButton.onclick = reset;
}

function spendPoint(id) {
	if (isLocked(id)) return;

	var talent = talents[id];
	var currentLevel = talentData[id];
	if (currentLevel == undefined)
		currentLevel = 0;

	if (currentLevel < talent.levels.length) {
		talentData[id] = currentLevel + 1;

		save();

		replaceTalents();
	}
}

function refundPoint(id) {
	var canRefund = true;

	if (!talentData[id]) {
		canRefund = false;
	}

	for (k in talentData) {
		if (k == id)
			continue;
		
		if (talents[k].requirements[id]) {
			if (talentData[id] == talents[k].requirements[id])
				canRefund = false;
		}
		
	}

	if (canRefund) {
		talentData[id]--;

		if (talentData[id] == 0) {
			delete talentData[id];
		}

		save();

		replaceTalents();
	}
}

/*
	TODO: fadeInCharSheet and fadeOutCharSheet just look plain bad. I need to do somethinf about them.
*/

function fadeInCharSheet() {
	if (charSheetActive)
		return;

	var charSheet = document.getElementById("charSheet");



	charSheet.style.width = charSheet.style.height = "initial";
	
	var computedStyle = window.getComputedStyle(charSheet);
	
	if (!initialWidth || !initialHeight) {
		initialWidth = computedStyle.width;
		initialHeight = computedStyle.height;
	}

	charSheet.style.width = charSheet.style.height = 0;
	charSheet.style.visibility = "visible";

	//var interval = setInterval(animate, 1);
	//var millis = 0;
	var duration = 120;

	var keyframes = [
		{ opacity: 0, width: 0, height: 0, easing: "ease-out" },
		{ opacity: 0, width: initialWidth, height: initialHeight, offset: 0.5, easing: "ease-in"},
		{ opacity: 1, width: initialWidth, height: initialHeight }
	]

	charSheet.animate(keyframes, {duration: duration, fill: "forwards"});

	/*
	function animate() {
		if (millis >= duration) {
			clearInterval(interval);
			return;
		}

		var t = millis / (duration - 1);

		if (t < 0.5)
			charSheet.style.opacity = t * t;
		else
			charSheet.style.opacity = t;

		millis++;
	}
	*/




	charSheetActive = true;
}

function fadeOutCharSheet() {
	if (!charSheetActive)
		return;

	var charSheet = document.getElementById("charSheet");

	var computedStyle = window.getComputedStyle(charSheet);

	if (!initialWidth || !initialHeight) {
		initialWidth = computedStyle.width;
		initialHeight = computedStyle.height;
	}

	//var interval = setInterval(animate, 1);
	//var millis = 0;
	var duration = 120;

	var keyframes = [
		{ opacity: 1, width: initialWidth, height: initialHeight, easing: "ease-in" },
		{ opacity: 0, width: initialWidth, height: initialHeight, offset: 0.5, easing: "ease-out"},
		{ opacity: 0, width: 0, height: 0, }
	]

	charSheet.animate(keyframes, {duration: duration, fill: "forwards"}).onfinish = function() { charSheet.style.visibility = "hidden"; };

	/*
	function animate() {
		if (millis >= duration) {
			clearInterval(interval);
			charSheet.style.width = charSheet.style.height = "0";
			charSheet.style.visibility = "hidden";
			
			return;
		}

		var t = millis / (duration - 1);

		if (t < 0.5)
			charSheet.style.opacity = 1 - t * t;
		else
			charSheet.style.opacity = 1 - t;

		millis++;
	}
	*/

	charSheetActive = false;
}










