function SOAPParser() {
}

SOAPParser.invoke = function (url, methodName, inputXML, transformUrl, async, callback, key) {

    if (async)
        SOAPParser._loadWsdl(url, methodName, inputXML, transformUrl, async, callback, key);
    else
        return SOAPParser._loadWsdl(url, methodName, inputXML, transformUrl, async, callback, key);
}

SOAPParser._loadWsdl = function (url, method, paramXML, transformUrl, async, callback, key) {
    // load from cache?
    var wsdl = SOAPParser_cacheWsdl[url];
    if (wsdl + "" != "" && wsdl + "" != "undefined")
    return SOAPParser._sendSoapRequest(url, method, paramXML, async, callback, transformUrl, wsdl, key);
    // get wsdl
    var xmlHttp = SOAPParser._getXmlHttp();
    xmlHttp.open("GET", url + "?wsdl", async);
    if (async) {
        xmlHttp.onreadystatechange = function () {
            if (xmlHttp.readyState == 4)
            SOAPParser._onLoadWsdl(url, method, paramXML, transformUrl, async, callback, xmlHttp, key);
        }
    }
    xmlHttp.send(null);
    if ( ! async)
    return SOAPParser._onLoadWsdl(url, method, paramXML, transformUrl, async, callback, xmlHttp, key);
}

SOAPParser_cacheWsdl = new Array();

SOAPParser._onLoadWsdl = function (url, method, paramXML, transformUrl, async, callback, req, key) {
    var wsdl = req.responseXML;
    if ( ! wsdl ) {
        PhasePick.errorMsg("Unable to get wsdl from service at " + url);
        return;
    }
    SOAPParser_cacheWsdl[url] = wsdl;
// save a copy in cache
    return SOAPParser._sendSoapRequest(url, method, paramXML, async, callback, transformUrl, wsdl, key);
}

SOAPParser._sendSoapRequest = function (url, method, paramXML, async, callback, transformUrl, wsdl, key) {
    // get namespace
    var ns = "http://www.iris.edu/phasepick/xsd";
    if ( wsdl.documentElement.localName != "error" ) {
        ns = (wsdl.documentElement.attributes[ "targetNamespace" ] + "" == "undefined") ? wsdl.documentElement.attributes.getNamedItem("targetNamespace") .nodeValue : wsdl.documentElement.attributes[ "targetNamespace" ].value;
    }
    // build SOAP request
    var sr =
    "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
    "<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/\">" +
    "<soap:Header />" +
    "<soap:Body>" +
    "<" + method + " xmlns=\"" + ns + "\">" +
    paramXML +
    "</" + method + "></soap:Body></soap:Envelope>";
    //alert(sr);

    // send request
    var xmlHttp = SOAPParser._getXmlHttp();
    xmlHttp.open("POST", url, async);
    var soapaction = ((ns.lastIndexOf("/") != ns.length - 1) ? ns + "/" : ns) + method;
    xmlHttp.setRequestHeader("SOAPAction", soapaction);
    xmlHttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    if (async) {
        xmlHttp.onreadystatechange = function () {
            if (xmlHttp.readyState == 4)
            SOAPParser._onSendSoapRequest(xmlHttp.responseXML, transformUrl, async, callback, key);
        }
    }
    xmlHttp.send(sr);
    if ( ! async)
    return SOAPParser._onSendSoapRequest(xmlHttp.responseXML, transformUrl, async, callback, key);
}


SOAPParser._onSendSoapRequest = function (req, transformUrl, async, callback, key) {

    var error = null;

    if (req.getElementsByTagName("faultcode") .length > 0) {
        if (async || callback) {
            error = new Error(500,
                          req.getElementsByTagName("faultstring") [0].childNodes[0].nodeValue);
        }
        else
            throw new Error(500,
                            req.getElementsByTagName("faultstring") [0].childNodes[0].nodeValue);
    }

    var outputString = "Empty Response";
    var xmlSerializer = new XMLSerializer();

    if ( error ) {
        outputString = xmlSerializer.serializeToString( req );
        outputString = outputString.replace( /</g, "&lt;" );
        outputString = outputString.replace( />/g, "&gt;" );
    }
    else if ( transformUrl ) {
        var xsltHttp = SOAPParser._getXmlHttp();
        xsltHttp.open("GET", transformUrl, false);
        xsltHttp.send(null);

        var processor = new XSLTProcessor();
        processor.importStylesheet(xsltHttp.responseXML);
        var outputFrag = processor.transformToDocument(req);

        //alert("outFrag:"+xmlSerializer.serializeToString(outputFrag));
        if (Sarissa.getParseErrorText(outputFrag) == Sarissa.PARSED_OK) {
            outputString = xmlSerializer.serializeToString(outputFrag);
        }
        else {
            // alert("err = " + Sarissa.getParseErrorText(outputFrag));
            outputString = Sarissa.getParseErrorText(outputFrag);
            error = new Error(500,outputString);
        }
    }
    else {  // no transformation
        outputString = xmlSerializer.serializeToString( req );
    }

    if (callback){
        callback(error, outputString, key);
    }
    if ( ! async) {
        return outputString;
    }
}

SOAPParser._getXmlHttp = function () {
    try {
        if (window.XMLHttpRequest) {
            var req = new XMLHttpRequest();
            // some versions of Moz do not support the readyState property and the onreadystate event so we patch it!
            if (req.readyState == null) {
                req.readyState = 1;
                req.addEventListener("load",
                function () {
                    req.readyState = 4;
                    if (typeof req.onreadystatechange == "function")
                    req.onreadystatechange();
                },
                false);
            }
            return req;
        }
        if (window.ActiveXObject)
        return new ActiveXObject(SOAPParser._getXmlHttpProgID());
    }
    catch (ex) {
    }
    throw new Error("Your browser does not support XmlHttp objects");
}

SOAPParser._getXmlHttpProgID = function () {
    if (SOAPParser._getXmlHttpProgID.progid)
    return SOAPParser._getXmlHttpProgID.progid;
    var progids = [ "Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP" ];
    var o;
    for (var i = 0; i < progids.length; i++) {
        try {
            o = new ActiveXObject(progids[i]);
            return SOAPParser._getXmlHttpProgID.progid = progids[i];
        }
        catch (ex) {
        };
    }
    throw new Error("Could not find an installed XML parser");
}
