dojo.provide("ibm_soap.rpc.SoapService");

dojo.require("dojo.rpc.RpcService");
dojo.require("dojox.data.dom");
dojo.require("dojox.xml.DomParser");
dojo.require("dojox.wire.ml.util");
dojo.require("ibm_soap.io.ws");

dojo.declare("ibm_soap.rpc.SoapService", dojo.rpc.RpcService,{
	contentType:"text/xml",
	strictArgChecks:false,
	soapResponse:null,
	bind:function(method, parameters, deferredRequestHandler, url, soapParms){
		//	summary: Performs the XHR communication to the server
		// description: 
		//		rawXHRPost is called with the URL, the content to be posted is
		// 		generated by _getPostContent().
		// method:String
		//	A method name
		// parameters:
		//	An array of parameters
		// deferred:
		//	'Deferred'
		// url:
		//	A URL for the method
	    console.log("ibm_soap.rpc.SoapService.bind()");		
	    console.log("SoapService()..bind");
	    console.log(this.serviceUrl);
	   	var bindInfo = {
			url: url || this.serviceUrl,
			postData: this._getPostContent(method,parameters,soapParms.namespace),
			contentType: this.contentType,
			handleAs: "xml",
			headers: {"SOAPAction": (soapParms.soapAction ? soapParms.soapAction : '""')}
		};

		//IE has a problem with some XML formats, have to work around 
		//by modifying the return a bit.
		if(dojo.isIE){
			bindInfo.handleAs = "text";
		}
		var def = dojo.rawXhrPost(bindInfo);
		def.addCallback(this.resultCallback(deferredRequestHandler));
		def.addErrback(this.errorCallback(deferredRequestHandler));
		console.log(" / ibm_soap.rpc.SoapService.bind()");		
	},
	
	parseResults: function(data) {
		// summary:
		//	Return an element
		// data:
		//	Result data
	    console.log("ibm_soap.rpc.SoapService.parseresults()");
	    this.soapResponse = data;
	    this.onComplete();
		//Handle IE's quirk.
		if(dojo.isIE){
			var regExp = new RegExp("xmlns:[A-Za-z0-9]+=([\"\'])\\1", "i");
			var loc = data.search(regExp);
			while(loc >= 0) {
				var i;
				var stop = -1;
				for(i = loc; i < data.length; i++){
					if(data.charAt(i) === '='){
						stop = i;
						break;
					}
				}
				if(stop > -1){
					var newString = data.substring(0,stop);
					newString += "=\"ieWorkaround_" + (new Date()).getTime() + "\"";
					newString += data.substring(stop + 3, data.length);
					data = newString;
				}
				loc = data.search(regExp);
			}
			data = dojox.data.dom.createDocument(data);
		}
		if (data && data.nodeType == 9) {
			if (data.getElementsByTagNameNS){
				return data.getElementsByTagNameNS(ibm_soap.io.ws.soap.URI,"Body")[0];
			}else{
				var nl = data.getElementsByTagName("*");
				for(var i=0;i<nl.length;i++){
					var node = nl[i];
					var localname = (node.nodeName.indexOf(":") == -1) ?
										node.nodeName : 
										node.nodeName.split(":")[1];
					var namespace = node.namespaceURI;
					if (localname == "Body" && namespace == ibm_soap.io.ws.soap.URI){
						return node;
					}
				}
			}
		}
	    console.log(" / ibm_soap.rpc.SoapService.parseresults()");		
		return data;
	},
	generateMethod: function(/*string*/ method, /*array*/ parameters, /*string*/ url, soapParms){
			// summary:
			// 		generate the local bind methods for the remote object
			console.log("Inside ibm_soap.rpc.SoapService.generateMethod");
			return dojo.hitch(this, function(){
				var deferredRequestHandler = new dojo.Deferred();
				console.log(arguments.length);
				console.log(parameters.length);
				// if params weren't specified, then we can assume it's varargs
				if( (this.strictArgChecks) &&
					(parameters != null) &&
					(arguments.length != parameters.length)
				){
				// put error stuff here, no enough params
					throw new Error("Invalid number of parameters for remote method.");
				}else{
					this.bind(method, dojo._toArray(arguments), deferredRequestHandler, url, soapParms);
				}
				return deferredRequestHandler;
			});
	},	
	processSmd: function(/*json*/ object){
			// summary:
			// 		callback method for reciept of a smd object.  Parse the smd
			// 		and generate functions based on the description
			console.log("Calling the new process SMD");
			if(object.methods){
				dojo.forEach(object.methods, function(m){
					if(m && m["name"]){
						console.log("processSmd:Try to generate method for " + m.name);
						this[m.name] = this.generateMethod(	m.name,
											m.parameters, 
											m["url"]||m["serviceUrl"]||m["serviceURL"], m._soapBindingParameters);
						if(!dojo.isFunction(this[m.name])){
							console.log("RpcService: Failed to create", m.name, "()");
						} else {
							console.log("RpcService: Successfully created ", m.name, "()");
						}
					}
				}, this);
			}
			this.serviceUrl = object.serviceUrl||object.serviceURL;
			
	},
	onComplete:function() { /* Intentionally empty */ },
	_getPostContent: function(method, parameters, namespace) {
		
	    console.log("ibm_soap.rpc.SoapService._getPostContent() / ");
	    var node = parameters[0];
		if (node) {
			if (node instanceof dojox.wire.ml.XmlElement) {
				node = node.element;
			}
			else if (node.nodeType == 9) {
				node = node.documentElement;
			}
   			if(typeof XMLSerializer != 'undefined') console.log(new XMLSerializer().serializeToString(node));
			console.log("SoapService._getPostContent: node=" + node);
			//var nsuri = 'http://example'; // FIXME: temporary for test .....
			// var nsuri = 'urn:xmethods-CurrencyExchange'; // FIXME: temporary for test .....
			var qn_op = new ibm_soap.io.ws.QName(method, namespace);
			// var qn_op = new ibm_soap.io.ws.QName(method, nsuri);
		    var env = new ibm_soap.io.ws.soap.Envelope();
		    // TODO: need consider service type : document-literal, document-wrapped, rpc-encoded.
		    env.createBody().setRpc(qn_op, node, null /*encodingstyle*/);
		    // env.createBody().setDocumentBody(qn_op, node, null /*encodingstyle*/);
   			if(typeof XMLSerializer != 'undefined') console.log(new XMLSerializer().serializeToString(env.asElement().ownerDocument));
			return env.asElement().ownerDocument;
		}
		return null;
	}

});
