function remoteCall(objData) {
	
	objData.remote = "1";
		
	$.ajax({
		type: "post",
		url: "?", // post to current url (removing this breaks call)
		data: objData,
		success: function(jsonStatus) {
			
			try {								
				objStatus = eval('(' + jsonStatus + ')');
				
				if (objStatus.statusID == 1) { 
					if (objData.callback != undefined) {
						eval(objData.callback + '(' + objStatus.result + ')');
					} else {
						eval(objStatus.result);
					}
				} else {
					alert("Error: " + objStatus.statusMsg);
				}
				
			// <!--- FIXME: handle errors better --->
			} catch (err) {
				alert('Error: ' + err.message + ' (' + err.fileName + ':' + err.lineNumber + ')');
				// <!--- alert('Invalid code was received from the web server. Please refresh the page and try again.'); --->
			}

			
		},
		<!--- cmsfix: do something with errors --->
		error: function(req) {
			if (req.status == 500) {
				// <!--- cmsfix: should only see this on dev --->
				$("body").html(req.responseText);
			} else if (req.status == 404) {
				// <!--- cmsfix: display some type of admin 404 page --->
				alert("Error: " + req.status);
			} else if (req.status != 200) {
				// <!--- cmsfix: do something with unknown errors --->
				alert("Unknown error:" + req.status);
			}
		}
	 });
}

var arrTimers = new Array();

function checkField(fieldID) {
		
	var arguments = new Object;
	arguments.method = 'validateField';
	arguments.fieldID = fieldID.substring(5);
	if (tinyMCE.get(fieldID) == null) {
		// put this in for checkboxes - particularly datalists - see how it affects others
		arguments.value = $("[@name='" + fieldID + "']").fieldValue().toString();
		//arguments.value = $("#" + fieldID).val();
	} else {
		arguments.value = tinyMCE.get(fieldID).getContent();
	}
	arguments.captchaUuid = ($("#captcha" + fieldID).length == 1 ?  $("#captcha" + fieldID).val() : '');
		

		
	remoteCall(arguments);	
		
	// <!--- only run item calculations if the field is in the list of fields using in calculations on this page --->
	for (var i=0;i<objForm.pipedItems.length;i++) {
		if (objForm.pipedItems[i] == fieldID.substring(5)) {
			calculatePageItems();
		}
	}
	
}

function initCheckField(fieldID) {
	
	// <!--- stop getting called on other textboxes - should be done further up --->
	if (fieldID.match(/^field(\d*)$/) != null) {
	
		// <!--- remove any old timers --->
		for (var i = 1; i <= arrTimers.length; i++) {
			clearTimeout(arrTimers.shift())
		}
		
		// <!--- check field when timer expires --->
		arrTimers.push(setTimeout("checkField('" + fieldID + "')", 500));
	}
}

function checkFieldTinyMce(e) {
	// <!--- in tinyMCE2 (at least) tinyMCE.getContent (used later) causes some sort of refocus which causes a jump when pressing enter so we don't order a checkfield and clear the queue if enter is pressed.  --->
	if (e.type == 'keyup' && e.keyCode == 9) {
		// <!--- do nothing - this is handled by the tabfocus plugin - otherwise it will tab onto the next tinymce box --->
	}	else if (e.type == 'keyup' && e.keyCode != 13) {
		initCheckField(tinyMCE.activeEditor.id);
	} else if (e.keyCode == 13) {
		for (var i = 1; i <= arrTimers.length; i++) {
			clearTimeout(arrTimers.shift())
		}
	}
}

function checkFieldDateTime(objCalender) {
	checkField(objCalender.params.inputField.id);
}

function doValidateField(fieldID, objErrors) {
						
	if (objErrors.recordcount == 0) {
		$("#field" + fieldID).parents(".item:first").removeClass("error");	
		$("#field" + fieldID).parents(".item:first").addClass("valid");
		
		$("#" + $("#field" + fieldID).parents(".item:first").attr("id") + " .itemerrors").hide();
	} else {
		$("#field" + fieldID).parents(".item:first").removeClass("valid");	
		$("#field" + fieldID).parents(".item:first").addClass("error");
				
		// <!--- FIXME: this will only show last error --->
		$("#" + $("#field" + fieldID).parents(".item:first").attr("id") + " .itemerrors").html(objErrors.data.dbitemmessage[0]);
		$("#" + $("#field" + fieldID).parents(".item:first").attr("id") + " .itemerrors").show();
		
	}
}

// <!--- FIXME: is this really the best way to do this? --->
function addRepeatable(fieldID) {
			
	var instanceID = parseInt($("#frmRepeatableInstancefield" + fieldID).attr("value")) + 1;
	
	$("#frmRepeatableInstancefield" + fieldID).val(instanceID);
	
	var itemHtml = $("#frmRepeatableAddfield" + fieldID).parents(".item:first").html();

	itemHtml = itemHtml.replace(/([a-z]+)="(field[0-9]+)"/g,'$1="$2_' + instanceID + '"');
		
	// <!--- work out where new instance should be inserted and add it --->
	var insertItem = $("#frmRepeatableAddfield" + fieldID).parents(".item:first")
	
	for (i=1; i<=instanceID-1; i++) {
		insertItem = insertItem.next()
	}
	
	insertItem.after('<li class="item group">' + itemHtml + '</li>');
	
	insertItem.next().children(".repeatableoptions").append('<input type="submit" id="frmRepeatableRemove' + fieldID + '_' + instanceID + '" name="frmRepeatableRemove' + fieldID + '_' + instanceID + '" value="Remove" style="margin-top: 10px; margin-left: 15px;" />');
	
	$('#frmRepeatableRemove' + fieldID + '_' + instanceID).bind("click", function(e) { removeRepeatable($(this).attr("id")); return false; });
	
	$("#frmRepeatableAddfield" + fieldID).remove();
	
}

function removeRepeatable(buttonID) {
	$("#" + buttonID).parent().parent().remove()
}

function getPostCodeIDs(itemID) {
	
	remoteCall( {
		method: 'getPostCodeIDs',		
		itemID: itemID,
		postcode: $("#frmPostcode" + itemID).val()
	});	
	
}

function doGetPostCode(itemID, objAddresses) {
	var postCodeList = '';
	
	for (i=0;i<objAddresses.recordcount;i=i+1)  {
		postCodeList = postCodeList + '<a href="javascript:getPostCodeAddress(' + itemID + ', ' + objAddresses.data.dbid[i] + ')">' +objAddresses.data.dbdescription[i] + '</a><br />';
		
	}
		
	$("#frmPostcodeList" + itemID).html(postCodeList);
}

function getPostCodeAddress(itemID, addressID) {
	remoteCall( {
		method: 'getPostCodeAddress',		
		itemID: itemID,
		addressID: addressID
	});	
}

function doGetPostCodeAddress(itemID, objAddress) {
		
	$("#item" + itemID + " input[@type='text']").eq(1).val(objAddress.addressLine1);
	$("#item" + itemID + " input[@type='text']").eq(2).val(objAddress.addressLine2);
	$("#item" + itemID + " input[@type='text']").eq(3).val(objAddress.addressLine3);
	$("#item" + itemID + " input[@type='text']").eq(4).val(objAddress.postTown);
	$("#item" + itemID + " input[@type='text']").eq(5).val(objAddress.postCode);	
	
	$("#frmPostcodeList" + itemID).html("");
	
}

function checkItemConditions(fieldID) {	
	remoteCall( {
		component: 'item',
		method: 'checkItemConditions',
		callback: 'doCheckItemConditions',
		value: $("[@name='field" + $("#field" + fieldID).attr("name").substr(5) + "']").fieldValue().toString(),
		fieldID: $("#field" + fieldID).attr("name").substr(5)
		
	});
}

function doCheckItemConditions(itemConditions) {
	for (i=0; i<itemConditions.recordcount; i=i+1)  {
		if (itemConditions.data.dbbranchactionreference[i] == 'itemshow') {
			$("#item" + itemConditions.data.dbactionvalue[i]).slideDown();
		} else if (itemConditions.data.dbbranchactionreference[i] == 'itemhide') {
			$("#item" + itemConditions.data.dbactionvalue[i]).slideUp();
		}
	}
}

// <!--- FIXME: might become calculate form at some point --->
function calculateItem(itemID) {
	// <!--- FIXME: ideally we would put this in an object but the form plugin doesn't seem to support this --->
	var serializedData = $('#item' + itemID).parents("form:first").formSerialize();
	
	serializedData = serializedData + "&remote=1";
	
	serializedData = serializedData + "&component=item";
	serializedData = serializedData + "&method=calculateItem";
	// <!--- FIXME: don't use a callback as it can't be interpreted by remoteCall --->
	//serializedData = serializedData + "&callback=doCalculateItem";
	serializedData = serializedData + "&itemID=" + itemID;
	
	remoteCall(serializedData);	
}

function doCalculateItem(itemID, itemHtml) {
	$('#item' + itemID).after(itemHtml);
	$('#item' + itemID).prev().remove();
}

function calculatePageItems() {
	// <!--- FIXME: ideally we would put this in an object but the form plugin doesn't seem to support this --->
	var serializedData = $('.form form').formSerialize();
	
	serializedData = serializedData + "&remote=1";
	serializedData = serializedData + "&itemid=" + $("input[@name='page']").val();
	serializedData = serializedData + "&component=form";
	serializedData = serializedData + "&method=calculatePageItems";
	// <!--- FIXME: don't use a callback as it can't be interpreted by remoteCall --->
	//serializedData = serializedData + "&callback=doCalculateItem";
	
	remoteCall(serializedData);	
}

function doCalculatePageItems(items) {

	for (i=0; i<items.recordcount; i=i+1)  {
		$('#item' + items.data.dbitemid[i]).before(items.data.dbitemhtml[i]).remove(); 
	}
	
	// <!--- unbind fields to stop them being bound twice --->
	$(".page .item *").unbind();
	
	// <!--- rebind actions to fields --->
	bindFields();
}

function bindFields() {
	
	// <!--- change works on unfocus rather than as you type so cant use initCheckField with it, keypress doens't support backspace plus other keys in ie --->	
	$(".page .item input[@type='text']").bind("keyup", function(e) { initCheckField(e.target.id); });
	
	$(".page .item select").bind("change", function(e) { checkField(e.target.id); });
	$(".page .item input[@type='radio']").bind("change", function(e) { checkField(e.target.name); });
	$(".page .item input[@type='checkbox']").bind("change", function(e) { checkField(e.target.name); });
	$(".page .item input[@type='file']").bind("change", function(e) { checkField(e.target.name); });
	
	// <!--- bind dynamic add to repeatable field buttons --->
	//$("li.page .item input[@type='submit'].repeatableAdd").bind("click", function(e) { addRepeatable($(this).attr("name").substr(21)); return false; });
	
	// <!--- bind conditions to fields --->
	// <!--- FIXME: want to do text/textarea when finished typing, also might want to do rest on change --->
	// <!--- FIXME: really only want to apply conditions to items with conditions --->
	//$(".page .item input[@type='text']").bind("keypress", function(e) { checkItemConditions($(this).attr("id").substr(5)); });
	$(".page .item input[@type='radio'],input[@type='checkbox']").bind("click", function(e) { checkItemConditions($(this).attr("id").substr(5)); });
	$(".page .item select").bind("change", function(e) { checkItemConditions($(this).attr("id").substr(5)); });	
}
