function WriteClvlList()
{
	document.write("<select onchange='CalcUpgrades(form)' size='1' name='clevel' id='Select2'>");
	var i = 0;
	for (i=1;i<100;i++)
		document.write("<option value=" + i + ">" + i + "</" + "option>");
	document.write("</" + "select>");
}

function WriteArmorList()
{
	var i = 0;
	for (i=0;i<armor_types.length-1;i++)
		document.write("<input onclick='InitItems(form,0)' type='radio' value=" + armor_types[i][1] + " name='type'>" + armor_types[i][0] + "<br/>");
}

function WriteWeaponList()
{
	var i = 0;
	for (i=0;i<weapon_types.length-1;i++)
		document.write("<input onclick='InitItems(form,1)' type='radio' value=" + weapon_types[i][1] + " name='type'>" + weapon_types[i][0] + "<br/>");
}

function WriteVendorList()
{
	var i = 0;
	for (i=0;i<vendors.length-1;i++)
		document.write("<input onclick='InitVendor(form)' type='radio' value=" + i + " name='vendor'>" + vendors[i][0] + "<br/>");
}

function NMHellDisable(form)
{
	document.getElementById("nm_hell_disable").style.display="block";
	form.diff[1].disabled = "disabled";
	form.diff[2].disabled = "disabled";
	
	// If NM or Hell is selected, switch it to Normal
	if ((form.diff[1].checked == true) || (form.diff[2].checked == true))
	{
		form.diff[0].checked = true;
		form.dlevel.value = form.diff[0].value;
	}
}

function NMHellEnable(form)
{
	document.getElementById("nm_hell_disable").style.display="none";
	form.diff[1].disabled = "";
	form.diff[2].disabled = "";
}

function ShowUpgradeHelp()
{
	document.getElementById("showupgradehelp").style.display="none";
	document.getElementById("upgradehelp").style.display="block";
}

function HideUpgradeHelp()
{
	document.getElementById("showupgradehelp").style.display="block";
	document.getElementById("upgradehelp").style.display="none";
}

function ShowVendorHelp()
{
	document.getElementById("showvendorhelp").style.display="none";
	document.getElementById("vendorhelp").style.display="block";
}

function HideVendorHelp()
{
	document.getElementById("showvendorhelp").style.display="block";
	document.getElementById("vendorhelp").style.display="none";
}

function ShowSpecItemHelp()
{
	document.getElementById("showspecitemhelp").style.display="none";
	document.getElementById("specitemhelp").style.display="block";
}

function HideSpecItemHelp()
{
	document.getElementById("showspecitemhelp").style.display="block";
	document.getElementById("specitemhelp").style.display="none";
}

function CalcUpgrades(form)
{
	var clvl = parseInt(form.clevel.value);
	var ilvl = clvl + 5;
	if (ilvl > 99)
		ilvl = 99;

	var results = "ilvl of shopped items will be " + ilvl + "<br><br>";

	if (clvl <= 19)
	{
		results = results + "Normal and socketed items will be offered for sale. No chance of exceptional or elite upgrades in Nightmare and Hell."
		NMHellDisable(form);
	}
	else
	{
		var nmexc = ((ilvl * 64.0) + 4000.0) / 1000.0;
		var hlexc = ((ilvl * 128.0) + 5000.0) / 1000.0;
		var hlelt = ((ilvl * 16.0) + 1000.0) / 1000.0;
		results = results + "Only magic items will be offered for sale (except in Acts 1 & 2 of Normal difficulty).<br><br>Chance of exceptional upgrade in Nightmare: " + nmexc + "%<br>Chance of exceptional upgrade in Hell: " + hlexc + "%<br>Chance of elite upgrade in Hell: " + hlelt + "%"
		NMHellEnable(form);
	}

	document.getElementById("chances").innerHTML = results;
	UpdateVendors(form);
	UpdateVendorItems(form);
}

function InitItems(form, armor_or_weapon)
{
	var i = 0;
	var type;
	for (i=0;i<form.type.length;i++)
		if (form.type[i].checked == true)
			type = form.type[i].value;
	var entry;

	// clear lists
	while (form.item.length > 0)
	form.item.options[0] = null;

//	document.getElementById("debug").innerHTML = "InitItems() called, armor_or_weapon = " + armor_or_weapon + ", type found to be " + type;
	form.a_or_w.value = armor_or_weapon;

	if (armor_or_weapon == 0)
	{
		for (i=0;i<armor.length-1;i++)
		{
			if (armor[i][1] == type)
			{
				entry = new Option(armor[i][0]);
				form.item.options[form.item.length] = entry;
				form.item.options[form.item.length-1].value = i;
			}
		}
	}
	else
	{
		for (i=0;i<weapons.length-1;i++)
		{
			if (weapons[i][1] == type)
			{
				entry = new Option(weapons[i][0]);
				form.item.options[form.item.length] = entry;
				form.item.options[form.item.length-1].value = i;
			}
		}
	}

	UpdateVendors(form);
}

function InitVendor(form)
{
	var i = 0;

	for (i=0;i<form.vendor.length;i++)
		if (form.vendor[i].checked == true)
		{
			form.vname.value = i;
			form.ilvl_cap.value = ilvl_caps[vendors[i][1]-1];
//			document.getElementById("debug").innerHTML = "InitVendor() called, vendor = " + i + " (" + vendors[i][0] + "), Act " + vendors[i][1] + ", ilvl cap = " + ilvl_caps[vendors[i][1]-1];
		}

	UpdateVendorItems(form);
}

function InitDifficulty(form)
{
	var i = 0;

	for (i=0;i<form.diff.length;i++)
		if (form.diff[i].checked == true)
			form.dlevel.value = form.diff[i].value;

	UpdateVendorItems(form);
}

function iMax(a,b)
{
	if (parseInt(a) > parseInt(b))
		return a;
	else
		return b;
}

// returns array of 4 values:
//   a[0]      : does normal range exist? 1=yes, 0=no
//   a[1]      : are we in it? 1=yes, 0=no, too low, -1=no, too high
//   a[2]      : does magic range exist? 1=yes, 0=no
//   a[3]      : are we in it? 1=yes, 0=no
function BuildRanges(item, v, ilvl, ilvl_cap, upgrade)
{
	var ranges = [0,0,0,0];
	var normmin = 0;
	var magicmin = 0;
	var qlvl = item[2];
	var vendorMax = item[v];
	var vendorMagicMax = item[v+1];
	var vendorMagicLvl = item[v+2];
	
	if (ilvl > ilvl_cap)
		ilvl = ilvl_cap;

	if ((vendorMax > 0) || (vendorMagicMax > 0))
	{
		// To offer normal items, VendorMax must contain a value, and item qlvl must be <=24, and not an upgrade call
		if ((vendorMax > 0) && (qlvl <= 24) && (upgrade == 0))
		{
			normmin = qlvl;
			
			if (ilvl_cap >= normmin)
			{
				ranges[0] = 1;
				if (ilvl < normmin)
					ranges[1] = 0;		// too low
				else
					if (ilvl >= 25)
						ranges[1] = -1;	// too high
					else
						ranges[1] = 1;	// just right!
			}
		}

		// To offer magic items, VendorMagicLevel must not be 100+
		if (vendorMagicLvl < 100)
		{
			if ((vendorMagicMax > 0) && (upgrade == 0))
				// magic items might be offered mixed with normal
				magicmin = iMax(qlvl,vendorMagicLvl);
			else
				// magic items are only offered by themselves at ilvl 25+
				magicmin = iMax(qlvl,iMax(vendorMagicLvl,25));
			
			if (ilvl_cap >= magicmin)
			{
				ranges[2] = 1;
				if (ilvl >= magicmin)
					ranges[3] = 1;
			}
		}
	}

	return ranges;
}

function AddItemToListNormal(list, name, ranges)
{
	var formatted = "";
	
	if ((ranges[0] == 1) && (ranges[2] == 1))
	{
		// Both ranges exist. They must overlap - normal ends at 24, magic only starts later than that if
		// qlvl>24 (in which case there is no normal range) or VendorMagicLvl>24 (only 4 cases, all of which
		// are magic-only). So, either we're in one or both ranges (good), or below the start of the normal
		// range
		if ((ranges[1] == 1) || (ranges[3] == 1))
			formatted = "<em class='ok'>" + name + "</em>";
		else
			formatted = "<em class='low'>" + name + "</em>";
	}
	else
	{
		if (ranges[0] == 1)
		{
			// Normal items only
			if (ranges[1] == 1)
				formatted = "<em class='ok'>" + name + "</em>";
			else
				if (ranges[1] == -1)
					formatted = "<em class='hi'>" + name + "</em>";
				else
					formatted = "<em class='low'>" + name + "</em>";
		}
		else
		{
			// Magic items only
			if (ranges[3] == 1)
				formatted = "<em class='ok'>" + name + "</em>";
			else
				formatted = "<em class='low'>" + name + "</em>";
		}
	}
	
	if (list == "")
		return formatted;
	else
		return list + ", " + formatted;
}

function AddItemToList(list, name, ranges)
{
	var formatted = "";
	
	// Magic items only
	if (ranges[3] == 1)
		formatted = "<em class='ok'>" + name + "</em>";
	else
		formatted = "<em class='low'>" + name + "</em>";
	
	if (list == "")
		return formatted;
	else
		return list + ", " + formatted;
}

function BuildVendorItemListNorm(label, list, vendor, ilvl)
{
	var i = 0;
	var returnlist = "";
	var v = (vendor * 3) + 9;
	var ilvl_cap = ilvl_caps[vendors[vendor][1]-1];
	//var debug = document.getElementById("debug").innerHTML;

	if (ilvl > ilvl_cap)
		ilvl = ilvl_cap;

	for (i=0;i<list.length-1;i++)
	{
		// only pick normal items from list
		if (i == list[i][4])
		{
			//debug = debug + list[i][0] + ": ";
			ranges = BuildRanges(list[i], v, ilvl, ilvl_cap, 0);
			//debug = debug + ranges[0] + "|" + ranges[1] + "|" + ranges[2] + "|" + ranges[3] + "<br>";
			
			// only continue if at least one range exists
			if ((ranges[0] == 1) || (ranges[2] == 1))
			{
				returnlist = AddItemToListNormal(returnlist, list[i][0], ranges);
			}
		}
	}

	//document.getElementById("debug").innerHTML = debug;
	return "<b>" + label + " this vendor can sell:</b><br>" + returnlist;
}

function BuildVendorItemListNM(label, list, vendor, ilvl)
{
	var i = 0;
	var normlist = "";
	var exceplist = "";
	var v = (vendor * 3) + 9;
//	var debug = document.getElementById("debug").innerHTML;

	for (i=0;i<list.length-1;i++)
	{
		// only pick normal items from list
		if (i == list[i][4])
		{
//			debug = debug + list[i][0] + ": ";
			ranges = BuildRanges(list[i], v, ilvl, 99, 0);
//			debug = debug + ranges[0] + "|" + ranges[1] + "|" + ranges[2] + "|" + ranges[3] + "<br>";
			
			// only continue if magic range exists
			if (ranges[2] == 1)
			{
				// Insert NightmareUpgrade into list if there is one, otherwise use base item
				if (list[i][7] != 0)
				{
					normlist = AddItemToList(normlist, list[list[i][7]][0], ranges);
//					debug = debug + AddItemToList(list[list[i][7]][0], ranges);
				}
				else
				{
					normlist = AddItemToList(normlist, list[i][0], ranges);
//					debug = debug + AddItemToList(list[i][0], ranges);
				}
					
				// Insert Exceptional version into list
				exceplist = AddItemToList(exceplist, list[list[i][5]][0], ranges);
//				debug = debug + ", " + AddItemToList(list[list[i][5]][0], ranges) + "<br>";
			}
		}
	}

//	document.getElementById("debug").innerHTML = debug;
	var returnlist = "<b>Normal " + label + " this vendor can sell:</b><br>" + normlist + "<br><br><b>Exceptional " + label + " this vendor can sell:</b><br>" + exceplist;
	return returnlist;
}

function BuildVendorItemListHell(label, list, vendor, ilvl)
{
	var i = 0;
	var normlist = "";
	var exceplist = "";
	var elitelist = "";
	var v = (vendor * 3) + 9;
//	var debug = document.getElementById("debug").innerHTML;

	for (i=0;i<list.length-1;i++)
	{
		// only pick normal items from list
		if (i == list[i][4])
		{
//			debug = debug + list[i][0] + ": ";
			ranges = BuildRanges(list[i], v, ilvl, 99, 0);
//			debug = debug + ranges[0] + "|" + ranges[1] + "|" + ranges[2] + "|" + ranges[3] + "<br>";
			
			// only continue if magic range exists
			if (ranges[2] == 1)
			{
				// Insert HellUpgrade into list if there is one, otherwise use base item and do exceptional & elite upgrades
				if (list[i][8] != 0)
				{
					normlist = AddItemToList(normlist, list[list[i][8]][0], ranges);
//					debug = debug + AddItemToList(list[list[i][8]][0], ranges);
				}
				else
				{
					normlist = AddItemToList(normlist, list[i][0], ranges);
//					debug = debug + AddItemToList(list[i][0], ranges);

					// Insert Exceptional & Elite versions into lists
					exceplist = AddItemToList(exceplist, list[list[i][5]][0], ranges);
					elitelist = AddItemToList(elitelist, list[list[i][6]][0], ranges);
				}
			}
		}
	}

//	document.getElementById("debug").innerHTML = debug;
	var returnlist = "<b>Normal " + label + " this vendor can sell:</b><br>" + normlist + "<br><br><b>Exceptional " + label + " this vendor can sell:</b><br>" + exceplist + "<br><br><b>Elite " + label + " this vendor can sell:</b><br>" + elitelist;
	return returnlist;
}

function UpdateVendorItems(form)
{
	var armorlist = "";
	var weaponlist = "";
	var i = 0;

	if ((form.vname.value == "") || (form.dlevel.value == ""))
	{
		document.getElementById("resultpara2").innerHTML = "";
		return;
	}

	var ilvl = parseInt(form.clevel.value) + 5;
	if (ilvl > 99)
		ilvl = 99;

	if (form.dlevel.value == "Normal")
	{
//		document.getElementById("debug").innerHTML = "";
		armorlist = BuildVendorItemListNorm("Armor", armor, form.vname.value, ilvl);
		weaponlist = BuildVendorItemListNorm("Weapons", weapons, form.vname.value, ilvl);
	}

	if (form.dlevel.value == "Nightmare")
	{
		armorlist = BuildVendorItemListNM("Armor", armor, form.vname.value, ilvl);
		weaponlist = BuildVendorItemListNM("Weapons", weapons, form.vname.value, ilvl);
	}

	if (form.dlevel.value == "Hell")
	{
		armorlist = BuildVendorItemListHell("Armor", armor, form.vname.value, ilvl);
		weaponlist = BuildVendorItemListHell("Weapons", weapons, form.vname.value, ilvl);
	}

	var finaltext = armorlist + "<br><br>" + weaponlist;

	if (finaltext.match("<em class='low'>") == "<em class='low'>")
		finaltext = finaltext + "<br><br>Items listed in <em class='low'>grey</em> are not yet available, character level " + form.clevel.value + " is too low.";

	if (finaltext.match("<em class='hi'>") == "<em class='hi'>")
		finaltext = finaltext + "<br><br>Items listed in <em class='hi'>pink</em> are no longer available, " + vendors[form.vname.value][0] + " only sells non-magical ones to characters below level 20.";

	document.getElementById("resultpara2").innerHTML = finaltext;
}

function UpdateVendors(form)
{
	var i = form.item.value;
	
	if (i == -1)
	{
		document.getElementById("resultpara1").innerHTML = "";
		return;
	}
		
	var returnlist = "";
	var finaltext = "";
	var list;

	var ilvl = parseInt(form.clevel.value) + 5;
	if (ilvl > 99)
		ilvl = 99;

	if (form.a_or_w.value == 0)
		list = armor;
	else
		list = weapons;

	if (list[i][4] == i)
		finaltext = "<b>Vendors who can sell this item:</b><br>" + UpdateVendorsNormItem(list, i, ilvl);
	else
	{
		if (ilvl<25)
			finaltext = "<b>Exceptional and Elite items are only sold when character level is 20+</b>"
		else
			if (list[i][5] == i)
				finaltext = "<b>Vendors who can sell this item:</b><br>" + UpdateVendorsUberItem(list, i, ilvl);
			else
				finaltext = "<b>Vendors who can sell this item:</b><br>" + UpdateVendorsUltraItem(list, i, ilvl);
	}

	if (finaltext == "<b>Vendors who can sell this item:</b><br>")
		finaltext = finaltext + "none";

	if (finaltext.match("<em class='low'>") == "<em class='low'>")
		finaltext = finaltext + "<br><br>Vendors listed in <em class='low'>grey</em> do not yet sell this item, character level " + form.clevel.value + " is too low.";

	if (finaltext.match("<em class='hi'>") == "<em class='hi'>")
		finaltext = finaltext + "<br><br>Vendors listed in <em class='hi'>pink</em> no longer sell this item, they only sell non-magical ones to characters below level 20.";

	document.getElementById("resultpara1").innerHTML = finaltext;
}

function UpdateVendorsNormItem(list, id, ilvl)
{
	var returnlist = "";
	var v = 0;
	var i;
	
	var debug = "";

	for (v=0; v<vendors.length-1; v++)
	{
		ranges = BuildRanges(list[id], (v*3)+9, ilvl, ilvl_caps[vendors[v][1]-1], 0);
//		debug = debug + vendors[v][0] + " " + list[id][(v*3)+9] + "," + list[id][(v*3)+10] + "," + list[id][(v*3)+11] + " " + ranges[0] + " " + ranges[1] + " " + ranges[2] + " " + ranges[3] + "<br>"

		// only continue if at least one range exists
		if ((ranges[0] == 1) || (ranges[2] == 1))
		{
			returnlist = AddItemToListNormal(returnlist, vendors[v][0] + " (Normal)", ranges);
		}
	}

	// workaround for non-upgradable items having "0" (id of Hand Axe) for their upgrade index
	if (id > 0)
	{
		// NightmareUpgrades
		for (i=0; i<list.length-1; i++)
		{
			// if item is normal and it's NightmareUpgrade is our desired id..
			if ((list[i][4] == i) && (list[i][7] == id))
			{
				debug = debug + list[i][0] + " ";
				for (v=0; v<vendors.length-1; v++)
				{
					ranges = BuildRanges(list[i], (v*3)+9, ilvl, 99, 1);

					// only continue if at least one range exists
					if ((ranges[0] == 1) || (ranges[2] == 1))
					{
						returnlist = AddItemToList(returnlist, vendors[v][0] + " (Nightmare)", ranges);
					}
				}
			}
		}
		document.getElementById("debug").innerHTML = debug;
		
		// HellUpgrades
		for (i=0; i<list.length-1; i++)
		{
			// if item is normal and it's HellUpgrade is our desired id..
			if ((list[i][4] == i) && (list[i][8] == id))
			{
				for (v=0; v<vendors.length-1; v++)
				{
					ranges = BuildRanges(list[i], (v*3)+9, ilvl, 99, 1);

					// only continue if at least one range exists
					if ((ranges[0] == 1) || (ranges[2] == 1))
					{
						returnlist = AddItemToList(returnlist, vendors[v][0] + " (Hell)", ranges);
					}
				}
			}
		}
	}
		
	return returnlist;
}

function UpdateVendorsUberItem(list, id, ilvl)
{
	var returnlist = "";
	var v = 0;
	var normitem = list[list[id][4]];

//	var debug = "";
//	debug = debug + "UpdateVendorsUberItem() called, item=" + list[id][0];
//	debug = debug + ", normitem=" + normitem[0] + "<br>";

	for (v=0; v<vendors.length-1;v++)
	{
		ranges = BuildRanges(normitem, (v*3)+9, ilvl, 99, 1);
//		debug = debug + vendors[v][0] + " " + normitem[(v*3)+9] + "," + normitem[(v*3)+10] + "," + normitem[(v*3)+11] + " " + ranges[0] + " " + ranges[1] + " " + ranges[2] + " " + ranges[3] + "<br>"

		// only continue if at least one range exists
		if ((ranges[0] == 1) || (ranges[2] == 1))
		{
			returnlist = AddItemToList(returnlist, vendors[v][0] + " (Nightmare)", ranges);
			
			// Hell vendors only sell uber/ultra upgrades to items with no HellUpgrade
			if (normitem[8] == 0)
				returnlist = AddItemToList(returnlist, vendors[v][0] + " (Hell)", ranges);
		}
	}

//	document.getElementById("debug").innerHTML = debug;

	return returnlist;
}

function UpdateVendorsUltraItem(list, id, ilvl)
{
	var returnlist = "";
	var v = 0;
	var normitem = list[list[id][4]];

	// Hell vendors only sell ultra upgrades to items with no HellUpgrade
	if (normitem[8] == 0)
	{
//		var debug = "";
//		debug = debug + "UpdateVendorsUberItem() called, item=" + list[id][0];
//		debug = debug + ", normitem=" + normitem[0] + "<br>";

		for (v=0; v<vendors.length-1;v++)
		{
			ranges = BuildRanges(normitem, (v*3)+9, ilvl, 99, 1);
//			debug = debug + vendors[v][0] + " " + normitem[(v*3)+9] + "," + normitem[(v*3)+10] + "," + normitem[(v*3)+11] + " " + ranges[0] + " " + ranges[1] + " " + ranges[2] + " " + ranges[3] + "<br>"

			// only continue if at least one range exists
			if ((ranges[0] == 1) || (ranges[2] == 1))
			{
				returnlist = AddItemToList(returnlist, vendors[v][0] + " (Hell)", ranges);
			}
		}

//		document.getElementById("debug").innerHTML = debug;
	}
	
	return returnlist;
}
