/************************************************************
          SOAPRESPONSE OBJECT - CONSTRUCTOR
 ************************************************************/
/**********************************************************************************
 * Parameters:
 *   <result> - the result status of the SOAP request
 * 
 * Description: 
 *   Creates an instance of a SOAPResponse object.
 **********************************************************************************/ 
SOAPResponse = function(result)
{
    this.result = result;
}


/************************************************************
          SOAPREQUEST OBJECT - CONSTRUCTOR
 ************************************************************/
/**********************************************************************************
 * Parameters:
 *   <serviceUrl> - the URL of the Web Service
 *   <serviceNS> - the namespace the Web Service uses
 *   <methodName> - the name of the SOAP method to invoke
 *   <soapVersion> - the version of SOAP to use (1.1 or 1.2); optional
 * 
 * Description: 
 *   Makes a call to the SOAP method described by this SOAPRequest object.
 **********************************************************************************/
SOAPRequest = function(serviceUrl, serviceNS, methodName, soapVersion)
{
    this.serviceUrl = serviceUrl;
    this.serviceNS = serviceNS;
    this.methodName = methodName;
    this.soapVersion = (soapVersion === undefined ? "1.2" : soapVersion);
    this.request = new XMLHttpRequest();
    this.response = new ActiveXObject("Msxml.DOMDocument");
    this.error = null;
    this.onError = null;
    this.onResponseReceived = null;
}

/************************************************************
          SOAPREQUEST OBJECT - MEMBERS
 ************************************************************/
 SOAPRequest.prototype =
 {
    /**********************************************************************************
     * Parameters:
     *   <requestParams> - an associative array containing the params to be sent with the SOAP request
     * 
     * Description: 
     *   Makes a call to the SOAP method described by this SOAPRequest object.
     **********************************************************************************/
    call:function(requestParams)
    {
        var soapResponse = null;
        var async = (this.onResponseReceived == null ? false : true);

        if (async)
        {
            var self = this;
            this.request.onreadystatechange = function() {self.onRequestStateChange()};
        }
        else
        {
            this.request.onreadystatechanged = null;
        }

        this.request.open("POST", this.serviceUrl, async);

        if (this.soapVersion == "1.1")
        {
            this.request.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
            this.request.setRequestHeader("SOAPAction", this.serviceNS + this.methodName);

            var soapRequestBody = '<?xml version="1.0" encoding="utf-8"?>';
            soapRequestBody += '<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/">';
            soapRequestBody += '<soap:Body>';
            soapRequestBody += '<' + this.methodName + ' xmlns="' + this.serviceNS + '">';
            soapRequestBody += this.getRequestParamString(requestParams);
            soapRequestBody += '</' + this.methodName + '>';
            soapRequestBody += '</soap:Body>';
            soapRequestBody += '</soap:Envelope>';

            this.request.send(soapRequestBody);
        }
        else if (this.soapVersion == "1.2")
        {
            this.request.setRequestHeader("Content-Type", "application/soap+xml; charset=utf-8");

            var soapRequestBody = '<?xml version="1.0" encoding="utf-8"?>';
            soapRequestBody += '<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">';
            soapRequestBody += '<soap12:Body>';
            soapRequestBody += '<' + this.methodName + ' xmlns="' + this.serviceNS + '">';
            soapRequestBody += this.getRequestParamString(requestParams);
            soapRequestBody += '</' + this.methodName + '>';
            soapRequestBody += '</soap12:Body>';
            soapRequestBody += '</soap12:Envelope>';

            this.request.send(soapRequestBody);
        }

        if (!async)
        {
            if (this.request.status != 200)
            {
                this.error = this.request.statusText;
                if (this.onError != null)
                {
                    this.onError(this);
                }
            }
            else
            {
                soapResponse = this.parseResponse(this.request.responseText);
            }
        }

        return soapResponse;
    },

    /**********************************************************************************
     * Parameters:
     *   none
     * 
     * Description: 
     *   Callback used internally when making an asynchronous request.
     **********************************************************************************/
    onRequestStateChange:function()
    {
        if (this.request.readyState == 4)
        {
            var soapResponse = null;

            if (this.request.status != 200)
            {
                this.error = this.request.statusText;
                if (this.onError != null)
                {
                    this.onError(this);
                }
            }
            else
            {
                soapResponse = this.parseResponse(this.request.responseText);
            }

            if (this.onResponseReceived != null)
            {
                this.onResponseReceived(this, soapResponse);
            }
        }
    },

    /**********************************************************************************
     * Parameters:
     *   <requestParams> - an associative array containing the params to be sent with the SOAP request
     * 
     * Description: 
     *   Internal method used to build the params section of the SOAP request XML.
     **********************************************************************************/
    getRequestParamString:function(requestParams)
    {
        var requestParamString = "";

        if (requestParams !== undefined)
        {
            for (var paramName in requestParams)
            {
                requestParamString += '<' + paramName + '>';
                requestParamString += requestParams[paramName];
                requestParamString += '</' + paramName + '>';
            }
        }

        return requestParamString;
    },

    /**********************************************************************************
     * Parameters:
     *   <responseText> - a string containing the response from the SOAP method invocation
     * 
     * Description: 
     *   Internal method used to parse the response from the SOAP method invocation and build a SOAPResponse object.
     **********************************************************************************/
    parseResponse:function(responseText)
    {
        var soapResponse = null;
        this.error = null;

        this.response.loadXML(responseText);
        if (this.response.parseError.errorCode != 0)
        {
            this.error = this.response.parseError.reason;
            if (this.onError != null)
            {
                this.onError(this);
            }
        }
        else
        {
            var responseElement = this.response.selectSingleNode("//" + this.methodName + "Response");
            if (responseElement == null)
            {
                this.error = "No valid response element found in the SOAP response.";
                if (this.onError != null)
                {
                    this.onError(this);
                }
            }
            else
            {
                soapResponse = new SOAPResponse(null);

                var resultNodeName = this.methodName + "Result";
                var responseElements = responseElement.selectNodes("*");
                for (var i = 0; i < responseElements.length; i++)
                {
                    var responseElement = responseElements[i];
                    if (responseElement.nodeName == resultNodeName)
                    {
                        soapResponse.result = responseElement.text;
                    }
                    else
                    {
                        soapResponse[responseElement.nodeName] = responseElement.text;
                    }
                }

                if (soapResponse.result == null)
                {
                    soapResponse = null;
                    this.error = "No valid result element found in the SOAP response.";
                    if (this.onError != null)
                    {
                        this.onError(this);
                    }
                }
                else if (soapResponse.result != "Ok")
                {
                    this.error = soapResponse.result;
                    if (this.onError != null)
                    {
                        this.onError(this);
                    }
                }
            }
        }

        return soapResponse;
    }
}

/************************************************************
          MESSENGERGADGETSERVICE OBJECT - CONSTRUCTOR
 ************************************************************/
 MessengerGadgetWebService = function()
 {
    this.url = WebServiceConstants.WEB_SERVICE_URL;
    this.ns = WebServiceConstants.WEB_SERVICE_NS;
 }
 
 /************************************************************
          MESSENGERGADGETSERVICE OBJECT - MEMBERS
 ************************************************************/
 MessengerGadgetWebService.prototype =
 {
	/**********************************************************************************
	 * Parameters:
	 *   <versionString> - the version string that will be tested
	 *   <callback> - callback function that will be called when the response is available
	 * 
	 * Description: 
	 *   Verifies if there is an update available for the supplied version.
	 **********************************************************************************/
    checkForUpdate:function(versionString, callback)
    {   
		debug("checkForUpdate");
        var soapRequest = new SOAPRequest(this.url, this.ns, "UpdateAvailable");
        soapRequest.onResponseReceived = callback;

        var soapRequestParams = new Object();
        soapRequestParams["versionString"] = versionString;
        soapRequest.call(soapRequestParams);
    },

	/**********************************************************************************
	 * Parameters:
	 *   <callback> - callback function that will be called when the response is available
	 * 
	 * Description: 
	 *   Gets the version string for the latest version.
	 **********************************************************************************/
    getCurrentVersionString:function(callback)
    {
        var soapRequest = new SOAPRequest(this.url, this.ns, "GetCurrentVersionString");
        soapRequest.onResponseReceived = callback;
        soapRequest.call();
    },

	/**********************************************************************************
	 * Parameters:
	 *   <callback> - callback function that will be called when the response is available
	 * 
	 * Description: 
	 *   Gets the URL where the latest version can be downloaded.
	 **********************************************************************************/
    getUpdateURL:function(callback)
    {
        var soapRequest = new SOAPRequest(this.url, this.ns, "GetUpdateURL");
        soapRequest.onResponseReceived = callback;
        soapRequest.call();
    }
}
