// ==UserScript==
// @name           IWannaDifferentFamiliar
// @description    Lets you customize your KoL familiars' appearance.
// @namespace      http://www.mrphlip.com/
// @include        http://*kingdomofloathing.com/charpane.php*
// @include        http://*kingdomofloathing.com/familiar.php*
// @include        http://*kingdomofloathing.com/familiarnames.php*
// @include        http://*kingdomofloathing.com/charsheet.php*
// @include        http://*kingdomofloathing.com/showplayer.php*
// @include        http://*kingdomofloathing.com/showfamiliars.php*
// @include        http://*kingdomofloathing.com/inventory.php*
// @include        http://*kingdomofloathing.com/fight.php*
// @include        http://*kingdomofloathing.com/arena.php*
// ==/UserScript==
// Based loosely on OneTonTomato's "IWannaBitten" script:
// http://kol.upup.us/scripts/#IWannaBitten

var replacements = [
	{
		fam_name_from:   "Cymbal-Playing Monkey",
		fam_name_to:     "Cheshire Bat",
		fam_img_from:    "http://images.kingdomofloathing.com/itemimages/familiar42.gif", // CPM
		fam_img_to:      "http://images.kingdomofloathing.com/itemimages/familiar23.gif", // Bitten
		equip_name_from: "funky brass fez",
		equip_name_to:   "smile-sharpening stone",
		equip_img_from:  "http://images.kingdomofloathing.com/itemimages/brassfez.gif",
		equip_img_to:    "http://images.kingdomofloathing.com/itemimages/sharpstone.gif",
		combatArray: [
			[/clashes its cymbals, begging for additional Meat.  Creepily./, "disappears for a moment, and reappears carrying some extra Meat."],
			[/smiles in a disturbing manner./, "smiles unsettlingly."],
			[/winks at you with one bloodshot plastic eye. How a plastic eye can be bloodshot, you don't know, but it really creeps you out./, "somehow manages to smile, wink, and vanish at the same time."],
			[/bangs his cymbals and does an arrhythmic, jerky dance around the maypole. Same as it ever was./, "do-si-does around the maypole, disappearing on every 'si.'"],
			[/manages to look even creepier with his blood-red wax lips. <i>shudder.<\/i>/, "disappears and reappears, leaving only the wax lips floating in the air in a curious (and curiouser) smile."],
		],
		arenaArray: []
	},
	{
		fam_name_from:   "Sabre-Toothed Lime",
		fam_name_to:     "Badly-Drawn Face",
		fam_img_from:    "http://images.kingdomofloathing.com/itemimages/familiar5.gif",
		fam_img_to:      "data:image/gif;base64,R0lGODdhHgAeAIABAAAAAP///ywAAAAAHgAeAAACa4yPAcub" +
		                 "DxV7LUJnDc4zn34BXkiOJSKaUfqxarJtkkvJmMvS387n2g8D+mw8SnFWo+FkGt1FxVxBnc" +
		                 "HpqOKJvkK47VKBotZQwCOnahO3wusWFSSphpe6urOhzatXYjhHC7MXNxWFtTWD51EAADs=",
		equip_name_from: "tiny shaker of salt",
		equip_name_to:   "anti-aliased curves",
		equip_img_from:  "http://images.kingdomofloathing.com/itemimages/saltshaker.gif",
		equip_img_to:    "data:image/gif;base64,R0lGODlhHgAeAKEEABocGVJUUpqcmfX39CH+FUNyZWF0ZWQg" +
		                 "d2l0aCBUaGUgR0lNUAAsAAAAAB4AHgAAAnCcj6DL3QiHmzMmipU9OW/TYZBAksGJpiX5Da" +
		                 "uQxsHbvrK61uuN0p/Nm+UQsYavdSgyjsiBcsFEPhXR1hRQ/TRizc021bV8UeHI+FSGnAPp" +
		                 "C3TYlizhbSM9bS/FQXP9Ps/y1xcYByiwJ/fmVzh4uFcAADs=",
		combatArray: [
			[/([^<>]+) bites (\w+) for (\d+) damage./, "$1 pixelates $2, dealing $3 damage."],
			[/([^<>]+) attempts to bite (\w+), but misses./, "$1 tries to pixelate $2, but misses."],
			[/([^<>]+) finds your slain foe's wallet stuck between its vicious fangs./, "One of $1's eyes disappears and reappears... you're going to assume that was a wink."],
			[/([^<>]+) gnashes his sabre-teeth at the maypole. I guess that's the way limes dance./, "$1 hovers in circles around the maypole."],
			[/([^<>]+) grins and almost loses his wax lips (they don't fit well over the sabre teeth, you see)./, "$1 smiles with his wax lips, in some humourous manner."],
		],
		arenaArray: [
			[/has no eyes, and so is not exactly the best choice for this event./, "has no hands, and can't carry the items he finds."],
		]
	},
]

//fight!?
switch(document.location.pathname)
{
	case "/charpane.php":
		replaceCharpane();
		break;
	case "/familiar.php":
		replaceTerrarium();
		break;
	case "/familiarnames.php":
		replaceFamiliarNames();
		break;
	case "/charsheet.php":
		replaceCharsheet();
		break;
	case "/showplayer.php":
		replaceShowplayer();
		break;
	case "/showfamiliars.php":
		replaceShowfamiliars();
		break;
	case "/inventory.php":
		replaceInventory();
		break;
	case "/fight.php":
		replaceFightText();
		break;
	case "/arena.php":
		replaceArenaText();
		break;
}

// I don't like iterators... don't ask me why...
function getElementsByXPath(root, path)
{
	var XPathIterator = document.evaluate(path, root, null, XPathResult.ANY_TYPE, null);
	var ret = new Array();
	var i;
	while (i = XPathIterator.iterateNext())
		ret.push(i);
	return ret;
}

function replaceCharpane()
{
	var image = getElementsByXPath(document, '//a[@href="familiar.php"]//img');
	if (image.length <= 0)
		return;
	image = image[0];
	for (var i=replacements.length-1;i>=0;i--)
	{
		if(image.src == replacements[i].fam_img_from)
		{
			image.src = replacements[i].fam_img_to;
			var text = getElementsByXPath(image, 'following::text()[contains(.,"-pound")]');
			if (text.length > 0)
			{
				text = text[0];
				text.nodeValue = text.nodeValue.replace(replacements[i].fam_name_from, replacements[i].fam_name_to);
			}
			break;
		}
	}
}
function replaceTerrarium()
{
	// check current familiar - there should be one image before the <select> boxes if you have a familiar on, and none if you don't.
	var image = getElementsByXPath(document, '//img[following::select]');
	if (image.length > 0)
	{
		var equip = image[1];
		image = image[0];
		
		for (var i=replacements.length-1;i>=0;i--)
		{
			if(image.src == replacements[i].fam_img_from)
			{
				image.src = replacements[i].fam_img_to;
				var text = getElementsByXPath(image, 'following::text()[contains(.,"-pound")][1]');
				if (text.length > 0)
				{
					text = text[0];
					text.nodeValue = text.nodeValue.replace(replacements[i].fam_name_from, replacements[i].fam_name_to);
				}
				if (equip && equip.src == replacements[i].equip_img_from)
				{
					equip.src = replacements[i].equip_img_to;
					equip.parentNode.nextSibling.firstChild.nodeValue = replacements[i].equip_name_to;
				}
				break;
			}
		}
	}
	
	// now the other familiars in the terrarium
	var rows = getElementsByXPath(document, '//form//tr[//input[@type="radio"]]');
	for (var i=rows.length-1;i>=0;i--)
	{
		var image = getElementsByXPath(rows[i], './/img');
		var equip = image[1];
		image = image[0];
		var text = getElementsByXPath(rows[i], './/text()[contains(.,"-pound")][1]');
		text = text[0];
		if (!image || !text)
			continue;
		for (var j=replacements.length-1;j>=0;j--)
		{
			if(image.src == replacements[j].fam_img_from)
			{
				image.src = replacements[j].fam_img_to;
				text.nodeValue = text.nodeValue.replace(replacements[j].fam_name_from, replacements[j].fam_name_to);
				if (equip && equip.src == replacements[j].equip_img_from)
					equip.src = replacements[j].equip_img_to;
				break;
			}
		}
	}
	
	// finally, the familiar equipment dropdowns
	var entries = getElementsByXPath(document, '//select[@name="whichfam"]//option//text()');
	for (var i=entries.length-1;i>=0;i--)
	{
		for (var j=replacements.length-1;j>=0;j--)
		{
			if(entries[i].nodeValue.indexOf(replacements[j].fam_name_from) >= 0)
			{
				entries[i].nodeValue = entries[i].nodeValue.replace(replacements[j].fam_name_from, replacements[j].fam_name_to);
				break;
			}
		}
	}
	var entries = getElementsByXPath(document, '//select[@name="whichitem"]//option//text()');
	for (var i=entries.length-1;i>=0;i--)
	{
		for (var j=replacements.length-1;j>=0;j--)
		{
			if(entries[i].nodeValue.indexOf(replacements[j].equip_name_from) >= 0)
			{
				entries[i].nodeValue = entries[i].nodeValue.replace(replacements[j].equip_name_from, replacements[j].equip_name_to);
				break;
			}
		}
	}
}
function replaceFamiliarNames()
{
	var rows = getElementsByXPath(document, '//tr[//img]');
	for (var i=rows.length-1;i>=0;i--)
	{
		var image = getElementsByXPath(rows[i], './/img');
		image = image[0];
		var text = getElementsByXPath(rows[i], './td[last()]//text()');
		text = text[0];
		if (!image || !text)
			continue;
		for (var j=replacements.length-1;j>=0;j--)
		{
			if(image.src == replacements[j].fam_img_from)
			{
				image.src = replacements[j].fam_img_to;
				text.nodeValue = text.nodeValue.replace(replacements[j].fam_name_from, replacements[j].fam_name_to);
				break;
			}
		}
	}
}
function replaceCharsheet()
{
	var row = getElementsByXPath(document, '//p[./b="Current Familiar:"]//table//tr[2]');
	row = row[0];
	if (!row)
		return;
	var image = getElementsByXPath(row, './/img[1]');
	image = image[0];
	var text = getElementsByXPath(row, './/text()[contains(.,"-pound")]');
	text = text[0];
	if (!image || !text)
		return;
	for (var i=replacements.length-1;i>=0;i--)
	{
		if(image.src == replacements[i].fam_img_from)
		{
			image.src = replacements[i].fam_img_to;
			text.nodeValue = text.nodeValue.replace(replacements[i].fam_name_from, replacements[i].fam_name_to);
			break;
		}
	}
}
function replaceShowplayer()
{
	if(document.getElementsByTagName('b')[0].textContent == top.frames[1].document.getElementsByTagName('b')[0].textContent)
	{
		var row = getElementsByXPath(document, '//p[./text()="Familiar:"]//table//tr[2]');
		row = row[0];
		if (!row)
			return;
		var image = getElementsByXPath(row, './/img');
		equip = image[1];
		image = image[0];
		var text = getElementsByXPath(row, './/text()[contains(.,", the ")]');
		text = text[0];
		if (!image || !text)
			return;
		for (var i=replacements.length-1;i>=0;i--)
		{
			if(image.src == replacements[i].fam_img_from)
			{
				image.src = replacements[i].fam_img_to;
				text.nodeValue = text.nodeValue.replace(replacements[i].fam_name_from, replacements[i].fam_name_to);
				if (equip && equip.src == replacements[i].equip_img_from)
					equip.src = replacements[i].equip_img_to;
				break;
			}
		}
	}
}
function replaceShowfamiliars()
{
	if(document.getElementsByTagName('b')[0].textContent == top.frames[1].document.getElementsByTagName('b')[0].textContent + "'s Familiars")
	{
		var table = getElementsByXPath(document, '//p//table');
		table = table[0];
		if (!table)
			return;
		// first replace equipped familiar, if any
		var image = getElementsByXPath(table, 'preceding::img');
		equip = image[1];
		image = image[0];
		var text = getElementsByXPath(table, 'preceding::text()[contains(.,"-pound")]');
		text = text[0];
		if (image && text)
		{
			for (var i=replacements.length-1;i>=0;i--)
			{
				if(image.src == replacements[i].fam_img_from)
				{
					image.src = replacements[i].fam_img_to;
					text.nodeValue = text.nodeValue.replace(replacements[i].fam_name_from, replacements[i].fam_name_to);
					if (equip && equip.src == replacements[i].equip_img_from)
					{
						equip.src = replacements[i].equip_img_to;
						equip.parentNode.nextSibling.firstChild.nodeValue = replacements[i].equip_name_to;
						break;
					}
				}
			}
		}
		// now replace other familiars
		var rows = getElementsByXPath(table, '//tr');
		for (var i=rows.length-1;i>=0;i--)
		{
			var image = getElementsByXPath(rows[i], './/img');
			var equip = image[1];
			image = image[0];
			var text = getElementsByXPath(rows[i], './/text()[contains(.,"-pound")][1]');
			text = text[0];
			if (!image || !text)
				continue;
			for (var j=replacements.length-1;j>=0;j--)
			{
				if(image.src == replacements[j].fam_img_from)
				{
					image.src = replacements[j].fam_img_to;
					text.nodeValue = text.nodeValue.replace(replacements[j].fam_name_from, replacements[j].fam_name_to);
					if (equip && equip.src == replacements[j].equip_img_from)
						equip.src = replacements[j].equip_img_to;
					break;
				}
			}
		}
	}
}
function replaceInventory()
{
	// maybe we just equipped something
	var results = getElementsByXPath(document, '//table[.//tr[1]//text()[.="Results:"]]//tr[2]//td');
	results = results[0];
	if (results)
	{
		var equip = results.getElementsByTagName('img');
		equip = equip[0];
		var equiptext = results.getElementsByTagName('b');
		equiptext = equiptext[0];
		if (equip && equiptext)
		{
			equiptext = equiptext.firstChild;
			for (var i=replacements.length-1;i>=0;i--)
			{
				if(equiptext.nodeValue == replacements[i].equip_name_from)
				{
					equip.src = replacements[i].equip_img_to;
					equiptext.nodeValue = replacements[i].equip_name_to;
					break;
				}
			}
		}
	}
	// Check that this is the equipment page
	var equipment = getElementsByXPath(document, '//table[.//tr[1]//text()[.="Current Equipment:"]]');
	equipment = equipment[0];
	if (!equipment)
		return;
	// replace the familiar equipment if one is equipped
	var equipped = getElementsByXPath(equipment, './/tr[./td/text()="Familiar:"]');
	equipped = equipped[0];
	if (equipped)
	{
		var image = getElementsByXPath(equipped, './/img');
		image = image[0];
		var text = getElementsByXPath(equipped, './/b/text()');
		text = text[0];
		if (image && text)
		{
			for (var i=replacements.length-1;i>=0;i--)
			{
				if(text.nodeValue == replacements[i].equip_name_from)
				{
					image.src = replacements[i].equip_img_to;
					text.nodeValue = replacements[i].equip_name_to;
					break;
				}
			}
		}
	}
	// now replace any in the inventory
	var inventory = document.getElementById("section512");
	if (!inventory)
		return;
	inventory = inventory.getElementsByTagName("img");
	for (var i=inventory.length-1;i>=0;i--)
	{
		for (var j=replacements.length-1;j>=0;j--)
		{
			if(inventory[i].src == replacements[j].equip_img_from)
			{
				var text = inventory[i].parentNode.nextSibling.firstChild.firstChild;
				if (text.nodeValue == replacements[j].equip_name_from)
				{
					inventory[i].src = replacements[j].equip_img_to;
					text.nodeValue = replacements[j].equip_name_to;
					break;
				}
			}
		}
	}
}
function replaceFightText()
{
	// innerHTML isn't safe on elements with broken HTML, like the KoL fight form... have to be a bit more ingeneous to avoid touching that...
	var paragraphs = document.getElementsByTagName('p');
	for (var i = 0; i < paragraphs.length; i++)
	{
		text = paragraphs[i].innerHTML;
		for(var j = 0; j < replacements.length; j++)
			for(var k = 0; k < replacements[j].combatArray.length; k++)
				text = text.replace(replacements[j].combatArray[k][0], replacements[j].combatArray[k][1]);
		paragraphs[i].innerHTML = text;
	}
}
function replaceArenaText()
{
	var results = getElementsByXPath(document, '//table[.//tr[1]//text()[.="Results:"]]//tr[2]//td');
	results = results[0];
	if (!results)
		return;
	text = results.innerHTML;
	for(var i = 0; i < replacements.length; i++)
		for(var j = 0; j < replacements[i].arenaArray.length; j++)
			text = text.replace(replacements[i].arenaArray[j][0], replacements[i].arenaArray[j][1]);
	results.innerHTML = text;
	// maybe we won some equipment
	var equip = results.getElementsByTagName('img');
	equip = equip[0];
	if (equip)
	{
		for (var i=replacements.length-1;i>=0;i--)
		{
			if(equip.src == replacements[i].equip_img_from)
			{
				var text = equip.parentNode.nextSibling.lastChild.firstChild;
				if (text.nodeValue == replacements[i].equip_name_from)
				{
					equip.src = replacements[i].equip_img_to;
					text.nodeValue = replacements[i].equip_name_to;
					break;
				}
			}
		}
	}
}
