/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * LEXMARK global namespace object, allow one and only one
 *
 */
if("undefined" === typeof(LEXMARK)) {
 var LEXMARK = {};
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * component: CEEHSAWWW
 * content:   interface to a provider of local print settings and basic printing tasks
 */
LEXMARK.CEEHSAWWW = function() {
 var active = false;
 var ahActivation = [];
 var listenMax = 3000;
 var retryPeriod = 500;
 var timeout = {"status":"timeout"};
 var invalid = {"status":"invalid"};

 function detect() {
  // once body is available, send an empty request
  if(document.body) {
   request(function() {}, "getVoid", {}, document);
  } else {
   window.setTimeout(function() {detect();}, retryPeriod);
  }
 }

 function isValidEnv() {
  // test for valid environment
  var ua = navigator.userAgent.toLowerCase();
  if(0 <= ua.indexOf("msie")) {
   var ver = ua.substring(ua.indexOf("msie") + "msie ".length, ua.indexOf(";", ua.indexOf("msie") + "msie ".length));
   if(!isNaN(ver.charAt(0))) {
    if(parseInt(ver.charAt(0), 10) >= 5) {
     return true;
    }
   }
  }
  return false;
 }

 function listen(h, id, doc, t) {
  try {
   if("function" === typeof(h)) {
    if("string" === typeof(id)) {
     if("object" === typeof(doc)) {     
      if("number" === typeof(t)) {
       var done = false;
       var d = new Date();
       var r = doc.getElementById(id).getAttribute("response");
       if(null !== r) {
        done = true;
        // if response is valid json, send the response object to the handler
        if(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/.test(r.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) {
         if(!active) {
          active = true;
          for(var i in ahActivation) {
           window.setTimeout(ahActivation[i], 0);
          }
         }
         window.setTimeout(function() {h(eval("(" + r + ")"));}, 0);
        } else {
         window.setTimeout(function() {h(invalid);}, 0);
        }
       } else {
        // continue listening for a response until timeout occurs
        if((d.getTime() - t) >= listenMax) {
         done = true;
         window.setTimeout(function() {h(timeout);}, 0);
        } else {
         window.setTimeout(function() {listen(h, id, doc, t);}, retryPeriod);
        }
       }
       if(done) {
        // remove iframe once done listening
        doc.body.removeChild(doc.getElementById(id));
       }
      }
     }
    }
   }
  } catch(err) {}
  return;
 }

 function request(h, m, opt, doc) {
  try {
   if(isValidEnv()) {
    if("function" === typeof(h)) {
     if("string" === typeof(m)) {
      if("object" === typeof(opt)) {
       if("object" === typeof(doc)) {
        // if any options were passed, turn them into a URL parameter string
        var p = "";
        for(var k in opt) {
         p += (("" === p) ? "?" : "&") + k + "=" + escape(opt[k]);
        }
        var d = new Date();
        var t = d.getTime();
        var e = doc.createElement("iframe");
        e.id = "";
        var c = "0123456789abcdefghiklmnopqrstuvwxyz";
        while(e.id.length < 16) {
         e.id += c.charAt(Math.floor(Math.random()*c.length));
        }
        e.style.position = "absolute";
        e.style.visibility = "hidden";
        // add our new element to the top of the DOM
        doc.body.insertBefore(e, doc.body.firstChild);
        // "CEEHSAWWW" the element's source with a cloneNode trick... prevents IE clicking
        var e2 = e.cloneNode(true);
        e2.src = "javascript:void({\"scheme\":\"ceehsawww\",\"id\":\"" + e.id + "\",\"call\":\"" + m + p + "\"});";
        e.parentNode.replaceChild(e2, e);
        // kick off listening attempts
        window.setTimeout(function() {listen(h, e.id, doc, t);}, retryPeriod);
       }
      }
     }
    }
   }
  } catch(err) {}
 }

 // start detection as part of object creation
 detect();

 return {
  isActive: function() {
   return active;
  },
  // params:
  //  h - handler function to be called when CEEHSAWWW becomes active (required)
  onActivation: function(h) {
   if("function" === typeof(h)) {
    ahActivation[ahActivation.length] = h;
   }
  },
  // params:
  //  h - handler function to be called (required)
  getVersion: function(h) {
   request(h, "getVersion", {}, document);
  },
  // params:
  //  h - handler function to be called (required)
  getValidRequests: function(h) {
   request(h, "getValidRequests", {}, document);
  },
  // params:
  //  h - handler function to be called (required)
  getValidPrintOptions: function(h) {
   request(h, "getValidPrintOptions", {}, document);
  },
  // params:
  //  h - handler function to be called (required)
  getDefaultPrinter: function(h) {
   request(h, "getDefaultPrinter", {}, document);
  },
  // params:
  //  h - handler function to be called (required)
  getPDFWriter: function(h) {
   request(h, "getPDFWriter", {}, document);
  },
  // params:
  //  h - handler function to be called (required)
  getPrinters: function(h) {
   request(h, "getPrinters", {}, document);
  },
  // params:
  //  h - handler function to be called (required)
  getPrintersOnline: function(h) {
   request(h, "getPrintersOnline", {}, document);
  },
  // params:
  //  h - handler function to be called (required)
  getPrintersPrinting: function(h) {
   request(h, "getPrintersPrinting", {}, document);
  },
  // params:
  //  h - handler function to be called (required)
  //  friendly - friendly name of printer (required)
  getPrinterInkCartridgeIDs: function(h, friendly) {
   request(h, "getPrinterInkCartridgeIDs", {"friendly": friendly}, document);
  },
  // params:
  //  h - handler function to be called (required)
  //  friendly - friendly name of printer (required)
  //  type - the type of ink; possible values: C, M, Y, K, PhotoC, PhotoM, PhotoK (required)
  getPrinterInkPercentage: function(h, friendly, type) {
   request(h, "getPrinterInkPercentage", {"friendly": friendly, "type": type}, document);
  },
  // params:
  //  h - handler function to be called (required)
  //  friendly - friendly name of printer (required)
  getPrinterDriverName: function(h, friendly) {
   request(h, "getPrinterDriverName", {"friendly": friendly}, document);
  },
  // params:
  //  h - handler function to be called (required)
  //  friendly - friendly name of printer (required)
  getPrinterMediaNames: function(h, friendly) {
   request(h, "getPrinterMediaNames", {"friendly": friendly}, document);
  },
  // params:
  //  h - handler function to be called (required)
  //  friendly - friendly name of printer (required)
  getPrinterMediaSizes: function(h, friendly) {
   request(h, "getPrinterMediaSizes", {"friendly": friendly}, document);
  },
  // params:
  //  h - handler function to be called (required)
  //  options - object containing associative array of options (optional)
  //  doc - document object from the window that should be printed (optional, defaults to current window)
  print: function(h, options, doc) {
   request(h, "print", ("object" === typeof(options)) ? options : {}, ("object" === typeof(doc)) ? doc : document);
  }
 };
}();
