// Shared code for FineStoneMiniatures// Declare global variables

// Global constants
var gcMaximumOrder = 8;		// Max no of miniatures a user may buy in one online order

// Arrays to hold details of all miniatures (array index = integer part of miniature ID)
var strNames = new Array();			// Array of miniature names
var strPrices = new Array();		// Array of miniature prices: stone()~green(GR)~bronze(A)~pewter(S)~gold(G)~red(R)
var strSizes = new Array();			// Array of miniature sizes
var intWeights = new Array();		// Array of miniature weights in grams

// Arrays to hold contents of shopping basket
var strIDs = new Array();			// Array of miniature ID numbers in basket (string as can hold eg 14G)
var intQuantities = new Array();	//Array of number of miniatures in basket

// Arrays to hold postage lookup tables (populated by fnBuildPostage() in postage.js)
var strPlaces = new Array();	// Array of postal places, formatted: PlaceName~ZoneNumber
var intBands = new Array();		// Array of postage weight band upper limits in grams (index is same as strPostage index)
var strPostage = new Array();	// Array of postage amounts (in pence) for each band (index) and each zone 1-n (delimited by ~)

// Basket totals & postal zone
var intTotalPrice = 0;		// Cost of miniatures in pence excluding p&p
var intTotalWeight = 0;		// Weight of miniatures in grams
var intTotalQuantity = 0;	// Number of miniatures in basket
var intPostage = 0;			// Cost of p&p
var intPlace = -1;			// Index of selected postal destination (from list on checkout.htm)

// Shared functions

// This function populates the global basket arrays and variables from the cookie data when a page is opened.
// This is formatted: Total-Weight*Postal-Zone-Index|Total-Postage!Total-Price#ID~Quantity^ID~Quantity...
// Set booCheckout to true in the p&p and checkout pages, false for all other pages
function fnBuildBasket(booCheckout) {
	var intIndex = 0;
	var str = "";
	var chr = "";
	var i = 0;
	var strBasket = fnReadBasket();
	// Rebuild total quantity each time we read the basket
	intTotalQuantity = 0;
	// Step through the basket string a character at a time, adding the characters to variable str.
	// Each time we hit a delimiter, store the content of str in the appropriate "total" variable and
	// reset str to an empty string
	for (i = 0; i < strBasket.length; i++) {
		chr = strBasket.charAt(i);
		// * terminates total weight
		if (chr == "*") {
			// Total weight only used by p&p and checkout pages
			if (booCheckout) {
				intTotalWeight = parseInt(str);
			}
			else {
				intTotalWeight = 0;
			}
			str = "";
		}
		// | terminates postal zone index
		else if (chr == "|") {
			intPlace = parseInt(str);
			str = "";
		}
		// ! terminates total postage
		else if (chr == "!") {
			intPostage = parseInt(str);
			str = "";
		}
		// # terminates total price
		else if (chr == "#") {
			// Total price only used by checkout page
			if (booCheckout) {
				intTotalPrice = parseInt(str);
			}
			else {
				intTotalPrice = 0;
			}
			str = "";
		}
		// ~ terminates an ID
		else if (chr == "~") {
			strIDs[intIndex] = str;
			str = "";
		}
		// ^ terminates a quantity
		else if (chr == "^") {
			intQuantities[intIndex] = parseInt(str);
			intTotalQuantity += intQuantities[intIndex];
			str = "";
			intIndex++;					
		}
		// Not a delimiter, so just add character to the str variable
		else {
			str = str + chr;
		}
	}
}

// Function to clear any message from the window status bar 
// (called from onMouseOver events, hence the "return true"
function fnClearStatus() {
	window.status = "";
	return true;
}

// Function to check if we are exceeding the maximum order size.
// If so, it displays a message to the user.  Returns true if full, or false otherwise.
function fnFullBasket(intQuantity) {
	var booFull = false;
	if (intQuantity > gcMaximumOrder) {
		str = "Sorry, this takes you over our maximum online order limit of " + gcMaximumOrder + " miniatures.\n";
		str += "Cannot add ";
		if (intQuantity == 1) {
			str += "this miniature";
		}
		else {
			str += "these miniatures";
		}
		str += " to your basket.\n\nPlease refer to our How To Order page for more information.";
		window.alert(str);
		booFull = true;
	}
	return booFull;
}

// Function to return the name (string) of a given miniature
function fnGetName(strID) {
	var chr = strID.charAt(strID.length - 1);	// Last character of the ID
	var chr2 = strID.charAt(strID.length - 2);	// 2nd last character of the ID (needed to check if suffix is "GR" or "R")
	var str = strNames[parseInt(strID)];		// The name of the miniature, to which eg " (Gold finish)" is appended
	//If the ID suffix is R we need to check if this is GR or just R
	if (chr == "r" || chr == "R") {
		if (chr2 == "g" || chr2 == "G") {
			str = str + " (Green finish)";
		} else {
			str = str + " (Red Antique finish)";
		}
	}
	else if (chr == "a" || chr == "A") {
		str = str + " (Bronze finish)";
	}
	else if (chr == "s" || chr == "S") {
		str = str + " (Pewter finish)";
	}
	else if (chr == "g" || chr == "G") {
		str = str + " (Gold finish)";
	}
	return str;
}

// Function to return the price (int) of a given miniature
// Prices are stored in strPrices array: stone()~green(GR)~bronze(A)~pewter(S)~gold(G)~red(R)
function fnGetPrice(strID) {
	var i = 0;									// Used to step through the pieced list of prices
	var j = 0;									// The piece number of the finish, ie 0 for plain, 1 for green, 2 for bronze, etc
	var intPrice = 0;							// Price to return
	var chr = strID.charAt(strID.length - 1);	// Last character of the ID (ie normally the suffix, except for GR)
	var chr2 = strID.charAt(strID.length - 2);	// 2nd last character of the ID (used to identify if suffix is GR or R)
	if (strPrices[parseInt(strID)] != null) {
		var str = strPrices[parseInt(strID)];
		if (chr == "r" || chr == "R") {
			if (chr2 == "g" || chr2 == "G") {
				j = 1;	// Green
			} else {
				j = 5;	// Red
			}
		}
		else if (chr == "a" || chr == "A") {
			j = 2;		// Bronze
		}
		else if (chr == "s" || chr == "S") {
			j = 3;		// Pewter
		}
		else if (chr == "g" || chr == "G") {
			j = 4;		// Gold
		}
		// Get this piece
		for (i = 0; i < j; i++) {
			str = str.substring(str.indexOf("~") + 1, str.length);
		}
		str = str.substring(0, str.indexOf("~"));
		// Convert to int (treat blank as zero)
		if (str == "") {
			str = "0";
		}
		intPrice = parseInt(str);	
	}
	return intPrice;
}

// Function to return the size & weight (string) of a given miniature
function fnGetSize(strID) {
	var str = strSizes[parseInt(strID)];
	var intWeight = intWeights[parseInt(strID)];
	if (str != "") {
		str = "Approx height: " + str + ", ";
	}
	if (intWeight > 0) {
		str += "Weight: " + intWeight.toString() + " grams";
	}
	if (str !="") {
		str += "<br>";
	}
	return str;
}

// Function to return the weight (integer) of a given miniature
function fnGetWeight(strID) {
	var int = intWeights[parseInt(strID)];
	if (int == null) {
		int = 0;
	}
	return int;
}

// Function to read the current contents of the shopping basket.  Returns either the string containing all of the shopping basket data,
// or null if the shopping basket is empty.
function fnReadBasket () {
	var intIndex = 0;
	var strName = "finestoneminiatures=";
	var strValue = document.cookie;
	intIndex = strValue.indexOf(strName);
	if (intIndex < 0) {
		return "";
	}
	else {
		strValue = strValue.substring(intIndex + strName.length, strValue.length);
		intIndex = strValue.indexOf(";");
		if (intIndex > 0) {
			strValue = strValue.substring(0, intIndex);
		}
		return unescape(strValue); 
	}
}

// Function to return price as a formatted string (pounds & pence with £ sign)
function fnShowPrice (intPrice) {
	var i = 0;
	var strPrice = "";
	var str = "" + intPrice;
	while (str.length < 3) {
		str = "0" + str;
	}
	strPrice = str.substring(0, (str.length - 2)) + "." + str.substring((str.length - 2), str.length);		
	return "£" + strPrice;
}

// Function to validate email address (adapted from http://www.xs4all.nl/~ppk/js/mailcheck.html)
// Checks strEmail comprises: a series of letters, numbers, underscores, dots or dashes (the user name)
// followed by @ then one or more subdomain names each followed by dot and finally a top level domain
// name of between 2 and 4 characters (this last doesn't seem to work!).  Returns true (valid) or false.
function fnValidEmail(strEmail) {
	var filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
	if (filter.test(strEmail)) {
		return true;
	}
	else {
		return false;
	}
}

// Function to check if a value is a positive integer or zero (returns true or false)
function fnValidQuantity(varValue) {
	var strValue = varValue.toString();
	var strChar = "";
	var booOK = true;
	var i = 0;
	for (i = 0; i < strValue.length; i++) {
		strChar = strValue.charAt(i);
		if (strChar < "0" || strChar > "9") {
			booOK = false;
			break;
		}
	}
	return booOK;
}

// Function to store the shopping basket in the cookie
// This is formatted Total-Weight*Postal-Place-Index|Total-Postage!Total-Price#ID~Quantity^ID~Quantity...
function fnWriteBasket () {
	var str = intTotalWeight.toString() + "*" + intPlace + "|";
	str += intPostage + "!" + intTotalPrice.toString() + "#";
	for (i = 0; i < strIDs.length; i++) {
		if (intQuantities[i] > 0) {
			str += strIDs[i] + "~" + intQuantities[i] + "^";
		}
	}
	document.cookie = "finestoneminiatures=" + escape(str);
}

// Code used by Catalog pages

		// Global arrays to hold images for the Add to Basket button
		var imgNormal = new Image(147, 30);
		var imgPressed = new Image(147, 30);

		// Preload the two images needed for the Add to Basket button
		function fnLoadImages () {
			imgNormal.src = "buttons/add_to_basket.gif";
			imgPressed.src = "buttons/add_to_basket_2.gif";
		}
		
		// Switch the images of the Add button when the user clicks it
		// Parameters: img is the image object to change, these are named imgAddID (ID varies)
		// str is set to "in" to press the button in, and "out" when the button is released
		function fnClick (img, str) {
			if (str == "in") {
				img.src = imgPressed.src;
			}
			else {
				img.src = imgNormal.src;
				window.status='';
			}
		}
			
		// This function adds the current selection to the shopping basket
		// The calling form provides the miniature ID and quantity to add
		function fnAddToBasket (strID, varQuantity) {
			var intQuantity = 0;
			var booFound = false;
			var intIndex = 0;
			var i = 0;
			var str = "";
			// Check the quantity is valid (integer, 1+)
			if (fnValidQuantity(varQuantity) && varQuantity > 0) {
				intQuantity = parseInt(varQuantity);
				// Check if the basket is full - only continue if not
				if (!fnFullBasket(intTotalQuantity + intQuantity)) {
					// Update the total quantity
					intTotalQuantity += intQuantity;
					// Step through the basket IDs array looking for this miniature
					for (i = 0; i < strIDs.length; i++) {
						// Found - add the new quantity to the existing quantity
						if (strIDs[i] == strID) {
							intQuantities[i] += intQuantity;
							booFound = true;
							break;
						}
					}
					// Miniature wasn't already in basket, so add it now
					if (!booFound) {
						intIndex = strIDs.length;
						strIDs[intIndex] = strID;
						intQuantities[intIndex] = intQuantity;
					}
					// Store the basket in the cookie
					fnWriteBasket();
				}
			}
			else {
				window.alert("Invalid quantity!  Please enter a whole number greater than zero.");
			}
		}
	

