// ==============================================================================================================================
// Class ServerSideObject1
// ==============================================================================================================================
ServerSideObject1.prototype = new InterfaceElement1;
ServerSideObject1.prototype.constructor = ServerSideObject1;
ServerSideObject1.superclass = InterfaceElement1.prototype;

function ServerSideObject1 (oInterface, sClass) {
	if ( arguments.length > 0 ) {
		this.construct(oInterface, sClass);
		for ( var i = 2; i < arguments.length; i++ )
			this.addConstructorArgument(arguments[i]);
	}
}

//-----------------------------------------------------------------
// Method ServerSideObject1.construct()
//-----------------------------------------------------------------
ServerSideObject1.prototype.construct = function (oInterface, sClass) {
	ServerSideObject1.superclass.construct.call(this);
	this.interfaceObject = oInterface;
	this.constructorArgs = new Array();

	this.readonlySession = null;
	
	this.className = sClass;

	this.scriptURL = CUSTOMER_URL + '/api/serversideobject/index.php';
}

//-----------------------------------------------------------------
// Method ServerSideObject1.setConstructorArguments()
//-----------------------------------------------------------------
ServerSideObject1.prototype.addConstructorArgument = function (sArg) {
	this.constructorArgs.push(sArg);
}

//-----------------------------------------------------------------
// Method ServerSideObject1.setReadonlySession()
//-----------------------------------------------------------------
ServerSideObject1.prototype.setReadonlySession = function (bReadonly) {
	this.readonlySession = bReadonly;
}

//-----------------------------------------------------------------
// Method ServerSideObject1.callMethod()
//-----------------------------------------------------------------
ServerSideObject1.prototype.callMethod = function (sMethod) {
	this.methodName = sMethod;
	this.methodArgs = new Array();
	for ( var i = 1; i < arguments.length; i++ )
		this.methodArgs.push(arguments[i]);
	return this.sendRequest(false);
}

//-----------------------------------------------------------------
// Method ServerSideObject1.asyncCallMethod()
//-----------------------------------------------------------------
ServerSideObject1.prototype.asyncCallMethod = function (sMethod) {
	this.methodName = sMethod;
	this.methodArgs = new Array();
	for ( var i = 1; i < arguments.length; i++ )
		this.methodArgs.push(arguments[i]);
	return this.sendRequest(true);
}

//-----------------------------------------------------------------
// Method ServerSideObject1.sendRequest()
//-----------------------------------------------------------------
ServerSideObject1.prototype.sendRequest = function (bAsync) {
	var sURL = this.scriptURL;
	sURL += '?class=' + this.className;
	for ( var i = 0; i < this.constructorArgs.length; i++ )
		sURL += '&c_arg[]=' + this.constructorArgs[i];
	sURL += '&method=' + this.methodName;
	for ( var i = 0; i < this.methodArgs.length; i++ )
		sURL += '&m_arg[]=' + this.methodArgs[i];
	// document.write('URL = ' + sURL);
	if ( this.readonlySession != null )
		sURL += '&readonly_session=' + ( this.readonlySession ? 1 : 0 );
	sURL += '&timestamp=' + Math.random();
	
	var oHTTP = new HTTPRequest1(sURL, bAsync, 'GET');
	if ( bAsync ) {
		oHTTP.request(this, 'handleRequest');
	} else {
		oHTTP.request();
		this.httpResponse = oHTTP.getResponse();
		if ( this.checkFatalError(this.httpResponse) ) {
			if ( typeof(this.httpResponse) == 'string' )
				var oXML = new XMLDom1(this.httpResponse);
			else
				var oXML = this.httpResponse;
			// var oXML = this.interfaceObject.dom.createXMLObject(this.httpResponse);
			if ( this.checkXML(oXML) ) {
				if ( this.extractValue() )
					return true;
				else
					return false;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}
}

//-----------------------------------------------------------------
// Method ServerSideObject1.callOnReady()
//-----------------------------------------------------------------
ServerSideObject1.prototype.callOnReady = function (oObject, sMethod) {
	this.callOnReadyObject = oObject;
	this.callOnReadyMethod = sMethod;
}

//-----------------------------------------------------------------
// Method ServerSideObject1.callOnFail()
//-----------------------------------------------------------------
ServerSideObject1.prototype.callOnFail = function (oObject, sMethod) {
	this.callOnFailObject = oObject;
	this.callOnFailMethod = sMethod;
}

//-----------------------------------------------------------------
// Method ServerSideObject1.handleRequest()
//-----------------------------------------------------------------
ServerSideObject1.prototype.handleRequest = function (oHTTP) {
	this.httpResponse = oHTTP.getResponse();
	if ( this.checkFatalError(this.httpResponse) ) {
		if ( typeof(this.httpResponse) == 'string' )
			var oXML = new XMLDom1(this.httpResponse);
		else
			var oXML = this.httpResponse;
		// var oXML = this.interfaceObject.dom.createXMLObject(this.httpResponse);
		if ( this.checkXML(oXML) ) {
			if ( this.extractValue() )
				this.requestReady();
			else
				this.requestFailed();
		} else {
			this.requestFailed();
		}
	} else {
		this.requestFailed();
	}
}

//-----------------------------------------------------------------
// Method ServerSideObject1.requestReady()
//-----------------------------------------------------------------
ServerSideObject1.prototype.requestReady = function () {
	this.sendEvent('ready');
	if ( this.callOnReadyObject && this.callOnReadyMethod ) 
		this.callOnReadyObject[this.callOnReadyMethod].apply(this.callOnReadyObject, [this]);
}

//-----------------------------------------------------------------
// Method ServerSideObject1.requestFailed()
//-----------------------------------------------------------------
ServerSideObject1.prototype.requestFailed = function () {
	this.sendEvent('fail');
	if ( this.callOnFailObject && this.callOnFailMethod ) 
		this.callOnFailObject[this.callOnFailMethod].apply(this.callOnFailObject, [this]);
}

//-----------------------------------------------------------------
// Method ServerSideObject1.checkFatalError()
//-----------------------------------------------------------------
ServerSideObject1.prototype.checkFatalError = function (sResponse) {
	if ( typeof(sResponse) == 'string' ) {
		var aMatch = sResponse.match(/<b>Fatal error<\/b>: (.*) <b>(.*)<\/b> on line <b>(.*)<\/b>/); 
		if ( aMatch ) {
			this.setError('Fatal error: ' + aMatch[1] + ' (line ' + aMatch[3] + ' of ' + aMatch[2] + ')');
			return false;
		} else {
			return true;
		}
	} else {
		return true;
	}
}

//-----------------------------------------------------------------
// Method ServerSideObject1.checkXML()
//-----------------------------------------------------------------
ServerSideObject1.prototype.checkXML = function (oXML) {
	if ( oXML ) {
		switch ( oXML.nodeName ) {
				
			case 'no-session':
				this.error = new Error1("no_session");
				return false;
				
			case 'error':
				var sType		= XML.getCDATA(XML.namedChildNode(oXML, 'type'));
				var sText		= XML.getCDATA(XML.namedChildNode(oXML, 'text'));
				var sSubText	= XML.getCDATA(XML.namedChildNode(oXML, 'subtext'));
				this.error = new Error1(sType, sText, sSubText);
				return false;
				
			case 'return-value':
				this.returnXML = oXML;
				return true;
				
			case '#document':
				return this.checkXML(oXML.childNodes[0]);

			case 'xml':
				return this.checkXML(oXML.nextSibling);
				
			default:
				this.setError('Invalid response: ' + this.httpResponse);
				return false;
		}
	} else {
		this.setError('Invalid XML: ' + this.httpResponse);
		return false;
	}
}

//-----------------------------------------------------------------
// Method ServerSideObject1.getReturnValue()
//-----------------------------------------------------------------
ServerSideObject1.prototype.getReturnValue = function () {
	return this.returnValue;
}

//-----------------------------------------------------------------
// Method ServerSideObject1.getError()
//-----------------------------------------------------------------
ServerSideObject1.prototype.getError = function () {
	return this.error;
}

//-----------------------------------------------------------------
// Method ServerSideObject1.setError()
//-----------------------------------------------------------------
ServerSideObject1.prototype.setError = function (sText) {
	var sError = '';
	sError += this.className + '(' + this.constructorArgs.join(',') + ') :: ';
	sError += this.methodName + '(' + this.methodArgs.join(',') + ') returned an error.';
	this.error = new Error1('error', sError, sText);
}

//-----------------------------------------------------------------
// Method ServerSideObject1.extractValue()
//-----------------------------------------------------------------
ServerSideObject1.prototype.extractValue = function (sXML) {
	var sType = this.returnXML.selectSingleNode('@type').nodeValue;
	var sValue = '';
	for ( var i = 0; i < this.returnXML.childNodes.length; i++ )
		sValue += this.returnXML.childNodes[i].nodeValue;
	switch ( sType ) {
		case 'null':
		case 'NULL':
			this.returnValue = null;
			return true;

		case 'integer':
		case 'int':
			if ( sValue.match(/^\d+$/) ) {
				this.returnValue = parseInt(sValue);
				return true;
			} else {
				this.setError('Invalid return value; integer expected (' + sValue + ')');
				return false;
			}

		case 'float':
			if ( sValue.match(/^\d+(\.\d+)?$/) ) {
				this.returnValue = parseFloat(sValue);
				return true;
			} else {
				this.setError('Invalid return value; float expected (' + sValue + ')');
				return false;
			}

		case 'boolean':
			switch ( sValue.toLowerCase() ) {
				case 'true':
				case '1':
					this.returnValue = true;
					return true;
				case 'false':
				case '0':
				case '':
					this.returnValue = false;
					return true;
				default:
					this.setError('Invalid return value; boolean expected (' + sValue + ')');
					return false;
			}

		case 'string':
			this.returnValue = sValue;
			return true;

		default:
			this.setError('Invalid return value; unknown type (' + sType + ')');
			return false;

	}
}


