//
// This is the javascript for the mychars.php page at www.thegreyguard.net
//
// *** Written by Tilda ***
// 

var char_max_level = 65;	// current max level for characters
var number_of_races = 4;	// current number of races
var number_of_classes = 9;	// current number of classes
var number_of_vocations = 7;	// current number of vocations

// As much as I hate doing this, we have to hardcode the game info here as we can't/won't call the site database from the webclient 
// (Might want to re-write this to build the arrays from the database using PHP to make the javascript)
allowed_races = new Array("select race","Dwarf","Elf","Hobbit","Human");
allowed_classes = new Array("select class","Burglar","Captain","Champion","Guardian","Hunter","Loremaster","Minstrel","Runekeeper","Warden");
allowed_race_classes = new Array(4);
allowed_race_classes[0] = new Array(1,1,1,1,1,1,1,1,1,1); // No race selected: all classes allowed
allowed_race_classes[1] = new Array(1,0,0,1,1,1,0,1,1,0); // Dwarf
allowed_race_classes[2] = new Array(1,0,0,1,1,1,1,1,1,1); // Elf
allowed_race_classes[3] = new Array(1,1,0,0,1,1,0,1,0,1); // Hobbit
allowed_race_classes[4] = new Array(1,1,1,1,1,1,1,1,0,1); // Human

// For validating the crafting proficiencies:
var crafts_per_vocation = 3; // Current number of crafts per vocation
var number_of_prof_tiers = 6; // Current number of crafting tiers
max_craft_proficiency = new Array(2);
max_craft_proficiency[1] = new Array(0, 200, 280, 360, 440, 520, 600); // Max proficiencies for pt 1 of each tier
max_craft_proficiency[2] = new Array(0, 400, 560, 720, 880, 1040, 1200); // Max proficiencies for pt 2 of each tier

var number_of_profession = 10;
ingame_professions = new Array('None','Cooking','Farming','Foresting','Jewellery','Metalsmithy','Prospecting','Scholaring','Tailoring','Weaponsmithy','Woodworking');
ingame_vocations = new Array(7); // Of these the names are not used. They are put in for readability
ingame_vocations[0] = new Array('No vocation',0,0,0);
ingame_vocations[1] = new Array('Armourer',5,6,8);
ingame_vocations[2] = new Array('Armsman',6,9,10);
ingame_vocations[3] = new Array('Explorer',3,6,8);
ingame_vocations[4] = new Array('Historian',2,7,9);
ingame_vocations[5] = new Array('Tinker',1,4,6);
ingame_vocations[6] = new Array('Woodsman',2,3,10);
ingame_vocations[7] = new Array('Yeoman',1,2,8);


// === Input help scripts ===


function removeAllOptions(selectbox) {
	var i;
	for ( i = selectbox.options.length-1 ; i >= 0 ; i-- )
	{
		selectbox.remove(i);
	}
}

function addOption(selectbox,text,value) {
	var optn = document.createElement("OPTION");
	optn.text = text;
	optn.value = value;
	selectbox.options.add(optn);
}


// == Input help for main character info ==


function raceClass(valfield,   // element to be validated
									 infofield,  // id of element to receive info/error msg
									 message) {  // message to set if all is well (all only used on validating at end)
	var race_selected = document.main_form.char_race_id.value;
	var class_selected = document.main_form.char_class_id.value;
	var class_selected_index = 0;
	removeAllOptions(document.main_form.char_class_id);    // Remove all the options to start buildig a new list of them
	var i;
	for ( i = 0 ; i <= number_of_classes ; i++ ) {
		if ( allowed_race_classes[race_selected][i] == 1 ) {
			addOption(document.main_form.char_class_id,allowed_classes[i],i);
			if ( document.main_form.char_class_id.options[document.main_form.char_class_id.options.length-1].value == class_selected ) {
				class_selected_index = document.main_form.char_class_id.options.length-1;
			}
		}
	}
	document.main_form.char_class_id.options[class_selected_index].selected = true;    // Select the former selected class (or default to none if not allowed)
	validateRace(valfield,infofield,message);
}

function classRace(valfield,   // element to be validated
									 infofield,  // id of element to receive info/error msg
									 message) {  // message to set if all is well (all only used on validating at end)
	var class_selected = document.main_form.char_class_id.value;
	var race_selected = document.main_form.char_race_id.value;
	var race_selected_index = 0;
	removeAllOptions(document.main_form.char_race_id);    // Remove all the options to start buildig a new list of them
	var i;
	for ( i = 0 ; i <= number_of_races ; i++ ) {
		if ( allowed_race_classes[i][class_selected] == 1 ) {
			addOption(document.main_form.char_race_id,allowed_races[i],i);
			if ( document.main_form.char_race_id.options[document.main_form.char_race_id.options.length-1].value == race_selected ) {
				race_selected_index = document.main_form.char_race_id.options.length-1;
			}
		}
	}
	document.main_form.char_race_id.options[race_selected_index].selected = true;    // Select the former selected race (or default to none if not allowed)
	validateClass(valfield,infofield,message);
}

function changeVocation(valfield) {
	// Wishlist: preserve proficiencies when a profession is in old and new vocation. Too much work for initial version though
	var disable_fields;
	var tfld = trim(valfield.value); // The vocation id (trim not needed here, but kept in for consistency with other formulae to get tfld)
	// Write new profession names in the fields on the form and clear the checkboxes
	for ( i = 1 ; i <= crafts_per_vocation ; i++ ) { // Each of the professions
		document.getElementById('prof'+i+'_name').value = ingame_professions[ingame_vocations[tfld][i]]; // Write new profession names in the fields on the form
		document.getElementById('prof'+i+'_public').checked = false; // Clear the checkboxes
		disable_fields = ( ingame_vocations[tfld][i] == '0' ? true : false ); // To enable/disable fields for the profession
		document.getElementById('prof'+i+'_public').disabled = disable_fields; // Enable/disable the checkboxes
		// Zero the crafting proficiencies
		for ( j = 1 ; j <= number_of_prof_tiers ; j++ ) { // Each of the tiers
			for ( k = 1 ; k <= 2 ; k++ ) { // Each of the parts in a tier
				document.getElementById(makeCraftFieldname(i,j,k)).value = 0;
				document.getElementById(makeCraftFieldname(i,j,k)).disabled = disable_fields; // Enable/disable the proficiencies
			}
		}
	}
	return true;
}

function hideShow(theDiv) {
//	craftingTable.style.display = 'inline';
	if ( document.getElementById(String(theDiv)).style.display=='none' ) {
		document.getElementById(String(theDiv)).style.display = 'inline';
	} else {
		document.getElementById(String(theDiv)).style.display = 'none';
	}
	return;
}


// === Validation scripts ===


// --------------------------------------------
//             validateAll
// Validate character's name
// Returns true if OK 
// --------------------------------------------

function validateAll() {
	var errs=0;
	if ( !validateName(document.main_form.char_name,'inf_char_name', 'Required')) errs += 1;
	if ( !validateLastname(document.main_form.char_lastname, 'inf_char_lastname', '')) errs += 1;
	if ( !validateGender(document.main_form.char_gender, 'inf_char_gender', 'Required')) errs += 1;
	if ( !validateRace(document.main_form.char_race_id, 'inf_char_race_id', 'Required')) errs += 1;
	if ( !validateClass(document.main_form.char_class_id, 'inf_char_class_id', 'Required')) errs += 1;
	if ( !validateLevel(document.main_form.char_level, 'inf_char_level', 'Required: 1-'+char_max_level)) errs += 1;
	if ( !( document.main_form.char_vocation_id.value >= 0 && document.main_form.char_vocation_id.value <= number_of_vocations )) errs += 1;
	// Validations of the crafting proficiencies
	for ( i = 0 ; j <= crafts_per_vocation ; i++ ) {
		for ( j = 1 ; j <= number_of_prof_tiers ; j++ ) {
			for ( k = 1 ; k <= 2 ; k++ ) {
				if ( !validateCraft(i,j,k,'inf_t'+j,'/'+max_craft_proficiency[1][j]+';/'+max_craft_proficiency[2][j])) errs += 1;
			}
		}
	}
	return (errs==0);
}


// ----------------------------------------------------------------------
// Javascript form validation routines.
// Author of basic scripts: Stephen Poley
// Edited to use on the TGG.net website by: Tilda Styscraper
// ----------------------------------------------------------------------

var nbsp = 160;		// non-breaking space char
var emptyString = /^\s*$/ ;
var global_valfield;	// retain valfield for timer thread

// --------------------------------------------
//                  trim
// Trim leading/trailing whitespace off string
// --------------------------------------------

function trim(str) {
	return str.replace(/^\s+|\s+$/g, '');
}


// --------------------------------------------
//                  setfocus
// Delayed focus setting to get around IE bug
// --------------------------------------------

function setFocusDelayed() {
	global_valfield.focus();
}

function setfocus(valfield) {
	// save valfield in global variable so value retained when routine exits
	global_valfield = valfield;
	setTimeout( 'setFocusDelayed()', 100 );
}


// --------------------------------------------
//                  msg
// Display warn/error message in HTML element.
// commonCheck routine must have previously been called
// --------------------------------------------

function msg(fld,       // id of element to display message in
						 msgtype,   // class to give element ("warn" or "error")
						 message) { // string to display
	// setting an empty string can give problems if later set to a 
	// non-empty string, so ensure a space present. (For Mozilla and Opera one could 
	// simply use a space, but IE demands something more, like a non-breaking space.)
	var dispmessage;
	if (emptyString.test(message)) 
		dispmessage = String.fromCharCode(nbsp);    
	else  
		dispmessage = message;

	var elem = document.getElementById(fld);
	elem.firstChild.nodeValue = dispmessage;  
	
	elem.className = msgtype;   // set the CSS class to adjust appearance of message
}


// == Validations for main character info ==


// --------------------------------------------
//             validateName
// Validate character's name
// Returns true if OK 
// --------------------------------------------

function validateName(valfield,    // element to be validated
											 infofield,  // id of element to receive info/error msg
											 message) {  // message to set if all is well
	var tfld = trim(valfield.value);
	var name_mask = /^[A-Z][a-z]+$/
	if (!name_mask.test(tfld))
	{
		msg (infofield, "mychars_error", "Not a valid name");
		setfocus(valfield);
		return false;
	}
	
	msg (infofield, "mychars_warn", message);
	return true;
}

// --------------------------------------------
//             validateLastname
// Validate character's lastname
// Returns true if OK 
// --------------------------------------------

function validateLastname(valfield, // element to be validated
											 infofield,   // id of element to receive info/error msg
											 message) {   // message to set if all is well
	var tfld = trim(valfield.value);
	var lastname_mask = /^$|^[A-Z][A-Za-z]+$/
	if (!lastname_mask.test(tfld))
	{
		msg (infofield, "mychars_error", "Not a valid last name");
		setfocus(valfield);
		return false;
	}
	
	msg (infofield, "mychars_warn", message);
	return true;
}

// --------------------------------------------
//             validateGender
// Validate character's gender
// Returns true if OK 
// --------------------------------------------

function validateGender(valfield,  // element to be validated
											 infofield,  // id of element to receive info/error msg
											 message) {  // message to set if all is well
	var tfld = trim(valfield.value);
	var gender_mask = /^(F|M)$/
	if (!gender_mask.test(tfld)) {
		msg (infofield, "mychars_error", message);
		setfocus(valfield);
		return false;
	}
	
	msg (infofield, "mychars_warn", message);
	return true;
}

// --------------------------------------------
//             validateRace
// Validate character's race
// Returns true if OK 
// --------------------------------------------

function validateRace(valfield,   // element to be validated
											 infofield, // id of element to receive info/error msg
											 message) { // message to set if all is well
	var tfld = trim(valfield.value);
	var race_mask = /^[0-9]{1}$/
	if (!race_mask.test(tfld)) {
		msg (infofield, "mychars_error", message);
		setfocus(valfield);
		return false;
	}
	
	if (tfld<1 || tfld>number_of_races) {
		msg (infofield, "mychars_error", message);
		setfocus(valfield);
		return false;
	}
	
	msg (infofield, "mychars_warn", message);
	return true;
}


// --------------------------------------------
//             validateClass
// Validate character's class
// Returns true if OK 
// --------------------------------------------

function validateClass(valfield,   // element to be validated
											 infofield,  // id of element to receive info/error msg
											 message) {  // message to set if all is well
	var tfld = trim(valfield.value);
	var class_mask = /^[0-9]{1}$/
	if (!class_mask.test(tfld)) {
		msg (infofield, "mychars_error", message);
		setfocus(valfield);
		return false;
	}
	
	if (tfld<1 || tfld>number_of_classes) {
		msg (infofield, "mychars_error", message);
		setfocus(valfield);
		return false;
	}
	
	msg (infofield, "mychars_warn", message);
	return true;
}


// --------------------------------------------
//             validateLevel
// Validate character's level
// Returns true if OK 
// --------------------------------------------

function validateLevel(valfield,   // element to be validated
											 infofield,  // id of element to receive info/error msg
											 message) {  // message to set if all is well
	var tfld = trim(valfield.value);
	var level_mask = /^[0-9]{1,2}$/
	if (!level_mask.test(tfld)) {
		msg (infofield, "mychars_error", message);
		setfocus(valfield);
		return false;
	}
	
	if (tfld<1 || tfld>char_max_level) {
		msg (infofield, "mychars_error", message);
		setfocus(valfield);
		return false;
	}
	
	msg (infofield, "mychars_warn", message);
	return true;
}


// == Validations for crafting info (mycraft)


// --------------------------------------------
//             validateCraft
// Validate character's craft proficiency
// (included some input help)
// Returns true if OK 
// --------------------------------------------

function makeCraftFieldname(craftnumber,
														tiernumber,
														partnumber) {
	return String('c'+craftnumber+'t'+tiernumber+'p'+partnumber);
}

function validateCraft(check_craft,
											 check_tier,
											 check_part,
											 infofield,  // id of element to receive info/error msg
											 message) {  // message to set if all is well
	var valfield = document.getElementById(makeCraftFieldname(check_craft,check_tier,check_part));
	var tfld = trim(valfield.value);
	var proficiency_mask = /^[0-9]{1,4}$/
	msg (infofield, "mychars_warn", message);
	if (!proficiency_mask.test(tfld)) {
		msg (infofield, "mychars_error", message);
		setfocus(valfield);
		return false;
	} 
	
	// Check part 2 first
	
	if ( check_part == 2 ) {
		valfield.value = Math.min(valfield.value,max_craft_proficiency[2][check_tier]); // If > max, then max
		
		// This tier is (made) correct. Draw conclusions on other tiers:
		
		// Check for completed lower tiers/parts:
		if ( tfld > 0 ) { // Can only be if lower tier is maxed and pt 1 is maxed (and this is not tier 0)
			if ( check_tier > 1 ) { // Make lower tier part 2 max, if there is a lower tier
				document.getElementById(makeCraftFieldname(check_craft,check_tier-1,2)).value = max_craft_proficiency[2][check_tier-1];
				validateCraft(check_craft,check_tier-1,2,'inf_t'+(check_tier-1),'/'+max_craft_proficiency[1][check_tier-1]+'; /'+max_craft_proficiency[2][check_tier-1]);
			}
			// Make this tier part 1 max
			document.getElementById(makeCraftFieldname(check_craft,check_tier,1)).value = max_craft_proficiency[1][check_tier];
			validateCraft(check_craft,check_tier,1,'inf_t'+(check_tier),'/'+max_craft_proficiency[1][check_tier]+'; /'+max_craft_proficiency[2][check_tier]);
		}
		// Check for uninitiated higher tier
		if ( tfld < max_craft_proficiency[2][check_tier] ) { // This tier not fully learned, so next tier (if any) = 0
			if ( check_tier < number_of_prof_tiers ) { // Make higher tier part 2 equal to 0, if there is a higher tier
				document.getElementById(makeCraftFieldname(check_craft,check_tier+1,2)).value = 0;
				validateCraft(check_craft,check_tier+1,2,'inf_t'+(check_tier+1),'/'+max_craft_proficiency[1][check_tier+1]+'; /'+max_craft_proficiency[2][check_tier+1]);
			}
		}
		return true;
	}
	
	// Part 2 done, just part 1 to go
	
	if ( check_part == 1 ) {
		valfield.value = Math.min(valfield.value,max_craft_proficiency[1][check_tier]); // If > max, then max
		
		// This tier is (made) correct. Draw conclusions on other tiers:
		
		// Check for completed lower tiers/parts:
		if ( tfld > 0 ) { // Can only be if lower tier pt 1 is maxed (and this is not tier 0)
			if ( check_tier > 1 ) { // Make lower tier pt 1 max, if there is a lower tier
				document.getElementById(makeCraftFieldname(check_craft,check_tier-1,1)).value = max_craft_proficiency[1][check_tier-1];
				validateCraft(check_craft,check_tier-1,1,'inf_t'+(check_tier-1),'/'+max_craft_proficiency[1][check_tier-1]+'; /'+max_craft_proficiency[2][check_tier-1]);
			}
		}
		// Check for uninitiated higher tier
		if ( tfld < max_craft_proficiency[1][check_tier] ) { // This tier pt 1 not fully learned, so part 2 and next tier (if any) = 0
			document.getElementById(makeCraftFieldname(check_craft,check_tier,2)).value = 0;
			validateCraft(check_craft,check_tier,2,'inf_t'+(check_tier),'/'+max_craft_proficiency[1][check_tier]+'; /'+max_craft_proficiency[2][check_tier]);
			if ( check_tier < number_of_prof_tiers ) { // Make higher tier pt 1 equal to 0, if there is a higher tier
				document.getElementById(makeCraftFieldname(check_craft,check_tier+1,1)).value = 0;
				validateCraft(check_craft,check_tier+1,1,'inf_t'+(check_tier+1),'/'+max_craft_proficiency[1][check_tier+1]+'; /'+max_craft_proficiency[2][check_tier+1]);
			}
		}
		return true;
	}
	
	// Unknown part of a tier -> return a fail
	return false;
} // End validateCraft



