/*
 * image preload...
 */
var i = new Image();
i.src = '../player/g/buttons/btn_pri_big_rollover_trans.png';
i.src = '../player/g/buttons/btn_pri_rollover_trans.png';


/**
 * adds a css class to an element
 * @param {Object} element
 * @param {Object} className
 */
function addClass(element, className) {
	if (element.className.indexOf(className) == -1) {
		element.className += ' ' + className;
	}
}

/**
 * checks whether an element node has the given attribute - purely for browser compatibility as IE
 * doesn't support the DOM 1.0 function 'hasAttribute'...
 *
 * @param {Object} element to check
 * @param {String} attribute to check for
 * @return {Bool} whether the attribute exists...
 */
function attributeExists(element, attribute) {
	if (element.hasAttribute != undefined) {
		return element.hasAttribute(attribute);
	} else {
		return (element.getAttribute(attribute) != null);
	}
}

/**
 * these variables are required for the autoOnLoad function, so don't delete them...
 */
var playerServices;
var submitButtons = new Array();

/**
 * general onload functionality
 * @param {Object} e
 */
var pl;
function autoOnLoad(e) {
	// objects...
	var nTle = new NameTitle('managerTitle', 'otherTitle');
	pl = new PostcodeLookup('postcodeToLookup','lookupPostcode', 'addressSummary', ['autoAddress', 'addressSummary'], ['manualAddress1', 'manualAddress2', 'manualAddress3', 'manualAddress4', 'manualAddress5', 'manualAddress6'], 'adjustAddress');

	var formId = 'syndicatePackRequest';

	// validation...
	var requiredFields = ['managerTitle', 'firstName', 'lastName'];
	for (var x = 0; x < requiredFields.length; x++) {
		var v = new Validator(requiredFields[x], formId);
		v.addValidationTest(new RequiredFieldsValidationTest('Please enter your name'));

		// if this is IE, we have a little fudge to force a re-render on the firstName validation to prevent a rendering error that sometimes occurs...
		if (requiredFields[x] == 'firstName' && (document.all != undefined)) {
			v.onValidation = function(args) { forceReRender(args.validator.getInputElement(), true); }
		}
	}

	var otherTitleValidator = new Validator('otherTitle', formId);
	var otherTitleRequired = new RequiredFieldsValidationTest('Please enter a title');
	otherTitleValidator.addValidationTest(new ConditionalValidationTest(validateOtherTitle, otherTitleRequired));
	nTle.addOtherTitleValidator(otherTitleValidator);

	var addressIdValidator = new Validator('addressId', formId);
	addressIdValidator.errorAdjacentLeft = document.getElementById("lookupPostcode");
	addressIdValidator.addValidationTest(new RequiredFieldsValidationTest('Please enter a postcode, do a lookup and select an address.'));

	var addressLine1Validator = new Validator('addressLine1', formId);
	addressLine1Validator.addValidationTest(new RequiredFieldsValidationTest('Please enter the first line of your address'));

	var postcodeValidator = new Validator('postCode', formId);
	postcodeValidator.addValidationTest(new RequiredFieldsValidationTest('Please enter a postcode'));
	
	var emailValidator = new Validator('email', formId);
	var validateEmail = new EmailValidationTest('Please enter a valid email address');
	emailValidator.addValidationTest(new ConditionalValidationTest(inputNotEmpty, validateEmail));
	
	var compareEmailValidator = new Validator('email2', formId);
	compareEmailValidator.addValidationTest(new CompareFieldsValidationTest('Email doesn\'t match, please check', 'email'));

	// disable 'otherTitle' initially if 'other' isn't selected in the title select box...
	var managerTitle = document.getElementById("managerTitle");
	if (managerTitle.value != 'other')
		document.getElementById("otherTitle").disabled = true;

	// when 'all' is selected for player services, check all the other boxes, when one box is unselected, uncheck 'all'
	playerServices = document.getElementsByName('playerServices[]');
	for (x = 0; x < playerServices.length; x ++) {
		eventSubscribe(playerServices[x], 'click', onPlayerServicesChange);
	}

	// if we're having problems with Ajax and so we've posted back to the server to get the address list, we need to make sure that
	// when an address list button is clicked the validation errors don't stop it submitting...
	if (document.getElementById('addressList') != null) {
		var addresses = document.getElementById('addressList').getElementsByTagName('button');
		for (x = 0; x < addresses.length; x++) {
			addresses[x].onclick = function(e) {document.getElementById('syndicatePackRequest').overrideValidation = true;};
		}
	}
}

/**
 * don't delete this line, it makes autoOnLoad run when the page loads...
 */
eventSubscribe(window, 'load', autoOnLoad);

/**
 * create a callback to be used by an object - rather than doing
 *   var self = this;
 *   var cb = function(e) { this.callbackMethod(e); }
 * you can just call this method.
 * @param {Object} object to create the callback for
 * @param {String} name of the function to call
 * @return {Function} callback function
 */
function createCallback(obj, methodName) {
	if (typeof obj[methodName] != 'function') {
		throw new Error('createCallback: no method of name \'' + methodName + '\'');
	}
	return function(e) { obj[methodName](e); }
}

/**
 * eventAbortAction - browser independent way of cancelling the action that follows an event. Calls preventDefault on DOM
 * compliant browsers, sets returnFalse to true with IE. A browser independence function...
 *
 * @param {Object} event object whose action we're cancelling
 */
function eventAbortAction(e) {
	switch (true) {
		case (e.preventDefault !== undefined): // Firefox and other DOM-compliant browsers...
			e.preventDefault();
		default: // could be IE - no way to check 'returnValue == undefined' because before it is set it *is* undefined (rather than 'true' which might actually be some use!)...
			e.returnValue = false;
	}
}

/**
 * subscribe to events in a browser independent way - calls addEventListener for DOM compliant browsers and attachEvent for IE.
 *
 * @param {Object} element whose event we're attaching to
 * @param {String} event we're subscribing to - omit the 'on' part
 * @param {Function} callback function
 * @return {Bool} true if we successfully attach to the event, false otherwise.
 */
function eventSubscribe(element, eventName, callback) {
	switch (true) {
		case (element.addEventListener !== undefined): // Firefox and other DOM-compliant browsers...
			element.addEventListener(eventName, callback, true);
			return true;
		case (element.attachEvent !== undefined): // IE...
			element.attachEvent('on' + eventName, callback);
			return true;
		default: // unsupported...
			return false;
	}
}

/**
 * causes an element to act in a similar way to a label - i.e. when clicked on it will focus on a different element. Also useful for 'double focus' labels,
 * such as the 'other' radio in a radio group that needs to select the 'other' radio button but also focus on a text input where the user specifies the
 * 'other' value
 * @param {String} the id of the element that when clicked on will activate the second element...
 * @param {String} the id of the element to focus on when the first one is clicked...
 */
function focusOnClick(clickedId, focusOnId) {
	var focusOn = document.getElementById(focusOnId);
	var cb = function(e) { focusOn.focus(); }
	eventSubscribe(document.getElementById(clickedId), 'click', cb);
}

/**
 * removes and re-adds id and classname, this should normally force the browser to re-render (useful in IE which can get muddled)...
 * @param {Object} element
 * @param {Bool} use parent of given element
 */
function forceReRender(element, useParent) {
	if (useParent) {
		element = element.parentNode;
	}
	var id = element.id;
	var className = element.className;
	element.id = '';
	element.className = '';
	element.id = id;
	element.className = className;
}

/**
 * childNodes is a useful element property, but it returns *all* child nodes, not just element nodes. This
 * function just returns the element nodes. Much more useful!
 * @param {Object} element to get the child elements for...
 * @return {Array} all child nodes that are also element nodes...
 */
function getChildElements(element) {
	var childElements = [];
	for (var xx = 0; xx < element.childNodes.length; xx++) {
		if (element.childNodes[xx].nodeType == 1) {
			childElements.push(element.childNodes[xx]);
		}
	}
	return childElements;
}

/**
 * getElementsByClassName
 * @param {Object} class name to look for
 * @param {Object} oElm - element to search, defaults to document.body
 * @param {Object} tagName - tag name to match, defaults to all
 * @return {Array} all matching elements
 */
function getElementsByClassName(name, oElm, tagName) {
	// default arguments...
	if (oElm == undefined || oElm == null) oElm = document.body;
	if (tagName == undefined || tagName == null) tagName = "*";

	// setup result stack...
	var results = new Array();

	// get the elements to search...
	var elems = oElm.getElementsByTagName(tagName);

	// now search...
	for (var i=0; i < elems.length; i++) {
		if (elems[i].className.indexOf(name) != -1) {
			// match, so add to stack...
			results.push(elems[i]);
		}
	}

	// return stack...
	return results;
}

/**
 * gets the size of an element - borrowed from the lightbox http://www.huddletogether.com/projects/lightbox/
 * @return {object} with properties pageWidth, pageHeight, windowWidth and windowHeight...
 */
function getPageSize(){
	var xScroll, yScroll;

	if (window.innerHeight && window.scrollMaxY) {
		xScroll = document.body.scrollWidth;
		yScroll = window.innerHeight + window.scrollMaxY;
	} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
		xScroll = document.body.scrollWidth;
		yScroll = document.body.scrollHeight;
	} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
		xScroll = document.body.offsetWidth;
		yScroll = document.body.offsetHeight;
	}

	var windowWidth, windowHeight;
	if (self.innerHeight) {	// all except Explorer
		windowWidth = self.innerWidth;
		windowHeight = self.innerHeight;
	} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
		windowWidth = document.documentElement.clientWidth;
		windowHeight = document.documentElement.clientHeight;
	} else if (document.body) { // other Explorers
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
	}

	// for small pages with total height less then height of the viewport
	if(yScroll < windowHeight){
		pageHeight = windowHeight;
	} else {
		pageHeight = yScroll;
	}

	// for small pages with total width less then width of the viewport
	if(xScroll < windowWidth){
		pageWidth = windowWidth;
	} else {
		pageWidth = xScroll;
	}

	return {pageWidth: pageWidth, pageHeight: pageHeight, windowWidth: windowWidth, windowHeight: windowHeight};
}

/**
 * works out whether an element is in the Document, or just in memory. A browser independence function...
 *
 * @param {Object} element to check
 * @return {Bool} true if the element is in the document, false otherwise
 */
function isInDocument(element) {
	if (element.parentNode == null) {
		return false;
	} else if (element.parentNode.nodeType == 11) {
		return false;
	} else {
		return true;
	}
}

/**
 * event handler for the click event on the 'select all' checkbox for player services, and all the individual check boxes within this...
 * @param {Object} event
 */
function onPlayerServicesChange(e) {
	var target = (e.currentTarget == undefined) ? (e.srcElement) : (e.currentTarget);
	if (target.value == 'all') {
		// either check all the others or uncheck them...
		for (var xx = 0; xx < playerServices.length; xx ++) {
			playerServices[xx].checked = target.checked;
		}
	} else {
		// if all selected, check the 'all' box otherwise uncheck it...
		var allChecked = true;
		for (var xx = 0; xx < playerServices.length; xx ++) {
			if (!playerServices[xx].checked) {
				allChecked = false;
				break; // set to false so break out...
			}
		}

		document.getElementById('cb_playerservices_1').checked = allChecked;
	}
}

/**
 * removes a css class from an element
 * @param {Object} element
 * @param {Object} className
 */
function removeClass(element, className) {
	if (element.className.indexOf(className) != -1) {
		var currentclass = element.className;
		var pattern = new RegExp("(^| )" + className + "( |$)");
		currentclass = currentclass.replace(pattern,"$1");
		currentclass = currentclass.replace(/ $/,"");
		element.className = currentclass;
	}
}

/**
 * shows the 'select all' checkbox, given its id
 * @param {Object} id
 */
function showSelectAllCheckbox(id) {
	// show 'select all' checkbox...
	var cont = document.getElementById(id);
	var hiddenEls = getElementsByClassName('hidden', cont, 'label');
	for (var x = 0; x < hiddenEls.length; x++) {
		removeClass(hiddenEls[x], 'hidden');
	}
}

/**
 * checks whether the validation test for the other title box should be carried out
 * @param {Object} otherTitle
 */
function validateOtherTitle(otherTitle) {
	var titleSelect = document.getElementById('managerTitle');
	return (titleSelect.value == 'other');
}

/**
 * checks whether a field is filled out - useful for validation tests that are only carried out if the field is filled out
 * @param {Object} field to check
 */
function inputNotEmpty(inputToCheck) {
	return (inputToCheck.value && inputToCheck.value != '');
}
	