//------------------------------------------------------------------------------
// ----- xmlWrapper.js (v1.0) --------------------------------------------------
// -----------------------------------------------------------------------------
//
// xmlWrapper(xmlUrl)
//   Local Declared:
//     domApi
//     xmlDoc
//     xslWrapper(xslName, xslUrl)
//       Local Declared:
//         loaded
//         xslUrl
//         xslProc
//       Properties: (None)
//       Methods:
//         writeTransform(targetDoc [, xslParam, value ...] )
//   Properties:
//     (Named xslWrappers)
//   Methods:
//     addXsl(xslUrl)
// Global/Local

function xmlWrapper(xmlUrl) {

  // Identify DOM API Type
  domApis = ["ActiveXObject", "XMLHttpRequest"]
  for (i=0; i<domApis.length; i++) if (window[domApis[i]]) { var domApi = domApis[i]; break; }
  if (domApi == undefined) throw "xmlWrapper.constructor: Undetected DOM API"

  // Load XML Document
  switch (domApi) {
    case "ActiveXObject":
      var xmlDoc = new ActiveXObject("MSXML2.FreeThreadedDOMDocument")
      xmlDoc.validateOnParse = true
      xmlDoc.async = false
      loadStat = xmlDoc.load(xmlUrl)
      // I/i DTD diffs were giving loadStat and xmlDoc was undefined
      if (loadStat) {
        if (xmlDoc.readyState == 4) {
          if (xmlDoc.parseError == 0) {
            // Other XML checks?                
          } else with(xmlDoc.parseError)
            throw "xmlWrapper.constructor: xmlDoc.parserror. errorCode = " + errorCode +
              ", reason = " + reason + ", line = " + line + ", linepos = " + linepos +
              ", srcText = " + srcText + ", url = " + url
        } else throw "xmlWrapper.constructor: xmlUrl='" + xmlUrl + "', xmlDoc.readyState = " + xmlDoc.readyState
      } else alert( "xmlWrapper.constructor: xmlUrl='" + xmlUrl + "', loadStat=" + loadStat )

      //nodes = xmlDoc.selectNodes("/Catalog/Items/Item/Xsl/..|/Catalog/Themes/Theme/Xsl/..")
      nodes = xmlDoc.selectNodes("/Catalog/Xsls/Xsl")
      for (i=0; i<nodes.length; i++) {
        node = nodes[i]
        xslName = node.getAttribute("XslId")
        this[xslName] = new xslWrapper(node.selectSingleNode('Url').text)
      } // for (i=0...
      break

    case "XMLHttpRequest":
      xmlReq = new XMLHttpRequest()
      xmlReq.open("GET", xmlUrl, false)
      xmlReq.send(null)
      if (xmlReq.readyState == 4) {
        if (xmlReq.status == 200 | xmlReq.status == 0) {
          if (xmlReq.responseXML.documentElement.nodeName != 'parsererror') {
            // Other XML checks?
          } else throw "xmlWrapper.constructor: xmlReq.responseXML.documentElement.nodeName = " + xmlReq.responseXML.documentElement.nodeName
        } else throw "xmlWrapper.constructor: xmlReq.status = " + xmlReq.status
      } else throw "xmlWrapper.constructor: xmlReq.readyState = " + xmlReq.readyState
      xmlDoc = xmlReq.responseXML

      var nodes=xmlDoc.evaluate("/Catalog/Xsls/Xsl", xmlDoc, null, XPathResult.ANY_TYPE, null)
      for (node=nodes.iterateNext(); node!=null; node=nodes.iterateNext()) {
        xslName = node.getAttribute("XslId")
        this[xslName] = new xslWrapper(node.getElementsByTagName("Url")[0].textContent)
      } // for (node=
      break

      default: throw "xmlWrapper: Unrecognized, domApi = " + domApi
  } // switch (domApi

  this.addXsl = function(xslName, xslUrl) {
    this[xslName] = new xslWrapper(xslUrl)
  } // addXsl
  
  // xslWrapper Local Object
  function xslWrapper(xslUrlArg) {

    var xslUrl = xslUrlArg
    var loaded = false
    var xslProc

    this.writeTransform = function(targetDoc) {
      if ((arguments.length - this.writeTransform.length)%2 != 0) throw "writeTransform: Unexpected argument"

      if (!loaded) { // Will this get xmlWrapper's var?
        // Load XSL Document      
        switch (domApi) { // Will this get xmlWrapper's var?
          case "ActiveXObject":
            xslDoc = new ActiveXObject("MSXML2.FreeThreadedDOMDocument")
            xslDoc.async = false
            var loadStat = xslDoc.load(xslUrl)
            if (xslDoc.readyState == 4) {
              if (loadStat) {
                // Other XSL checks (try/catch)? parseError does not work w/XSL
                // Add more info to throws, wrapName, Url
              } else throw "xslWrapper.writeTransform: loadStat = " + loadStat
            } else throw "xslWrapper.writeTransform: xslDoc.readyState = " + xslDoc.readyState

            xslCache = new ActiveXObject("MSXML2.XSLTemplate")  // Un vared so it would not persist
            xslCache.stylesheet = xslDoc
            xslProc = xslCache.createProcessor()
            xslProc.input = xmlDoc
            break

          case "XMLHttpRequest":
            xslReq = new XMLHttpRequest()
            xslReq.open("GET", xslUrl, false)
            xslReq.send(null)
            if (xslReq.readyState == 4) {
              if (xslReq.status == 200 | xslReq.status == 0) {
                // Other XSL checks? (test a bad xsl)
                // Add more info to throws, wrapName, Url
              } else throw "xslWrapper.writeTransformj: xslReq.status = " + xslReq.status
            } else throw "xslWrapper.writeTransformj: xslReq.readyState = " + xslReq.readyState
            xslDoc = xslReq.responseXML
            xslProc = new XSLTProcessor()
            xslProc.importStylesheet(xslDoc) // Moving this down gets FF Invalid Pointer, Saf/Chro only ItemId changes in xform
            break

          default:
            throw "xslWrapper.writeTransform: Unrecognized, domApi = '" + domApi + "'"
        } // switch (domApi)
        loaded = true
      } // if (!loaded)

      targetDoc.open()      
      switch (domApi) {
        case "ActiveXObject":
          for (i=this.writeTransform.length; i<arguments.length; i=i+2)
            xslProc.addParameter(arguments[i], arguments[i+1])
          xslProc.transform()
          targetDoc.write(xslProc.output)
          break

        case "XMLHttpRequest":
          for (i=this.writeTransform.length; i<arguments.length; i=i+2)
            xslProc.setParameter(null, arguments[i], arguments[i+1])
// Could alloc XMLSerializer in xmlWrapper to save space
          targetDoc.write(new XMLSerializer().serializeToString(xslProc.transformToDocument(xmlDoc)))
          break

        default: throw "xslWrapper.writeTransform: Unrecognized, domApi='" + domApi + "'"
      } // switch (domApi)
      targetDoc.close()
    } // writeTransform
  } // xslWrapper
} // xmlWrapper