;(function(context) {
  'use strict';
  
  if(context.zetaBridge){
    console.log('skipping bridge injection');
    return;
  }
  
  console.log('inject script load');
  
  // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
  // This way, it's very unlikely that any new callback would get the same callbackId as an old callback
  var nextCallbackId = Math.floor(Math.random() * 2000000000);
  var callbacks = {};
  var messagesFromNative = [];
  
  function callbacksFromNative(msgs) {
  Array.prototype.push.apply(messagesFromNative, msgs);
  processMessages();
  }
  
  function processMessage(message) {
  var callbackId = message.callbackId;
  var isSuccess = message.isSuccess;
  var arg = message.arg;
  
  var callbackObject = callbacks[callbackId];
  if (callbackObject) {
  if (isSuccess) {
  callbackObject.success(arg);
  } else {
  callbackObject.error(arg);
  }
  }
  delete callbacks[callbackId];
  }
  
  function popMessageFromQueue() {
  return messagesFromNative.shift();
  }
  
  function processMessages() {
  while (messagesFromNative.length > 0) {
  var message = popMessageFromQueue();
  if (message) {
  processMessage(message);
  }
  }
  }
  
  function dispatchEvent(eventName, eventData) {
  var event = new CustomEvent(eventName, {
                              bubbles: true,
                              cancellable: true,
                              detail: eventData
                              });
  document.dispatchEvent(event);
  }
  
  context.zetaBridge = {
  ask: function(service, action, arg, successCallback, errorCallback) {
  var callbackId = service + nextCallbackId++;
  var argJson = JSON.stringify(arg);
  
  if (successCallback || errorCallback) {
  callbacks[callbackId] = {success: successCallback, error: errorCallback};
  }
  
  var msg = { service: service, action: action, args: argJson, callbackId: callbackId};
  var msgsJson = window.webkit.messageHandlers._zetaNative.postMessage(msg);
  if (msgsJson) {
  callbacksFromNative(msgsJson);
  }
  },
  callbacksFromNative: callbacksFromNative,
  dispatchEvent: dispatchEvent
  };
  })(this);
