if(typeof(Cosplay) == "undefined") {
	Cosplay = new Object();
}


// #### BASE #####

if(typeof(Cosplay.Base) == "undefined") {
	Cosplay.Base = new Object();
	
	Cosplay.Base.BASE_URL = window.Cosplay_Base_BASE_URL;
	Cosplay.Base.WEBMASTER_MAIL = window.Cosplay_Base_WEBMASTER_MAIL;
	Cosplay.Base.PRODUCT_IMAGES_URL = window.Cosplay_Base_PRODUCT_IMAGES_URL;
	
	Cosplay.Base.__NO_CALLBACK = function() {};
	
	Cosplay.Base.resolve = function(targetURL) {
		if(targetURL.charAt(0) == '/') {
			targetURL = Cosplay.Base.BASE_URL + targetURL;
		}
		return targetURL;
	};
	
	Cosplay.Base.parseObject = function(objectString) {
		var result = eval("result = " + objectString);
		return result;
	};

	Cosplay.Base.normalizeCallback = function(callback) {
		if(typeof(callback) == "undefined") {
			callback = Cosplay.Base.__NO_CALLBACK;
		}
		return callback;
	};
	
	Cosplay.Base.getTimestamp = function() {
		return new Date().getTime();
	};
}

if(typeof(Cosplay.Util) == "undefined") {
	Cosplay.Util = new Object();
	
	Cosplay.Util.trim = function(sString) {
		while (sString.substring(0,1) == ' ') {
			sString = sString.substring(1, sString.length);
		}
		while (sString.substring(sString.length-1, sString.length) == ' ') {
			sString = sString.substring(0,sString.length-1);
		}
		return sString;
	};
}
if(typeof(Cosplay.Address) == "undefined") {
	Cosplay.Address = new Object();
	
	Cosplay.Address.validateZip=function(zip, countryCode) {
		if(countryCode=='us') {
			var zipFormat1=/^[0-9]{5}$/;
			var zipFormat2=/^[0-9]{5}-[0-9]{4}$/;
			if(!zip.match(zipFormat1) && !zip.match(zipFormat2)) {
				return false;
			}
			return true;
		} else if(countryCode=='ca') {
			if(zip.length == 7 && zip.charAt(3)==' ') {
				zip = zip.charAt(0) + zip.charAt(1) + zip.charAt(2) + zip.charAt(4) + zip.charAt(5) + zip.charAt(6);
			}
			var zipFormat=/^[A-Z][0-9][A-Z][0-9][A-Z][0-9]$/;
			if(!zip.match(zipFormat)) {
				return false;
			}
			return true;
		}
		return true;
	};

	Cosplay.Address.validatePhone=function(phoneNumber) {
		for(var i=0; i<phoneNumber.length; i++) {
			var chr=phoneNumber.charAt(i);
			if(
					chr != '0' &&
					chr != '1' &&
					chr != '2' &&
					chr != '3' &&
					chr != '4' &&
					chr != '5' &&
					chr != '6' &&
					chr != '7' &&
					chr != '8' &&
					chr != '9' &&
					chr != ' ' &&
					chr != '(' &&
					chr != ')' &&
					chr != '+' &&
					chr != '-'
					) {
				return false;
			}
		}
		return true;
	};

}
		
// #### DOM ####
if(typeof(Cosplay.Dom) == "undefined") {
	Cosplay.Dom = new Object();

	Cosplay.Dom.getRadioGroupSelectedOption = function(radioGroup) {
		for(var i = 0; i< radioGroup.length; i++) {
			if(radioGroup[i].checked) {
				return radioGroup[i];
			}
		}
		return null;
	}

	Cosplay.Dom.getRadioGroupOption = function(radioGroup, value) {
		for(var i = 0; i< radioGroup.length; i++) {
			if(radioGroup[i].value == value) {
				return radioGroup[i];
			}
		}
		return null;
	}
	
	Cosplay.Dom.getClientDimensions = function() {
	  var width = 0;
	  var height = 0;
	  if( typeof( window.innerWidth ) == 'number' ) {
    	//Non-IE
    	width = window.innerWidth;
    	height = window.innerHeight;
  	} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
	    //IE 6+ in 'standards compliant mode'
    	width = document.documentElement.clientWidth;
    	height = document.documentElement.clientHeight;
  	} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
	    //IE 4 compatible
    	width = document.body.clientWidth;
    	height = document.body.clientHeight;
  	}
  	return {width: width, height: height};
  };
  
  Cosplay.Dom.submit = function(target, parameters, method) {
		var form=document.createElement('form');
		form.method = method;
		form.action = target;
		document.body.appendChild(form);
		for(var parameter in parameters) {
				var value = Cosplay.Async.encodeParameterValue(parameters[parameter]);
				var input = document.createElement('input');
				input.type = 'hidden';
				input.name = parameter;
				input.value = value;
				form.appendChild(input);
		}
		form.submit();
	};
}


// #### ASYNC ####

if(typeof(Cosplay.Async) == "undefined") {
	Cosplay.Async = new Object();
	Cosplay.Async.__nextCallId = 1;
	
	Cosplay.Async.NULL_PARAMETER = '!null!';
	
	//doesn't work yet
	Cosplay.Async.synchronize = function(aFunction /*, varargs...*/) {
		var returnValues = null;
		var callback = function() {
			var args = new Array();
			for(var i = 0; i<arguments.length; i++) {
				args[i] = arguments[i];
			}
			returnValues = args;
		}
		var args = new Array();
		for(var i = 1; i<arguments.length; i++) {
			args[i-1] = arguments[i];
		}
		args[arguments.length] = callback;
		aFunction.apply(null, args);
		while(returnValues==null) {
		}
		return returnValues;
	}
	
	/*
		target: the php page url.
		parameters: the map of (parameter: value).
		callback: a function with the arguments callId, failure (boolean), response (the text response or the exception)
		returns: the call id.
	*/
	Cosplay.Async.request = function(target, parameters, callback) {
		callback = Cosplay.Base.normalizeCallback(callback);
		var callId = Cosplay.Async.__nextCallId;
		Cosplay.Async.__nextCallId++;
		var request;
		try {
			request = window.XMLHttpRequest? new XMLHttpRequest(): new ActiveXObject("Microsoft.XMLHTTP");
		} catch (e) {
			callback(callId, true, 'Ajax error: ' + e);
			return callId;
		}
		request.onreadystatechange = function() {
			if(request.readyState == 4) {
				if (request.status == 200) {
					callback(callId, false, request.responseText);
				} else {
					callback(callId, true, 'Ajax error: readyState=' + request.readyState + ', readyState=' + request.status);
				}
			}
		};
		target = Cosplay.Base.resolve(target);
		var parametersString = Cosplay.Async.encodeParameters(parameters)
		parametersString = Cosplay.Async.appendTimeStamp(parametersString);
		request.open("POST", target);
		request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		request.send(parametersString);
		return callId;
	};

	Cosplay.Async.showDialog = function(target, parameters, options) {
		target = Cosplay.Base.resolve(target);
		var parametersString = Cosplay.Async.encodeParameters(parameters)
		parametersString == Cosplay.Async.appendTimeStamp(parametersString);
		var contentURL = Cosplay.Async.appendParameters(target, parametersString);
		Modalbox.showMessage(contentURL, options);
	};

	Cosplay.Async.appendParameters = function(resourceURL, parametersString) {
		if(parametersString == "") {
			return resourceURL;
		} else {
			return resourceURL + "?" + parametersString;
		}
	};

	Cosplay.Async.appendTimeStamp = function(parametersString) {
		if(parametersString == "") {
			return "timeStamp=" + Cosplay.Base.getTimestamp();
		} else {
			return parametersString + "&" + "timeStamp=" + Cosplay.Base.getTimestamp();
		}
	};

	Cosplay.Async.encodeParameters = function(parameters) {
		var parametersString = "";
		for(var parameter in parameters) {
			value = Cosplay.Async.encodeParameterValue(parameters[parameter]);
			if(parametersString != "") {
				parametersString += "&";
			}
			parametersString += parameter + "=" + value;
		}
		return parametersString;
	};
	
	Cosplay.Async.encodeParameterValue = function(value) {
		if(value == null) {
			return Cosplay.Async.NULL_PARAMETER;
		} 
		return encodeURIComponent(value);
	};
	
	Cosplay.Async.createParameters = function(form, includeUncheckedBoxes) {
		var parameters = new Object();
		for (i=0; i < form.length; i++) {
			var element = form.elements[i];
			var name = element.name;
			if(typeof(name)!='undefined' && name!=null) {
				if(element.tagName.toLowerCase() == 'input') {
					if(element.type.toLowerCase() == "text"){
						parameters[name] = element.value;
					} else if(element.type.toLowerCase() == "textarea"){
						parameters[name] = element.value;
					} else if(element.type.toLowerCase() == "hidden"){
						parameters[name] = element.value;
					} else if(element.type.toLowerCase() == "checkbox"){
						if(element.checked==true){
							var value = element.value;
							if(typeof(value)=='undefined' || value==null) {
								value='on';
							}
							if(includeUncheckedBoxes) {
								parameters[name] = '+' + value;
							} else {
								parameters[name] = value;
							}
						} else {
							if(includeUncheckedBoxes) {
								parameters[name] = '-' + element.value;
							}
						}
					} else if(element.type.toLowerCase() == "radio"){
						if(element.checked==true){
							var value = element.value;
							if(typeof(value)=='undefined' || value==null) {
								value='on';
							}
							parameters[name] = value;
						}
					} else if(element.type.toLowerCase() == 'submit') {
						//nothing to do. append submit name and value accoding to the  desired action.
					} else if(element.type.toLowerCase() == 'button') {
						//nothing to do.
					} else {
						throw 'Unsupported form input element: element.name=' + element.name + ' element.value=' + element.value + ' element.tagName=' + element.tagName + ' element.type=' + element.type;
					}
				} else if(element.tagName.toLowerCase() == 'select') {
					parameters[name] = element.value;
				} else {
					throw 'Unsupported form input element: element.name=' + element.name + ' element.value=' + element.value + ' element.tagName=' + element.tagName + ' element.type=' + element.type;
				}
			}
		}
		return parameters;
	};

/////////
	Cosplay.Setlocale = function(locale, callback) {
		callback = Cosplay.Base.normalizeCallback(callback);
		return Cosplay.Async.request(
				'/includes/locale.php', 
				{
					locale: locale
				}, 
				function(callId, failure, response) {
					callback(callId,true,'test');
					/*var stockInfo;
					if(failure) {
					 callback(callId, false, true, response);
					} else {
						var result = Cosplay.Base.parseObject(response);
						callback(callId, result, false);
					} */
				}
			);
	};
	
// END TEST
}

if(typeof(Cosplay.XML) == "undefined") {
	Cosplay.XML = new Object();

	Cosplay.XML.XMLNodeReader = function() {
		this.header=null;
		this.name=null;
		this.attributes=null;
		this.childNodes=null;
		this.text=null;

		this.init=function(name, text, attributes, childNodes){
			if(typeof(name)=="undefined") {
				name="#document";
			}
			if(typeof(attributes)=="undefined") {
				attributes=new Object();
			}
			if(typeof(childNodes)=="undefined") {
				childNodes=new Object();
			}
			if(name=="#document") {
				this.header='<?xml version="1.0" encoding="UTF-8" ?>';
			}
			this.name=name;
			this.attributes=attributes;
			this.childNodes=childNodes;
			this.text=text;
			return this;
		};

		this.initNode=function(node){
			var nodeName=node.nodeName;
		  var children=node.childNodes;
		  var childNodes=new Object();
		  var attributes=new Object();
		  var text=null;
		  for(var i=0 ;  i < children.length; i++ ) {
		    var child=children.item(i);
		    if(child.nodeType == 3/*XML_TEXT_NODE*/) {
		    	if(text==null) {
		    		text='';
		    	}
		    	text+=child.nodeValue;
		    } else if(child.nodeType == 2/*XML_ATTRIBUTE_NODE*/) {
			    attributes[child.nodeName]=child.nodeValue;
		    } else {
		    	if(typeof(childNodes[child.nodeName])=="undefined") {
						childNodes[child.nodeName]=new Array();
		    	}
		    	childNodes[child.nodeName].push(new Cosplay.XML.XMLNodeReader().initNode(child));
		    }
		  }
		  return this.init(nodeName, text, attributes, childNodes);
		};

		this.initString=function(xmlString){       
			var xmlDoc;
			try { //Internet Explorer
				xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
				xmlDoc.async=false;
				xmlDoc.loadXML(xmlString);
			} catch(e) {
				try { // Firefox, Mozilla, Opera, etc.
					var parser=new DOMParser();
					xmlDoc=parser.parseFromString(xmlString,"text/xml");
				} catch(e) {
					alert(e.message);
					throw e;
				}
			} 
			return this.initNode(xmlDoc);
		};

		this.initFile=function(xmlFile){
			var xmlDoc;
			try { //Internet Explorer
				xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
			} catch(e) {
				try { //Firefox, Mozilla, Opera, etc.
					xmlDoc=document.implementation.createDocument("","",null);
				} catch(e) {
					alert(e.message);
					throw e;
				}
			}
			xmlDoc.async=false;
			xmlDoc.load(xmlFile);
			return this.initNode(xmlDoc);
		};

		this.getAttribute=function(attributeName, defaultValue) {
			if(typeof(defaultValue)=="undefined") {
				defaultValue=null;
			}
			if(typeof(this.attributes[attributeName])=="undefined") {
				return defaultValue;
			} else {
				return this.attributes[attributeName];
			}
		};

		this.getAttribute=function(attributeName, value) {
			this.attributes[attributeName]=value;
		};
		
		this.setText=function(text) {
			this.text=text;
		};
		
		this.getText=function(defaultText) {
			if(typeof(defaultText)=="undefined") {
				defaultText=null;
			}
			if(this.text==null) {
				return defaultText;
			} else {
				return this.text;
			}
		};
		
		this.getChild=function(nodeName) {
			var children=this.getChildren(nodeName);
			if(children.length==0) {
				return null;
			} else {
				return children[0];
			}			
		};
	
		this.createChild=function(nodeName) {
			var children=this.getChildren(nodeName);
			var nodeReader=new Cosplay.XML.XMLNodeReader().init(nodeName);
			this.childNodes[nodeName].push(nodeReader);
			return nodeReader;
		};
		
		this.getChildren=function(nodeName) {
			if(typeof(this.childNodes[nodeName])=="undefined") {
				this.childNodes[nodeName]=new Array();
			}
			return this.childNodes[nodeName];
		};
	
		this.getNodeProperty=function(propertyName, defaultValue) {
			if(typeof(defaultValue)=="undefined") {
				defaultValue=null;
			}
			var node=this.getChild(propertyName);
			if(node==null) {
				return defaultValue;
			} else {
				return node.getText(defaultValue);
			}
		};

		this.getNodeListProperty=function(propertyName) {
			var nodes=this.getChildren(propertyName);
			var values=new Array();
		  for(var i=0 ;  i < nodes.length; i++ ) {
		  	var node=nodes[i];
				values.push(node.getText());
			}
			return values;
		};

		this.addNodeListProperty=function(propertyName, values) {
		  for(var i=0 ;  i < values.length; i++ ) {
		  	var value=values[i];
				this.createChild(propertyName).setText(value);
			}
		};
		
		this.setNodeProperty=function(propertyName, value) {
			var node=this.getChild(propertyName);
			if(node==null) {
				node=this.createChild(propertyName);
			}
			node.setText(value);
		};
	
		this.contentsToXMLString=function(indent) {
			if(typeof(indent)=="undefined") {
				indent='';
			}
			var hasChildren=false;
			for(var nodeName in this.childNodes) {
				hasChildren=true;
				break;
			}
			var str='';
			if(!hasChildren) {
				if(this.text!=null) {
					str+= this.text;
				}
			} else {
				if(this.text!=null) {
					str+= this.text+"\n";
				}
				for(var nodeName in this.childNodes) {
					var nodes=this.childNodes[nodeName];
					for(var i=0; i<nodes.length; i++) {
						var node=nodes[i];
						str+= node.toXMLString(indent);
					}
				}
			}
			return str;
		};
		
		this.toXMLString=function(indent) {
			if(typeof(indent)=="undefined") {
				indent='';
			}
			if(this.name=="#document") {
				return this.header + '\n' + this.contentsToXMLString();
			}
			var str=indent+'<'+this.name;
			for(var attributeName in this.attributes) {
				var value=this.attributes[attributeName];
				str+= "\n"+indent+"  "+attributeName+'='+value; 
			}
			var hasChildren=false;
			for(var nodeName in this.childNodes) {
				hasChildren=true;
				break;
			}
			str+= ">"; 
			if(hasChildren) {
				str+= "\n";
			}
			str+=this.contentsToXMLString(indent+'  ');
			if(hasChildren) {
				str+= indent;
			}
			str+= '</'+this.name+">\n";
			return str;
		};
	};

};

// #### STOCK ####

/*
STRUCTURE RETURNED BY getStock:
{
	type: 'ERROR',
	error: '<error>'
}
OR
{
	type: 'EMPTY'
}
OR
{
	type: 'SIMPLE',
	data: '<stock>'
}
OR
{
	type: 'DETAILED',
	data: {
		stock: '<stock>',
		quantity: <quantity>
	}
}
OR
{
	type: 'BY_SIZE',
	data: {
		0: {
			size: '<size>',
			stock: '<stock>'
		},
		...
		n: {
			size: '<size>',
			stock: '<stock>'
		}
	}
}
OR
{
	type: 'DETAILED/BY_SIZE',
	data: {
		0: {
			size: '<size>',
			stock: '<stock>',
			quantity: '<detail>'
		},
		...
		n: {
			size: '<size>',
			stock: '<stock>',
			quantity: <quantity>
		}
	}
}
<error> IS an string containing the error description.
<stock> IS 'yes', 'low' OR 'no'.
<quantity> IS an number with the amount in stock.
<size> IS an string containing size number.
<options_set> IS the options set as stored in localstock2 table
<warehouse i> IS the warehouse code (FL, TO, MO, etc)
*/
if(typeof(Cosplay.Stock) == "undefined") {
	Cosplay.Stock = new Object();

	/*
		productId: the product id.
		callback: a function with the arguments callId, stockInfo (structure described above)
		returns: the call id.
	*/
	Cosplay.Stock.getStock = function(productId, callback) {
		callback = Cosplay.Base.normalizeCallback(callback);
		return Cosplay.Async.request(
				'/includes/stock_check_js.php', 
				{id: productId}, 
				function(callId, failure, response) {
					var stockInfo;
					if(failure) {
						stockInfo = {
							type: 'ERROR', 
							error: response
						};
					} else {
						stockInfo = Cosplay.Base.parseObject(response);
					}
					callback(callId, stockInfo);
				}
			);
	};
	
	/*
		productId: the product id.
		options: the product options.
		action: the stock action ('add', 'remove' or 'move').
		warehouse: the affected warehouse.
		targetWarehouse: the other affected targetWarehouse (when action == 'move').
		quantity: the quantity.
		note: some arbitrary note.
		callback: a function with the arguments callId, failure (boolean), description
		returns: the call id.
	*/
	Cosplay.Stock.change = function(productId, options, action, warehouse, targetWarehouse, quantity, purchaseOrder, notes, callback) {
		callback = Cosplay.Base.normalizeCallback(callback);
		var parameters = new Object();
		parameters.productId = productId;
		parameters.action = action;
		parameters.warehouse = warehouse;
		parameters.targetWarehouse = targetWarehouse;
		parameters.quantity = quantity;
		parameters.purchaseOrder = purchaseOrder;
		parameters.notes = notes;
		for(var option in options) {
			parameters[option] = options[option];
		}
		return Cosplay.Async.request(
				'/includes/stockChangeHandler.php', 
				parameters, 
				function(callId, failure, response) {
					var stockInfo;
					if(failure) {
						callback(callId, true, 'Unable to modify stock records: ' + response);
					} else {
						var result = Cosplay.Base.parseObject(response);
						if(result.status == 'SUCCESS') {
							callback(callId, false, result.description);
						} else {
							callback(callId, true, result.description);
						}
					}
				}
			);
	};
	
	Cosplay.Stock.undoChange = function(undoIds, callback) {
		callback = Cosplay.Base.normalizeCallback(callback);
		var parameters = new Object();
		parameters.undoIds = undoIds;
		
		return Cosplay.Async.request(
				'/localstock/undoStockChangeHandler.php', 
				parameters, 
				function(callId, failure, response) {
					var stockInfo;
					if(failure) {
						callback(callId, true, 'Unable to undo modify stock records: ' + response);
					} else {
						var result = Cosplay.Base.parseObject(response);
						if(result.status == 'SUCCESS') {
							callback(callId, false, result.description);
						} else {
							callback(callId, true, result.description);
						}
					}
				}
			);
	};
	
	Cosplay.Stock.showHistoryDialog = function(productId, options, dialogOptions) {
		var parameters = new Object();
		parameters.productId = productId;
		for(var option in options) {
			parameters['option__' + option] = options[option];
		}
		Cosplay.Async.showDialog(
				'/includes/stockChangeHistoryDialog.php', 
				parameters,
				dialogOptions
			);
	};
		
}

// #### CART ####
if(typeof(Cosplay.Cart) == "undefined") {
	Cosplay.Cart = new Object();

	/*
		productId: the product id.
		options: the product options.
		quantity: the quantity.
		PATH: the category path of the product
		callback: a function with the arguments callId, failure (boolean), description
		returns: the call id.
	*/
	Cosplay.Cart.add = function(productId, options, quantity, callback, PATH) {
		callback = Cosplay.Base.normalizeCallback(callback);
		var parameters = new Object();
		parameters.productId = productId;
		parameters.quantity = quantity;
		parameters.PATH = PATH;
		
		for(var option in options) {
			parameters[option] = options[option];
		}
		return Cosplay.Async.request(
				'/shoppingcart/addProductHandler.php',
				parameters, 
				function(callId, failure, response) {
					var stockInfo;
					if(failure) {
						callback(callId, true, 'Unable add product: ' + response);
					} else {
						var result = Cosplay.Base.parseObject(response);
						if(result.status == 'SUCCESS') {
							callback(callId, false, result.description);
						} else {
							callback(callId, true, result.description);
						}
					}
				}
			);
	};
}

// #### MAIL ####
if(typeof(Cosplay.Mail) == "undefined") {
	Cosplay.Mail = new Object();

	/*
		to: the receiver's address.
		subject: the mail subject.
		body: the message body.
		callback: a function with the arguments callId, failure (boolean), errorDescription (present only if failure is true)
		returns: the call id.
	*/
	Cosplay.Mail.send = function(to, subject, body, callback) {
		callback = Cosplay.Base.normalizeCallback(callback);
		return Cosplay.Async.request(
				'/includes/mail.php', 
				{
					action: 'send_plain',
					to: to,
					subject: subject,
					body: body
				}, 
				function(callId, failure, response) {
					var stockInfo;
					if(failure) {
						callback(callId, true, response);
					} else {
						var result = Cosplay.Base.parseObject(response);
						if(result == true) {
							callback(callId, false);
						} else {
							callback(callId, true, 'Mail error: Unable to send mail.');
						}
					}
				}
			);
	};

	/*
		to: the receiver's address.
		subject: the mail subject.
		body: the message body.
		fromaddress: the senders address.
		fromname: the senders name.
		callback: a function with the arguments callId, failure (boolean), errorDescription (present only if failure is true)
		returns: the call id.
	*/
	Cosplay.Mail.sendHTML = function(to, body, subject, fromaddress, fromname, callback) {
		callback = Cosplay.Base.normalizeCallback(callback);
		return Cosplay.Async.request(
				'/includes/mail.php', 
				{
					action: 'send_html',
					to: to,
					subject: subject,
					body: body,
					fromaddress: fromaddress,
					fromname: fromname
				}, 
				function(callId, failure, response) {
					var stockInfo;
					if(failure) {
						callback(callId, true, response);
					} else {
						var result = Cosplay.Base.parseObject(response);
						if(result == true) {
							callback(callId, false);
						} else {
							callback(callId, true, 'Mail error: Unable to send mail.');
						}
					}
				}
			);
	};

	/*
		mail: mail to validate.
		callback: a function with the arguments callId, valid (boolean), failure (boolean), errorDescription (present only if failure is true)
		returns: the call id.
	*/
	Cosplay.Mail.validate = function(mail, callback) {
		callback = Cosplay.Base.normalizeCallback(callback);
		return Cosplay.Async.request(
				'/includes/mail.php', 
				{
					action: 'validate',
					mail: mail
				}, 
				function(callId, failure, response) {
					var stockInfo;
					if(failure) {
						callback(callId, false, true, response);
					} else {
						var result = Cosplay.Base.parseObject(response);
						callback(callId, result, false);
					}
				}
			);
	};

	Cosplay.Mail.sendInternal = function(subject, body, callback) {
		var ts = new Date();
		var h = ts.getHours();
		var m = ts.getMinutes();
		var s = ts.getSeconds();
		var mm = ts.getMonth();
		var d =  ts.getDate();
		var y =  ts.getFullYear();
		
		body += '\n\nTimestamp: ' + (h < 10? '0' + h : h) + ':' + (m < 10? '0' + m : m) + ':' + (s < 10? '0' + s : s) + ' - ' +
			mm + '/' + d + '/' + y + ' (MM/DD/YYYY)';
		return Cosplay.Mail.send(Cosplay.Base.WEBMASTER_MAIL, subject, body, callback);
	};
}
