///
// Web Service Configuration
///
var ws_autodetect = true

var ns_base = 'http://higherfunction.com/Pincushion';

var ws_ssl = false

var ws_version = '0.8.1.4048'
var ws_session_id = ''

var ws_host = 'www.mypincushion.com'
var web_host = 'www.mypincushion.com'


if (ws_autodetect)
{
	if (window.location)
	{
		var host = window.location.hostname
		var proto = window.location.protocol
		
		if (host)
		{
			ws_host = host
			web_host = host
			
			ws_ssl = (proto == "https:")
		}
	}
	else if (document.URL)
	{	
		if (document.URL.indexOf('://localhost') > 0) {
			ws_host = 'localhost'
			web_host = 'localhost'
		}
		
		ws_ssl = (document.URL.substring(0, 5) == "https")
	}
}

var web_base = "http"
if (ws_ssl) web_base += "s"
web_base += "://" + web_host + getRootedUrl("/")

var ws_base = "http"
if (ws_ssl) ws_base += "s"
ws_base += "://" + web_host + getRootedUrl("/Server")


///
// Web Service code
///


function pcException(request, error)
{
	var url = "---"
	var action = "---"
	var httpCode = "000"
	var httpMsg = "---"
	var headers = "---"
	

	try { url = request.url } catch (ex) {}
	try { action = request.options.requestHeaders['SOAPAction'] } catch (ex) {}
	try { httpCode = request.transport.status } catch (ex) {}
	try { httpMsg = request.transport.statusText } catch (ex) {}
	try { headers = request.transport.getAllResponseHeaders() } catch (ex) {}

	var message = "Sorry, a naughty Pincushion error has occurred."
	try { message += "\r\nError: "+error.name+" :: "+error.message } catch (ex) {}
	try { message += "\r\n\r\nIn: "+error.fileName+":"+error.lineNumber } catch (ex) {}

	try {
		if (error.stack)
			message += "\r\n\r\nStack:\r\n\r\n"+error.stack
	} catch (ex) {}


	
	if (url || action || httpCode)
		message += "\r\nLast AJAX Call State...\r\nURL: "+url
			+ "\r\nSOAPAction: "+action
			+ "\r\n\r\nHTTP Response: "+httpCode+" ("+httpMsg+")"
			+ "\r\nHTTP Headers...\r\n"+headers
	if (request.responseText)
		message += "\r\n\r\n"+request.responseText
		
	//blog(message)
}

function getTransport()
{
    try {
      return new XMLHttpRequest()
    } catch(ex) {}
    try {
      return new ActiveXObject('Msxml2.XMLHTTP')
    } catch(ex) {}
    try {
      return new ActiveXObject('Microsoft.XMLHTTP')
    } catch(ex) {}
    
    //blog("No AJAX transport avilable!", 4)
    return false
}



function Soap(ws, funcname, content, completionHandler, errorHandler)
{
  refreshSession();

	this.transport = getTransport()
	if (! this.transport)
	{
		if (errorHandler)
			errorHandler(this, {"name":"noXMLRequest", "message":"Failed to find a functional XMLHttpRequest mechanism"})
		return
	}
	
	this._complete = false
	this.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']
	
	this.onComplete = completionHandler
	this.onError = (errorHandler) ? errorHandler : pcException
	
	this.onStateChange = bind(this, function() {
		var that = this

		var readyState = that.transport.readyState;
    	if (readyState > 1 && !((readyState == 4) && that._complete))
      	that.respondToReadyState(this.transport.readyState);
    })
    
    this.success = bind(this, function() {
	    return !this.transport.status
	        || (this.transport.status >= 200 && this.transport.status < 300);
  	})
  	
    this.respondToReadyState = bind(this, function(readyState) {

    	var state = this.Events[readyState];
    	var transport = this.transport
    	if (state == 'Complete') {
       		this._complete = true;
    	}

    	try {
    		var f = this["on"+state]
    		if (f) 
    			f(transport)
    	} catch (ex) {
    	}

    	if (state == 'Complete') {
      		// avoid memory leak in MSIE: clean up
      		this.transport.onreadystatechange = function() {};
    	}
    })
    
    this.reqBody = soappacket(ns_base, ws, funcname, content); 
    this.url = ws_base + '/' + ws;
    this.soapAction = ns_base /*+ "/" + ws */+ "/" + funcname;

//blog("SOAP :: POST ==> "+this.url)

    
    
    this.transport.onreadystatechange = this.onStateChange

    this.transport.open("POST", this.url, true)
    
	this.transport.setRequestHeader("SOAPAction", this.soapAction);
	this.transport.setRequestHeader("Accept", "text/javascript, text/html, application/xml, text/xml, */*");
	this.transport.setRequestHeader("ServerVersion", ws_version);
	this.transport.setRequestHeader("Content-type", "text/xml; charset=utf-8");
	this.transport.setRequestHeader("Content-length", this.reqBody.length);
    
  this.transport.send(this.reqBody);
}

function refreshSession()
{
  if (typeof(sendPincushionMessage) != "undefined")
    sendPincushionMessage("action=refresh_session")
}

function Post(path, content, completionHandler, errorHandler)
{
  refreshSession();

	this.transport = getTransport()
	if (! this.transport)
	{
		if (errorHandler)
			errorHandler(this, {"name":"noXMLRequest", "message":"Failed to find a functional XMLHttpRequest mechanism"})
		return
	}
	
	this._complete = false
	this.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']
	
	this.onComplete = completionHandler
	this.onError = (errorHandler) ? errorHandler : pcException
	
	this.onStateChange = bind(this, function() {
		var that = this

		var readyState = that.transport.readyState;
    	if (readyState > 1 && !((readyState == 4) && that._complete))
      	that.respondToReadyState(this.transport.readyState);
    })
    
    this.success = bind(this, function() {
	    return !this.transport.status
	        || (this.transport.status >= 200 && this.transport.status < 300);
  	})
  	
    this.respondToReadyState = bind(this, function(readyState) {

    	var state = this.Events[readyState];
    	var transport = this.transport
    	if (state == 'Complete') {
       		this._complete = true;
    	}

    	try {
    		var f = this["on"+state]
    		
    		if (f) 
    			f(transport)
    	} catch (ex) {
    	}

    	if (state == 'Complete') {
      		// avoid memory leak in MSIE: clean up
      		this.transport.onreadystatechange = function() {};
    	}
    })
    
    this.reqBody = content; 
    this.url = web_base + path;
    
    this.transport.onreadystatechange = this.onStateChange

    this.transport.open("POST", this.url, true)
    
	this.transport.setRequestHeader("Accept", "text/javascript, text/html, application/xml, text/xml, */*");
	this.transport.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
	this.transport.setRequestHeader("Content-length", this.reqBody.length);
    
  this.transport.send(this.reqBody);
}

function DoPost(path, onComplete)
{
    while (path.substr(0, 1) == '/')
        path = path.substr(1)
    var url = web_base + path

    var dl = new Ajax.Request(
        url, 
        {
            method: 'post', 
            onComplete: onComplete,
            postBody: "",
			onException: pcException
        })
    
}

function soappacket(xmlns, service, funcname, content)
{
    var packet = soapheader(xmlns, service, funcname)
    packet += content
    packet += soapfooter(funcname)

    return packet
}

function soapheader(xmlns, service, funcname)
{
	var packet = '<?xml version="1.0" encoding="utf-8"?>\n'
    packet += '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">\n'
	packet += '  <soap:Header>\n'
	packet += '    <ServerVersion xmlns="http://higherfunction.com/Pincushion/">\n'
	packet += '      <Version>' + ws_version + '</Version>\n'
	packet += '    </ServerVersion>\n'
	if (ws_session_id && ws_session_id != "expired") {
	    packet += '    <SessionID xmlns="http://higherfunction.com/Pincushion/">\n'
	    packet += '      <ID>' + ws_session_id + '</ID>\n'
	    packet += '    </SessionID>\n'
	}
	packet += '  </soap:Header>\n'
    packet += '  <soap:Body>\n'
    packet += '    <'+funcname+' xmlns="'+xmlns+'/'/*+service*/+'">\n'
    
    return packet
}

function soapheaderForLogin(xmlns, service, funcname)
{
	var packet = '<?xml version="1.0" encoding="utf-8"?>\n'
    packet += '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">\n'
	packet += '  <soap:Header>\n'
	packet += '    <ServerVersion xmlns="http://higherfunction.com/Pincushion/">\n'
	packet += '      <Version>' + ws_version + '</Version>\n'
	packet += '    </ServerVersion>\n'
	packet += '  </soap:Header>\n'
    packet += '  <soap:Body>\n'
    packet += '    <'+funcname+' xmlns="'+xmlns+'/'/*+service*/+'">\n'
    
    return packet
}


function soapfooter(funcname)
{
    var packet = '    </'+funcname+'>\n'
    packet += '  </soap:Body>\n'
    packet += '</soap:Envelope>\n'
    
    return packet
}

function soap12header(xmlns, service, funcname)
{
	var packet = '<?xml version="1.0" encoding="utf-8"?>\n'
	packet += '<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">\n'
    packet += '  <soap12:Body>\n'
    packet += '    <'+funcname+' xmlns="'+xmlns/*+'/'+service*/+'">\n'
    
    return packet
}
function soap12footer(funcname)
{
    var packet = '    </'+funcname+'>\n'
    packet += '  </soap12:Body>\n'
    packet += '</soap12:Envelope>\n'
    
    return packet
}

function ServiceResponse(status, message)
{
	this.Status = status
	this.Message = message
	this.Data = new Array()
	this.Token = ""
}

// checks an AJAX response to ensure it's valid soap/xml and we didn't get access denied
function ValidSoapResponse(response)
{
  if (response.status == 401) { // not logged in
    return false
  }
  if (response.status < 200 || response.status >= 400) { // HTTP error / unhandled status
    return false
  }
  if (! response.responseXML)
    return false
    
  var lmnts = response.responseXML.getElementsByTagName("Body")
  if (lmnts && lmnts.length > 0)
    return true
  lmnts = response.responseXML.getElementsByTagName("soap:Body")
  return (lmnts && lmnts.length > 0)
}

/*
  checks the supplied XML for a valid ServiceResponse object from the FUNCNAME web service function
  returns a ServiceResponse object mirroring the XML response
 */
function CheckSoapResponse(funcname, xml)
{
	if (! xml)
		return new ServiceResponse(501, "Server did not return valid XML")
		
	var response = new ServiceResponse(502, "Invalid Server Response")

	var lmnts = xml.getElementsByTagName(funcname+"Result")
	
	if (lmnts && lmnts.length > 0) {
		var regRes = lmnts.item(0)
		
		for (var i=0; i<regRes.childNodes.length; i++) {
			var lmnt = regRes.childNodes.item(i)
			if (lmnt && lmnt.firstChild) {
				switch (lmnt.nodeName)
				{
					case "Status":
						var status = parseInt(lmnt.firstChild.nodeValue)
						if (isNaN(status))
					    	status = 400
						response.Status = status
						break
					case "Message":
						response.Message = lmnt.firstChild.nodeValue
						break
					case "Data":
						response.Data = lmnt.firstChild.nodeValue
						break
					case "Token":
						response.Token = lmnt.firstChild.nodeValue
						break
					default:
						if (lmnt.firstChild)
							response[lmnt.nodeName] = lmnt.firstChild.nodeValue
				}
			}
		}
	}

    return response
}

function StringToXml(strvalue)
{
    var dom
    // code for IE
    if (window.ActiveXObject) {
        dom = new ActiveXObject("Microsoft.XMLDOM")
        dom.async = "false"
        dom.loadXML(strvalue)
    }
    // code for Mozilla, Firefox, Opera, etc.
    else
    {
        var parser = new DOMParser()
        dom = parser.parseFromString(strvalue,"text/xml")
    }

    if (dom && dom.documentElement)
        return dom.documentElement
    else
        return false
}


function convertXmlNode(xmlNode)
{
	if (! xmlNode || ! xmlNode.childNodes)
		return null
		
	var outp = new Array()
	
	for (var j=0; j<xmlNode.childNodes.length; j++) {
		var lmnt = xmlNode.childNodes.item(j)
		if (lmnt.nodeName)
		{
			outp[lmnt.nodeName] = ""
			if (lmnt.firstChild)
				outp[lmnt.nodeName] = lmnt.firstChild.nodeValue
		}
	}

	return outp
}


function XmlValue(dom, tag)
{
	var elements = dom.getElementsByTagName(tag)	
	if (elements && elements.length > 0)
	{
		if (elements.item(0).firstChild)
			return elements.item(0).firstChild.nodeValue
	}
	
	return null
}

function XmlValueList(dom, tag)
{
	var values = new Array()
	var elements = dom.getElementsByTagName(tag)	
	
	if (elements && elements.length > 0)
	{
		for (var i=0; i<elements.length; i++)
			if (elements.item(i).firstChild)
				values.push(elements.item(i).firstChild.nodeValue)
	}
	
	return values
}
