function SPC_Validation_AjaxClientHandler(gg_form) {
	
	var gee_form = gg_form;
	
	_initialize = function() {
		console.log("@@@ SPC_Validation_AjaxClientHandler:: Init called");
	};
	
	this._validSPC = function(code) {
		var spc = code.trim();
		var ga = new GlideAjax('HumanResourcesAsyncQueries');
		
		console.log("@@@ SPC_Validation_AjaxClientHandler::_validSPC called. ["+spc+"] length["+spc.length+"]");
		if(spc.length!=9 || spc.charAt(0)!='5') 
		{
			return false;
		}
		ga.addParam('sysparm_name', 'getSPCvalidity'); //getRequest
		ga.addParam('sysparm_spc', spc);
		ga.getXMLWait(function (response) { (function tmp(response /*optional additional parameteres*/){
			var answer = response.responseXML.documentElement.getAttribute("answer");
		
			console.log("@@@ (valid SPC) GOT ["+answer+"]");
			var set = [];
			set = answer.split('#;#');
			var options = [];
			var spc = 0; // array index
			var validity = 1; // array index
			var longDesc = 2;
			options = answer.split('#,#');
		
			if(options[validity]!='valid') {
				return false;
			} 	
			
			return true;
		})(response /*optional additional parameteres*/); });		
	};

	this._singleSPC = function(code, varName) {
		var spc = code.trim();
		var ga = new GlideAjax('HumanResourcesAsyncQueries');
		
		if(spc.length!=9 || spc.charAt(0)!='5') 
		{
			gee_form.showFieldMsg(varName, "The SPC code is not valid. The code needs to be nine digits long and start with a five(5).", 'error');
			return;
		}
		ga.addParam('sysparm_name', 'getSPCvalidity'); //getRequest
		ga.addParam('sysparm_spc', spc);
		ga.getXML(function (response) { (function tmp(response /*optional additional parameteres*/){
			var answer = response.responseXML.documentElement.getAttribute("answer");
		
			console.log("@@@ (SINGLE) GOT ["+answer+"]");
			var set = [];
			set = answer.split('#;#');
			var options = [];
			var spc = 0; // array index
			var validity = 1; // array index
			var longDesc = 2;
			options = answer.split('#,#');
		
			if(options[validity]!='valid') {
				gee_form.showFieldMsg(varName, "The SPC code is not valid. Please enter a valid code.", 'error');
			} else {
				gee_form.showFieldMsg(varName, options[longDesc], 'info');
			}	
			
		})(response /*optional additional parameteres*/); });		
	};
	
	this._multiSPC = function(code, varName) {
		var ga = new GlideAjax('HumanResourcesAsyncQueries');

		spc = code.replace(/\s/g, ''); // remove all whitespace
		
		spcSet = spc.split(';');
		// make unique
		var seen = '';
		var dup = '';
		var spcErrors = [];
		for(var i=0; i<spcSet.length; ++i) {
				
			// filter for unique items
			if(seen.indexOf(spcSet[i])==-1) {
				// not seen this one before add to list
				seen += ((seen=='') ? '' : ',') + spcSet[i];
			} else /* duplicate */ {
				dup += ((dup=='') ? '' : ',') + spcSet[i];
			}
			// build list of format errors
			if(spcSet[i].length!=9 || spcSet[i].charAt(0)!='5') 
			{
				spcErrors.push(spcSet[i]);
			}
		}
			
		var unique = seen.split(',');
		if(spcErrors.length>0) {
			gee_form.showFieldMsg(varName, "One or more SPC code(s) are not valid. The code needs to be nine digits long and start with a five(5).", 'error');
			// popup listing errors
			var list = spcErrors.join(',');
			alert("The following SPC code(s) are incorrectly formated. Please review and correct. ["+list+"]");
			return;
		} else if(unique.length!=spcSet.length) {
			alert("SPC List contains duplicate entries. These SPCs occur more than once["+dup+"] please remove duplicates.");
			g_form.showFieldMsg(varName, "Please remove duplicate SPCs.", 'error');
			return;
		}
		ga.addParam('sysparm_name', 'getSPCSetValidity'); //getRequest
		ga.addParam('sysparm_spc', spc);
		ga.getXML(function (response) { (function tmp(response /*optional additional parameteres*/){
			var answer = response.responseXML.documentElement.getAttribute("answer");
		
			console.log("@@@ (MULTI) GOT ["+answer+"]");
			var set = [];
			var optIdx = 0;// array index
			var optSpc = 1; 
			var optValidity = 2; 
			var optLongDesc = 3;
			var ivOrgSPCs = 1;
			var ivFailedSPCs = 2;
			set = answer.split('#;#');
				
			// debug
			//for(var x=0; x<set.length; ++x) {
			//	console.log("@@@ ["+x+"]:["+set[x]+"]");
			//}
				
			var results = [];
			for(var i=1; i < set.length; ++i) {
				var options = [];
				options = set[i].split('#,#');
		
				// list of SPC descriptions
				results[i] = {idx: options[optIdx], spc: options[optSpc], state: (options[optValidity]=='valid'), dest: options[optLongDesc]};
			}
			var invalidLst = set[0].split('#,#');
			console.log("@@@ invalidLst:: 0["+invalidLst[0]+"] 1["+invalidLst[1]+"] 2["+invalidLst[2]+"] 3["+invalidLst[3]+"]");
			if(invalidLst[ivFailedSPCs]!='') {
				// one or more SPCs failed validation.
				alert("SPC List contains invalid entries. These SPCs ["+invalidLst[ivFailedSPCs]+"] are not valid. please review and correct.");
				gee_form.showFieldMsg(varName, "List contains invalid SPCs["+invalidLst[ivFailedSPCs]+"]. Please correct.", 'error');
				return;
			} else /* Present valid list in a pop-up */ {
				var validList = 'The following details are available for listed SPCs;\n';
					
				for(var vl=1; vl<results.length; ++vl) {
					validList += "\t"+results[vl].spc+" :: "+results[vl].dest + "\n";
				}
					
				alert(validList);
				gee_form.showFieldMsg(varName, "All listed Sub Project codes are valid.", 'info');
					
			}			
		})(response /*optional additional parameteres*/); });
	};
	
	//
	//  Used on submission of a form. to validate submission
	//
	this.isValidSPC = function(SubProjCode) {
		try{
			//console.log("@@@ SPC_Validation_AjaxClientHandler::isValidSPC called. ["+SubProjCode+"]");
			return this._validSPC(SubProjCode);
		} catch(err) {
			console.log("@@@ an error in SPC_Validation_AjaxClientHandler::isValidSPC. message["+err.message+"]");			
		}
	};
	//
	// 
	// Validate the single SPC provided. Held in the variable named varName
	// this method operates on the variable given.
	//
	this.validateSingle = function(varName, newValue) {
		try {
			// empty is allowed if not mandatory
			if(!gee_form.isMandatory(varName) && newValue == '' ) {
				// empty is permitted value
				// clear any messages
				gee_form.hideFieldMsg(varName, true);	
				return;
			}
		
			gee_form.hideFieldMsg(varName, true);
			var spc = gee_form.getValue(varName) + "";
			if(spc.indexOf(';')==-1) {
				// single SPC code
				this._singleSPC(spc, varName);
			} else {
				gee_form.showFieldMsg(varName, "Only a single code is expected. this variable must not contain semi-colons.", 'error');
			}
		
		} catch(err) {
			console.log("@@@ an error in SPC_Validation_AjaxClientHandler::validateSingle. message["+err.message+"]");
		}				
	};
	
	//
	// Validate one or more provided Subproject codes, held in the variable named varName
	// this method operates on the variable given.
	//
	this.validate = function(varName, newValue) {
		try {
			// empty is allowed if not mandatory
			if(!gee_form.isMandatory(varName) && newValue == '' ) {
				// empty is permitted value
				// clear any messages
				gee_form.hideFieldMsg(varName, true);	
				return;
			}
		
			gee_form.hideFieldMsg(varName, true);
			var spc = gee_form.getValue(varName) + "";
			if(spc.indexOf(';')==-1) {
				// single SPC code
				this._singleSPC(spc, varName);
			} else {
				// multiple SPC codes - at least two
				this._multiSPC(spc, varName);
			}
		
		} catch(err) {
			console.log("@@@ an error in SPC_Validation_AjaxClientHandler::validate. message["+err.message+"]");
		}			
	};
	
	this.type = 'SPC_Validation_AjaxClientHandler';
}