IkariamCRCEngine = {
	ResourceImages: [
		'http://img196.imageshack.us/img196/1127/woodsmall.gif',	// wood 
		'http://img193.imageshack.us/img193/2796/winesmall.gif',	// wine 
		'http://img194.imageshack.us/img194/421/iconmarble.gif',	// marb  
		'http://img190.imageshack.us/img190/5090/glasssmall.gif',	// glas  
		'http://img195.imageshack.us/img195/2010/sulfursmall.gif'	// sulf  
	],
	UnitMapping: {
		name: { 
			slinger: 		"army s301", 
			swordsman: 		"army s302", 
			phalanx: 		"army s303", 
			archer: 		"army s313", 
			marksman: 		"army s304", 
			gyrocopter: 	"army s312", 
			"steam giant": 	"army s308", 
			bombardier: 	"army s309", 
			ram: 			"army s307", 
			catapult: 		"army s306", 
			mortar: 		"army s305", 
			doctor: 		"army s311", 
			cook: 			"army s310", 
			barbarian:		"army s316"
		},
		costs: {
			slinger: 		20, 
			swordsman: 		60, 
			phalanx: 		70, 
			archer: 		55, 
			marksman: 		200, 
			gyrocopter: 	125, 
			"steam giant": 	310, 
			bombardier: 	290, 
			ram: 			220, 
			catapult: 		560, 
			mortar: 		1550, 
			doctor: 		200, 
			cook: 			30,
			barbarian:		0
		},
		clas: { 
			"army s301": "slinger", 
			"army s302": "swordsman", 
			"army s303": "phalanx", 
			"army s313": "archer", 
			"army s304": "marksman", 
			"army s312": "gyrocopter", 
			"army s308": "steam giant", 
			"army s309": "bombardier", 
			"army s307": "ram", 
			"army s306": "catapult", 
			"army s305": "mortar", 	
			"army s311": "doctor", 
			"army s310": "cook", 
			"army s315": "spearmen", 
			"army s316": "barbarian" 
		}
	},
	ShipMapping: {
		name: { 
			cargo: 		"fleet s201", 
			ram: 		"fleet s210", 
			ballista:	"fleet s213", 
			flame: 		"fleet s211", 
			catapult: 	"fleet s214", 
			paddle: 	"fleet s216", 
			mortar: 	"fleet s215", 
			diving: 	"fleet s212" 
		},
		clas: { 
			"fleet s201": "cargo", 
			"fleet s210": "ram", 
			"fleet s213": "ballista", 
			"fleet s211": "flame", 
			"fleet s214": "catapult", 
			"fleet s216": "paddle", 
			"fleet s215": "mortar", 
			"fleet s212": "diving" 
		}
	},
	Engines: {
		"v.0.3.2": {
			BuildReport:function(formatter, report, lang, script_version, events) 
			{
				if (formatter == null) return "NullReferenceException: formatter";

				// Add Place & Time of Attack 
				output = formatter.AddColor(report.info.place + '\n' + report.info.time + '\n', 'HEADER');

				// Add Attackers + Defenders Involved 
				output += '\n';
				output += formatter.AddColor(report.info.attackers, 'ATTACKING') + '\n';
				output += 'vs' + '\n';
				output += formatter.AddColor(report.info.defenders, 'DEFENDING') + '\n';

				// Add Attacking / Defending Unit(s) 
				output += '\n';
				output += formatter.AddSeparator(67) + '\n';
				var allUnitCosts = report.info.type == "army"
					? [ 20, 60, 70, 55,  200, 125, 310, 290, 220, 560, 1550, 500, 200, 30, 0]
					: [ 270, 340, 310, 320, 1800, 1120, 910 ];
				var allUnits = report.info.type == "army"
					? ["slinger", "swordsman", "phalanx", "archer", "marksman", "gyrocopter", "steam giant", "bombardier", "ram", 
					   "catapult", "mortar", "doctor", "cook", "spearmen", "barbarian"]
					: ["ram", "ballista", "flame", "catapult", "paddle", "mortar", "diving"];
				var UNIT = report.info.type == "army" ? lang.units : lang.ships;
				var attackersLosses = 0, defendersLosses = 0; 
				for (var unit = 0; unit < allUnits.length; unit++) {
					var unitName = UNIT[allUnits[unit]]; 
					if (unitName != null) {
						var attacker = report.battle.attackers[allUnits[unit]]; 
						var defender = report.battle.defenders[allUnits[unit]];
						if (attacker != null || defender != null) {
							if (attacker != null) {
								output += formatter.PadString('right', unitName, 19, '.', 'ATTACKING');
								output += formatter.PadString('left',  attacker.left, 5, '.', 'UNITLEFT');
								output += formatter.PadString('right', '(-' + formatter.AddColor(attacker.lost, 'UNITLOST') + ')', 8, '.', '') + ' - ';
								attackersLosses += attacker.lost * allUnitCosts[unit];
							}
							else {	output += formatter.PadString('right', '', 32, '.', '') + ' - '; }
							if (defender != null) {
								output += formatter.PadString('right', unitName, 19, '.', 'DEFENDING');
								output += formatter.PadString('left',  defender.left, 5, '.', 'UNITLEFT');
								output += formatter.PadString('right', '(-' + formatter.AddColor(defender.lost, 'UNITLOST') + ')', 8, '.', '');
								defendersLosses += defender.lost * allUnitCosts[unit];
							}
							else {	output += formatter.PadString('right', '', 32, '.'); }
							output += '\n';
						}
					}
				}

				// Add Table to display Net Losses/Gains + Loot 
				var results = formatter.AddSeparator(67) + '\n';
				var metricTranslations = [lang.highscore.army_score_main, lang.report.damage];
				var metricAttackers = [IkariamCRCEngine.AddCommas(parseInt(attackersLosses*-1*.02)), IkariamCRCEngine.AddCommas(attackersLosses)];
				var metricDefenders = [IkariamCRCEngine.AddCommas(parseInt(defendersLosses*-1*.02)), IkariamCRCEngine.AddCommas(defendersLosses+report.loot.total)];
				for (var m = 0; m < metricTranslations.length; m++) {
					results += formatter.PadString('right', metricTranslations[m], 22, '.', 'ATTACKING');
					results += formatter.PadString('left', metricAttackers[m]+'', 10, '.', 'ATTACKING') + ' - ';
					results += formatter.PadString('right', metricTranslations[m], 22, '.', 'DEFENDING'); 
					results += formatter.PadString('left', metricDefenders[m]+'', 10, '.', 'DEFENDING') + '\n';
				}
				results += formatter.AddSeparator(67) + '\n';
				output += results;

				// Add Victor(s) 
				if (report.battle.victors != null) output += '\n' + formatter.AddColor(report.battle.victors, 'VICTOR') + '\n';
	
				// Add Loot 
				if (report.loot.total > 0) {
					results = '\n';
					results += lang.report.loot + ': ';
					var lootTotals = [
						report.loot.resource["wood"], 
						report.loot.resource["wine"], 
						report.loot.resource["marble"], 
						report.loot.resource["glass"], 
						report.loot.resource["sulfur"]
					];
					var lootString = [lang.resources.wood, lang.resources.wine, lang.resources.marble, lang.resources.glass, lang.resources.sulfur];
					for (var r = 0; r < lootTotals.length; r++) {
						if (lootTotals[r] > 0 ) {
							var imageString = formatter.AddImage(IkariamCRCEngine.ResourceImages[r]);
							if (imageString == '') imageString = '\n' + lootString[r];
							results += imageString + " " + IkariamCRCEngine.AddCommas(lootTotals[r]) + ' ';
						}
					}
					output += results + '\n';
				}

				// Add Results 
				if (events && report.battle.results != null)
				{
					results = '';
					output += '\n';
					for (var r in report.battle.results)
					{
						results += report.battle.results[r] + '\n';
					}
					output += formatter.AddColor(results, 'RESULTS');
				}

				// Add Homepage Link
				if (script_version)
				{
					output += "\nCreated using DLR's " + 
						formatter.AddLink("Ikariam CR Converter", "http://board.ikariam.org/index.php?page=Thread&threadID=56204") + ' (' +
						formatter.AddLink('Version ' + script_version, "http://userscripts.org/scripts/show/50784") + ')';
				}
				else
				{
					output += "\nCreated using DLR's " + 
						formatter.AddLink("Ikariam CR Converter [Web Version]", "http://tools.betawarriors.com/ikcrc/");
				}

				// Add Size, Font, Bold-Styling and Alignment 
				output = formatter.AddSize(output, 85);
				output = formatter.AddFont(output, 'Courier New');
				output = formatter.AddBold(output);
				output = formatter.AddAlignment(output, 'center');

				return output;
			},
			ParseReport:function(report)
			{
				// Report ID 
				report.info.id = $("a[href*='detailedCombatId=']").attr('href').substr(
					$("a[href*='detailedCombatId=']").attr('href').indexOf('detailedCombatId=') + 17); 

				// Battle Type / Place / Time 
				report.info.type  = $("#troopsReport table.overview tr th div[class^='army']").size() > 0 ? "army" : "fleet"; 
				report.info.place = $("#troopsReport h3.header")[0].childNodes[0].nodeValue;
				report.info.time  = $("#troopsReport h3.header span.date").text().replace(/\(/,'( ').replace(/\)/, ' )'); 
	
				// Attackers / Defenders 
				report.info.attackers = $("#troopsReport div.content div:eq(0) span").text(); 
				report.info.defenders = $("#troopsReport div.content div:eq(1) span").text(); 

				// Remaining Totals / Units - This is the tricky part to parse 
				var unitSide = null;
				var unitKeys = new Array();
				$("#troopsReport table.overview tr").each(function() {
					// re-define units that are being parsed 
					if ($(this).find("th div").size() > 0) {
						unitSide = "attackers";
						unitKeys = []; 
						$(this).find("th div").each(function() { unitKeys.push($(this).attr("class")); });
					}
					else
					if ($(this).find("td[colspan='8'][class^='col1 nobg']").size() == 1) { 
						unitSide = "defenders";
					}
					else
					if ($(this).find("td.numbers").size() == unitKeys.length) {
						unitCount = 0; 
						$(this).find("td.numbers").each(function() {
							var unitClass = unitKeys[unitCount++];
							var unit = report.info.type == "army" 
								? IkariamCRCEngine.UnitMapping.clas[unitClass] 
								: IkariamCRCEngine.ShipMapping.clas[unitClass];
							var list = unitSide == "attackers" 
								? report.battle.attackers 
								: report.battle.defenders;
							var details = $(this).text();
							if (unit != null && details.indexOf("(") != -1) {
								if (list[unit] == null || list[unit] == null) { list[unit] = { left: 0, lost: 0 } }
								list[unit].left += parseInt(details.substr(0, details.indexOf('(')).replace(/\s+/, ''));
								list[unit].lost += parseInt(details.substr(details.indexOf('(') + 2).replace(/\s+/, '').replace(/\)/, ''));
							}
						});
					}
				});

				// Victors 
				report.battle.victors = $("#troopsReport div.result div.winners").text().replace(/^\s*/, '').replace(/\s*$/, ''); 

				// Results 
				var results = {}; var count = 0;
				$("#troopsReport div.result div").not("div.winners,div.losers").each(function() {
					if ($(this).find("ul.resources").size() == 0) {
						results[count++] = $(this).text(); 
					}
				});
				if (results != '') report.battle.results = results;

				// Loot, If Available 
				$("div.result ul.resources li").each(function() {
					var type = $(this)[0].className;
					var amount = parseInt($(this).contents()[1].nodeValue.replace(/,/,''));
					report.loot.resource[type] = report.loot.resource[type] == null ? amount : report.loot.resource[type] + amount;
					report.loot.total += amount;
				});
			},
			ReadDetailed:function()
			{
				// TODO
				//$("#fieldAttacker ul div[id^='slot']").each(function() {
				//});
			}
		},
		"v.0.3.1": {
			AddUnit:function(list, unit, details)
			{
				list[unit] = {
					left: $(details).contents()[0].nodeValue.replace(/\s+\(/, ''),
					lost: $(details).find("span.loss").html().replace(/-/, '')
				};
			},
			BuildReport:function(formatter, report, lang, script_version, events) 
			{
				if (formatter == null) return "NullReferenceException: formatter";

				/* Add Place & Time of Attack */
				output = formatter.AddColor(report.info.type + ' ' + report.info.place + '\n' + '( ' + report.info.time + ' )' + '\n', 'HEADER');

				/* Add Attackers + Defenders Involved */
				output += '\n';
				output += formatter.AddColor(report.info.attackers, 'ATTACKING') + '\n';
				output += 'vs' + '\n';
				output += formatter.AddColor(report.info.defenders, 'DEFENDING') + '\n';

				/* Add Offensive / Defensive Totals */
				output += '\n';
				var totalsTranslations = [lang.report.offense, lang.report.defense, lang.report.stamina];
				for (var total = 0; total < totalsTranslations.length; total++) {
					output += formatter.PadString('right', totalsTranslations[total], 20, '.', 'ATTACKING'); 
					output += formatter.PadString('left', report.battle.attacking_totals[total], 10, '.', 'ATTACKING') + ' - ';
					output += formatter.PadString('right', totalsTranslations[total], 20, '.', 'DEFENDING'); 
					output += formatter.PadString('left', report.battle.defending_totals[total], 10, '.', 'DEFENDING') + '\n';
				}
				/* Add wall, if applicable */
				if (report.battle.wall != '' && report.battle.walltext != '') {
					output += formatter.PadString('right', '', 30, '.', '') + ' - ';
					output += formatter.PadString('right', report.battle.walltext, 20, '.', 'DEFENDING'); 
					output += formatter.PadString('left', report.battle.wall, 10, '.', 'DEFENDING') + '\n';
				}

				/* Add Attacking / Defending Unit(s) */
				output += '\n';
				var allUnitCosts = [ 40, 64, 98, 131, 196, 256, 289, 960, 210, 456, 1053, 706, 453, 144, 153, 190, 257,  346,  532, 712 ];
				var allUnits = ["slinger", "swordsman", "phalanx", "archer", "marksman", "gyrocopter", "steam giant", "bombardier", "ram", "catapult", "mortar", "doctor", "cook", "ram", "ballista", "flame", "catapult", "paddle", "mortar", "diving"];
				var UNIT = lang.units;
				var attackersLosses = 0, defendersLosses = 0; 
				for (var unit = 0; unit < allUnits.length; unit++) {
					var unitName = UNIT[allUnits[unit]]; 
					if (unitName != null) {
						var attacker = report.battle.attackers[unitName]; 
						var defender = report.battle.defenders[unitName];
						if (attacker != null || defender != null) {
							if (attacker != null) {
								output += formatter.PadString('right', unitName, 17, '.', 'ATTACKING');
								output += formatter.PadString('left',  attacker.left, 5, '.', 'UNITLEFT');
								output += formatter.PadString('right', '(-' + formatter.AddColor(attacker.lost, 'UNITLOST') + ')', 8, '.', '') + ' - ';
								attackersLosses += attacker.lost * allUnitCosts[unit];
							}
							else {	output += formatter.PadString('right', '', 30, '.', '') + ' - '; }
							if (defender != null) {
								output += formatter.PadString('right', unitName, 17, '.', 'DEFENDING');
								output += formatter.PadString('left',  defender.left, 5, '.', 'UNITLEFT');
								output += formatter.PadString('right', '(-' + formatter.AddColor(defender.lost, 'UNITLOST') + ')', 8, '.', '');
								defendersLosses += defender.lost * allUnitCosts[unit];
							}
							else {	output += formatter.PadString('right', '', 30, '.'); }
							output += '\n';
						}
					}
					if (allUnits[unit] == "cook") UNIT = lang.ships;
				}

				/* Add Table to display Net Losses/Gains + Loot */
				output += '\n';
				var results = formatter.AddSeparator(63) + '\n';
				var metricTranslations = [lang.highscore.army_score_main, lang.report.damage];
				var metricAttackers = [IkariamCRCEngine.AddCommas(parseInt(attackersLosses*-1*.02)), IkariamCRCEngine.AddCommas(attackersLosses)];
				var metricDefenders = [IkariamCRCEngine.AddCommas(parseInt(defendersLosses*-1*.02)), IkariamCRCEngine.AddCommas(defendersLosses+report.loot.total)];
				for (var m = 0; m < metricTranslations.length; m++) {
					results += formatter.PadString('right', metricTranslations[m], 20, '.', 'ATTACKING');
					results += formatter.PadString('left', metricAttackers[m]+'', 10, '.', 'ATTACKING') + ' - ';
					results += formatter.PadString('right', metricTranslations[m], 20, '.', 'DEFENDING'); 
					results += formatter.PadString('left', metricDefenders[m]+'', 10, '.', 'DEFENDING') + '\n';
				}
				results += formatter.AddSeparator(63) + '\n';
				output += results;

				/* Add Loot */
				if (report.loot.total > 0) {
					results = '\n';
					results += lang.report.loot + ': ';
					var lootTotals = [report.loot.resource["wood"], report.loot.resource["wine"], report.loot.resource["marble"], report.loot.resource["glass"], report.loot.resource["sulfur"]];
					var lootString = [lang.resources.wood, lang.resources.wine, lang.resources.marble, lang.resources.glass, lang.resources.sulfur];
					for (var r = 0; r < lootTotals.length; r++) {
						if (lootTotals[r] > 0 ) {
							var imageString = formatter.AddImage(IkariamCRCEngine.ResourceImages[r]);
							if (imageString == '') imageString = '\n' + lootString[r];
							results += imageString + " " + IkariamCRCEngine.AddCommas(lootTotals[r]) + ' ';
						}
					}
					output += results + '\n';
				}

				/* Add Victor(s) */
				output += '\n' + formatter.AddColor(report.battle.victors, 'VICTOR') + '\n';

				/* Add Homepage Link */
				if (script_version)
				{
					output += "\nCreated using DLR's " + 
						formatter.AddLink("Ikariam CR Converter", "http://board.ikariam.org/index.php?page=Thread&threadID=56204") + ' (' +
						formatter.AddLink('Version ' + script_version, "http://userscripts.org/scripts/show/50784") + ')';
				}
				else
				{
					output += "\nCreated using DLR's " + 
						formatter.AddLink("Ikariam CR Converter [Web Version]", "http://tools.betawarriors.com/ikcrc/");
				}


				/* Add Size, Font, Bold-Styling and Alignment */
				output = formatter.AddSize(output, 85);
				output = formatter.AddFont(output, 'Courier New');
				output = formatter.AddBold(output);
				output = formatter.AddAlignment(output, 'center');

				return output;
			},
			ParseReport:function(report)
			{
				/* Battle Type / Place / Time */
				report.info.type  = $("td.battle")[0].childNodes[2].nodeValue.replace(/^\s*/, '').replace(/\s*$/, ''); 
				report.info.place = $("td.battle")[0].childNodes[3].lastChild.nodeValue.replace(/^\s*/, '').replace(/\s*$/, '');
				report.info.time  = $("td.battle")[0].childNodes[4].nodeValue.replace(/^\s*/, '').replace(/\s*$/, '').replace(/\(/,'').replace(/\)/, '');
	
				/* Attackers / Defenders */
				$("td[colspan*=3]").each(function() {
					if ($(this).html() != '') {
						if (report.info.attackers == null) 
							report.info.attackers = $(this).html().replace(/^\s+/,'').replace(/\s+$/,'').replace(/<br>/g, ', ').replace(/,\s$/, '');
						else 
							report.info.defenders = $(this).html().replace(/^\s+/,'').replace(/\s+$/,'').replace(/<br>/g, ', ').replace(/,\s$/, '');
					}
				});

				/* Remaining Totals / Units - This is the tricky part to parse */
				var total = 0;
				$("tr.rep").each(function() {
					if( $(this).find("td.sum")[0] != null && $(this).find("td.own")[0] != null ) {
						report.battle.attacking_totals[total] = $(this).find("td.own").next().html();
						report.battle.defending_totals[total] = $(this).find("td.own:last").next().html();
						total++;
					} 
					else
					if( $(this).find("td.units")[0] != null ) {
						if( $(this).find("td[colspan*=3]")[0] != null ) {
							IkariamCRCEngine.Engines["v.0.3.1"].AddUnit(report.battle.defenders, $(this).find("td.units").html(), $(this).find("td.own").next());
						}
						else
						if( $(this).find("td[colspan*=4]")[0] != null ) {
							IkariamCRCEngine.Engines["v.0.3.1"].AddUnit(report.battle.attackers, $(this).find("td.units").html(), $(this).find("td.own").next());
						}
						else {
							IkariamCRCEngine.Engines["v.0.3.1"].AddUnit(report.battle.attackers, $(this).find("td.units").html(), $(this).find("td.own").next());
							IkariamCRCEngine.Engines["v.0.3.1"].AddUnit(report.battle.defenders, $(this).find("td.units:last").html(), $(this).find("td.own:last").next());
						} 
					}
					else
					if( $(this).find("td.sum")[0] != null && $(this).find("td.sum").html() == '-')
					{
						report.battle.wall = $(this).find("td:last").html();
						report.battle.walltext = $(this).find("td.sum:last").contents()[1].nodeValue.substr(1);
					}
				});

				/* Victors */
				$("td[colspan*=15]").each(function() { report.battle.victors = $(this).html(); });

				/* Loot, If Available */
				var battleId = -1;
				if (document.location.href.indexOf('combatId=') != -1) {
					battleId = document.location.href.substr(document.location.href.indexOf('combatId=') + 9);
					if (battleId.indexOf('&') != -1) { 
						battleId = battleId.substr(0, battleId.indexOf('&')); 
					} 
				}
				if (battleId != -1 && battleId == GM_getValue(cache_variables.LAST_REPORT, false)) {
					report.loot.resource["wood"]   = GM_getValue(cache_variables.LAST_REPORT + '.wood', false);
					report.loot.resource["wine"]   = GM_getValue(cache_variables.LAST_REPORT + '.wine', false);
					report.loot.resource["marble"] = GM_getValue(cache_variables.LAST_REPORT + '.marble', false);
					report.loot.resource["glass"]  = GM_getValue(cache_variables.LAST_REPORT + '.glass', false);
					report.loot.resource["sulfur"] = GM_getValue(cache_variables.LAST_REPORT + '.sulfur', false);
					report.loot.total = parseInt(report.loot.resource["wood"] + report.loot.resource["wine"] + report.loot.resource["marble"] + report.loot.resource["glass"] + report.loot.resource["sulfur"]);
				}
				else {
					$("td.winner ul.resources li").each(function() {
						var type = $(this)[0].className;
						var amount = parseInt($(this).contents()[1].nodeValue.replace(/,/,''));
						report.loot.resource[type] = amount;
						report.loot.total += amount;
					});
				}
			}
		}
	},
	AddCommas:function(nStr) {
		nStr += '';
		x = nStr.split('.');
		x1 = x[0];
		x2 = x.length > 1 ? '.' + x[1] : '';
		var rgx = /(\d+)(\d{3})/;
		while (rgx.test(x1)) {
			x1 = x1.replace(rgx, '$1' + ',' + '$2');
		}
		return x1 + x2;
	}
}
