var MAX_LEVEL = 85;

var DEBUGMODE = false;
// var DEBUGMODE = true;


function WriteOptions(SlotType)
{
	// DebugPrint ("SlotType = " + SlotType);
	for (var i=0; i < GemList.length; i++)
	{
		if ( ! ((SlotType == 10) && (GemList[i][1] != 10)) )
		{
			document.write("<option value=" + i + ">" + GemList[i][0]);
			if (GemList[i][23] != "")
			{
				document.write(" (" + GemList[i][23] + ")");
			}
			document.writeln("</option>");
		}
	} // for
} // WriteOptions()


// return the value of the radio button that is checked
// return an empty string if none are checked, or
// there are no radio buttons
// stolen from http://www.somacon.com/p143.php
function getCheckedValue(radioObj) {
	if(!radioObj)
		return "";
	var radioLength = radioObj.length;
	if(radioLength == undefined)
		if(radioObj.checked)
			return radioObj.value;
		else
			return "";
	for(var i = 0; i < radioLength; i++) {
		if(radioObj[i].checked) {
			return radioObj[i].value;
		}
	}
	return "";
}


function ShowLayer(LayerName)
{
	var theLayer;
	if (document.getElementById)
	{
		// this is the way the standards work
		theLayer = document.getElementById(LayerName).style;
	}
	else if (document.all)
	{
		// this is the way old msie versions work
		theLayer = document.all[LayerName].style;
	}
	else if (document.layers)
	{
		// this is the way nn4 works
		theLayer = document.layers[LayerName].style;
	}
	else
	{
		// This browser uses a system we don't understand.  Just exit.
		return;
	}
	theLayer.display = "inline";
} // ShowLayer()

function HideLayer(LayerName)
{
	if (document.getElementById)
	{
		// this is the way the standards work
		theLayer = document.getElementById(LayerName).style;
	}
	else if (document.all)
	{
		// this is the way old msie versions work
		theLayer = document.all[LayerName].style;
	}
	else if (document.layers)
	{
		// this is the way nn4 works
		theLayer = document.layers[LayerName].style;
	}
	else
	{
		// This browser uses a system we don't understand.  Just exit.
		return;
	}
	theLayer.display = "none";
} // HideLayer()




function UpdateGemCount(NumGems)
{
	if (NumGems == 3)
	{
		ShowLayer("Gem2");
		ShowLayer("Gem3");
	}
	else if (NumGems == 2)
	{
		ShowLayer("Gem2");
		HideLayer("Gem3");
	}
	else
	{
		HideLayer("Gem2");
		HideLayer("Gem3");
	}

	UpdateDisplay();
} // UpdateGemCount()




function DebugPrint(stuff)
{
	if (!DEBUGMODE)
	{
		return;
	}
	var currentTime = new Date();
	var hours = currentTime.getHours();
	var minutes = currentTime.getMinutes();
	var seconds = currentTime.getSeconds();
	if (hours < 10)
	{
		hours = " " + hours;
	} 
	if (minutes < 10)
	{
		minutes = "0" + minutes;
	}
	if (seconds < 10)
	{
		seconds = "0" + seconds;
	}
	var now = hours + ":" + minutes + ":" + seconds;
	ShowLayer("debug");
	document.getElementById("debug").value += now + ": " + stuff + "\n";
}








function UpdateDisplay()
{
	// Get a pointer to the form.
	var theForm = document.GemForm;
	//DebugPrint (theForm.name);

	// Get pointers to the gem choices.  These will be validated later.
	var t11 = parseInt(theForm.T11.value);
	var t10_1 = parseInt(theForm.T10_1.value);
	var t10_2 = parseInt(theForm.T10_2.value);

	// Validate the player level.  If it's blank, zero, or an invalid int, assume it's the max level.
	var CharLevel = parseInt(theForm.CharLevel.value);
	if (isNaN(CharLevel))
	{
		CharLevel = MAX_LEVEL;
	}
	else if (CharLevel < 1 || CharLevel > MAX_LEVEL)
	{
		CharLevel = MAX_LEVEL;
	}


	// A variable to hold the final item name.  This is constructed in parts as we go through.
	// Start with the base metal name.
	var Name = theForm.Metal.options[theForm.Metal.options.selectedIndex].value;

	// Get the appropriate mods for the base metal.
	var Mods = MetalList[Name];

	// Initialize the rec level.  This will be increased later for duo and trio items.
	var RecLevel = Mods[REC_LEVEL];

	DebugPrint("At 1, Mods = " + Mods + ", RecLevel = " + RecLevel);



	// Set the slots.  This also affects the name.
	var Slots = getCheckedValue(theForm.Style);

	var HaveError = false;

	switch (parseInt(Slots))
	{
	case 1:
		HideLayer("Slot2TypeText");
		HideLayer("Slot3TypeText");
		Name += " Solo ";
		break;
	case 2:
		if ((t10_1 == t11) && (t11 != 0))
		{
			ShowLayer("T10_1_Error");
			HaveError = true;
		}
		else
		{
			HideLayer("T10_1_Error");
		}

		ShowLayer("Slot2TypeText");
		HideLayer("Slot3TypeText");
		Name += " Duo ";
		if (RecLevel > 1)
		{
			RecLevel += 3;
		}
		break;
	case 3:
		if ((t10_1 == t11) && (t10_1 != 0))
		{
			ShowLayer("T10_1_Error");
			HaveError = true;
		}
		else
		{
			HideLayer("T10_1_Error");
		}


		if ((t10_2 == t11 || t10_2 == t10_1) && (t10_2 != 0))
		{
			ShowLayer("T10_2_Error");
			HaveError = true;
		}
		else
		{
			HideLayer("T10_2_Error");
		}

		ShowLayer("Slot2TypeText");
		ShowLayer("Slot3TypeText");
		Name += " Trio ";
		if (RecLevel > 1)
		{
			RecLevel += 5;
		}
		break;
	} // switch

	if (HaveError)
	{
		// There was a problem with duplicate gems.  Stop processing until it's fixed.
		return;
	}


	// Calculate the difference between the recommended level and the actual level.
	var LevelDiff = RecLevel - CharLevel;
	if (LevelDiff < 0)
	{
		// Character is over the rec level
		LevelDiff = 0;
	}
	else if (LevelDiff > 10)
	{
		// Max of ten levels
		LevelDiff = 10;
	}
	// Note the LevelDiff is now guaranteed to be between 0 and 10 inclusive

	// Now, determine the gem modifier based on level difference 
	// (what Ngreth calls the "internal" mod) and metal type
	// From Ngreth's post:
	// INT (Metal * Internal / 100)
	// Based on testing, it turns out that the formula is slightly incomplete.  
	// The full formula for the hp returned by the script is:
	// INT (Metal * Internal / 100 * Base hp / 100)
	// The extra divide by 100 is because the first part of the script returns a value in the 
	// range of 0 to 100, instead of 0 to 1.
	// We don't multiply by the HP here, but the rest of the factors together comprise the "gem modifier"

	var GemModifier = Mods[METAL_POWER] * InternalRecLevelMod[LevelDiff] / 100 / 100;
		// This produces a number between 0 and 1
	
	
	DebugPrint ("At 2, Mods[METAL_POWER] = " + Mods[METAL_POWER] + ", InternalRecLevelMod[LevelDiff] = " + InternalRecLevelMod[LevelDiff]
			+ "\n      RecLevel = " + RecLevel + ", LevelDiff = " + LevelDiff + ", GemModifier = " + GemModifier);
	
	
	
	// An array to hold the sum of the stats.  Note that values are auto-initialized to undefined, which is bad.
	var StatTotals = [];
	for (var i = 0; i <= LastStat; i++)
	{
		// Initialize to zero.
		StatTotals[i] = 0;
	}

	// Clear the effect text.  We'll fill it in during the next case block.
	document.getElementById("EffectText").innerHTML = "";

	// Calculate the stats and effects.  
	// Note the lack of break statements.  This allows execution to fall through for subsequent gems
	var thisGem;
	var CalcHolder;


	for (var SlotNumber = parseInt(Slots); SlotNumber > 0; SlotNumber--)
	{
		switch (SlotNumber)
		{
		case 3:
			thisGem = GemList[parseInt(theForm.T10_2.value)];
			break;
		case 2:
			thisGem = GemList[parseInt(theForm.T10_1.value)];
			break;
		case 1:
			thisGem = GemList[parseInt(theForm.T11.value)];
			break;
		}

		CalcHolder = thisGem[2];
		if (undefined == CalcHolder)
		{
			CalcHolder = CALC_STATS;
		}
		if (CalcHolder != CALC_EFFECT)
		{
			// It's a stat or calc aug
			for (var i = FirstStat; i <= LastStat; i++)
			{
				if (thisGem[i] != undefined)
				{
					// Determine the gem power, adjusted by metal and level diff.
					DebugPrint ("At 3"
						+ ", Slot = " + SlotNumber 
						+ ", i=" + i 
						+ ", Stat = " + Labels[i]
						+ ", Value = " + thisGem[i] 
						+ ", Calc = " + CalcHolder 
						+ ", StatTotals[i] = " + StatTotals[i]);
					StatTotals[i] += Math.floor(thisGem[i] * GemModifier);
					DebugPrint ("          new StatTotals[i] = " + StatTotals[i]);
				}
			}
		}
		else
		{
			// It's an effect aug
			if (document.getElementById("EffectText").innerHTML != "")
			{
				document.getElementById("EffectText").innerHTML += "<br />";
			}
			document.getElementById("EffectText").innerHTML += "Effect: " + thisGem[22];
		}
		if (thisGem[0] != "None")
		{
			document.getElementById("Slot" + SlotNumber + "Contents").innerHTML = thisGem[23] + " Cut " + thisGem[0];
		}
		else
		{
			document.getElementById("Slot" + SlotNumber + "Contents").innerHTML = "empty";
		}
	} // for




	// Apply the recommended level.  Note that it only applies if the player level is under the rec level.
	if (RecLevel > CharLevel)
	{
		for (var i = FirstStat; i <= LastStat; i++)
		{
			if (StatTotals[i] != 0)
			{
				DebugPrint ("At 4, before rec level, " + Labels[i] + " = " + StatTotals[i]);
				DebugPrint ("      without rounding, " + Labels[i] + " = " + StatTotals[i] * CharLevel / RecLevel);
				DebugPrint ("      normal  rounding, " + Labels[i] + " = " + Math.round(StatTotals[i] * CharLevel / RecLevel));
				DebugPrint ("      EQ-type rounding, " + Labels[i] + " = " + EQRound(StatTotals[i] * CharLevel / RecLevel));
				StatTotals[i] = Math.max(EQRound(StatTotals[i] * CharLevel / RecLevel), 1);
					// Note that rec level rounding always provides at least 1 of each rounded stat.
					// @TODO: this will probably bug out if JC ever gets negative stats.
				DebugPrint ("       after rec level, " + Labels[i] + " = " + StatTotals[i]);
			}
		}
	}

	// Display the stats
	for (var i = FirstStat; i <= LastStat; i++)
	{
		var ElementID = (Labels[i]).replace(" ", "_");
		if ((StatTotals[i] == 0) || (StatTotals[i] == undefined))
		{
			// Remove that display
			document.getElementById(ElementID + "Text").innerHTML = "";
		}
		else
		{
			// show that display
			document.getElementById(ElementID + "Text").innerHTML = Labels[i] + ": <span id=\"" + ElementID + "\">" + StatTotals[i] + "</span> ";
		}
	}

	// Display the recommended level, if appropriate.
	if (RecLevel > 0)
	{
		document.getElementById("RecLevel").innerHTML = "Recommended level of " + RecLevel + ".<br />";
	}
	else
	{
		// No rec level, clear the display
		document.getElementById("RecLevel").innerHTML = "";
	}


	// Set the name
	switch (theForm.ItemSlot.value)
	{
	case "FINGER":
		Name += "Ring";
		break;
	case "EAR":
		Name += "Earring";
		break;
	case "FACE":
		Name += "Veil";
		break;
	case "NECK":
		Name += "Pendant";
		break;
	case "WRIST":
		Name += "Bracelet";
		break;
	}
	document.getElementById("Name").innerHTML = Name;

	// Set the slot too.
	document.getElementById("Slot").innerHTML = theForm.ItemSlot.value;

}


// Turns out there's a bug in EQ rounding for recommended levels.  If the stat comes out to x.5, EQ rounds *down* instead of up.
// So, a function to duplicate this.
function EQRound( num )
{
	if (num - Math.floor(num) == 0.5)
		return Math.floor(num);
	else
		return Math.round(num);
}


function PrintGemStats()
{

	for (var Gem = 1; Gem < GemList.length; Gem++)
	{
		// Print the gem name and cut
		document.write(GemList[Gem][0] + "\t\t" + GemList[Gem][23] + "\t");
		
		var AnyStat = false; // true means we've displayed a stat for this gem.


		// Loop for each metal type.
		// As of this writing, Dwerium = 100%, but that could change in the future.

		for (MetalType in MetalList)
		{
			// Get the appropriate mods for the base metal.
			var Mods = MetalList[MetalType];

			// Get the gem modifier.  Note that the level factor is hard-coded to 100%
			var GemModifier = Mods[METAL_POWER] * (100) / 100 / 100;
			// This produces a number between 0 and 1
		
			//document.writeln("xx" + GemModifier + "xx");

			// Display the stats
			for (var Stat = FirstStat; Stat <= LastStat; Stat++)
			{
				if (GemList[Gem][2] == CALC_EFFECT)
				{
					// It's an effect aug
					document.write("Effect: " + GemList[Gem][22]);
					break; // no point in looping for all the stats.
				}
				var ElementID = (Labels[Stat]).replace(" ", "_");
				if ((GemList[Gem][Stat] == 0) || (GemList[Gem][Stat] == undefined))
				{
					// Null stat.  Do nothing.
				}
				else
				{
					// display that stat
					if (AnyStat)
					{
						document.write(" ");
					}
					else
					{
						AnyStat = true;
					}
					document.write(Labels[Stat] + ": " + Math.floor(GemList[Gem][Stat] * GemModifier));

				}
			} // for stat
			
			// End the cell
			document.write ("\t");

		} // for metal

		// End the line
		//document.writeln ("<br />");
		document.writeln ("");

	} // for gem
	


} // PrintGemStats()


