//notation: js file can only use this kind of comments
//since comments will cause error when use in webview.loadurl,
//comments will be remove by java use regexp
(function () {
  if (window.SeeklaneJsBridge) {
    return;
  }

  var messagingIframe;
  var bizMessagingIframe;
  var sendMessageQueue = [];
  var receiveMessageQueue = [];
  var messageHandlers = {};

  var CUSTOM_PROTOCOL_SCHEME = 'yy';
  var QUEUE_HAS_MESSAGE = '__QUEUE_MESSAGE__/';

  var responseCallbacks = {};
  var uniqueId = 1;

  // 创建消息index队列iframe
  function _createQueueReadyIframe(doc) {
    messagingIframe = doc.createElement('iframe');
    messagingIframe.style.display = 'none';
    doc.documentElement.appendChild(messagingIframe);
  }

  //创建消息体队列iframe
  function _createQueueReadyIframe4biz(doc) {
    bizMessagingIframe = doc.createElement('iframe');
    bizMessagingIframe.style.display = 'none';
    doc.documentElement.appendChild(bizMessagingIframe);
  }

  //set default messageHandler  初始化默认的消息线程
  function init(messageHandler) {
    if (SeeklaneJsBridge._messageHandler) {
      throw new Error('SeeklaneJsBridge.init called twice');
    }
    SeeklaneJsBridge._messageHandler = messageHandler;
    var receivedMessages = receiveMessageQueue;
    receiveMessageQueue = null;
    for (var i = 0; i < receivedMessages.length; i++) {
      _dispatchMessageFromNative(receivedMessages[i]);
    }
  }

  // 发送
  function send(data, responseCallback) {
    _doSend({
      data: data
    }, responseCallback);
  }

  // 注册线程 往数组里面添加值
  function registerHandler(handlerName, handler) {
    messageHandlers[handlerName] = handler;
  }

  // 调用线程
  function callHandler(handlerName, data, responseCallback) {
    _doSend({
      handlerName: handlerName,
      data: data
    }, responseCallback);
  }

  //sendMessage add message, 触发native处理 sendMessage
  function _doSend(message, responseCallback) {
    if (responseCallback) {
      var callbackId = 'cb_' + (uniqueId++) + '_' + new Date().getTime();
      responseCallbacks[callbackId] = responseCallback;
      message.callbackId = callbackId;
    }

    sendMessageQueue.push(message);
    messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE;
  }

  // 提供给native调用,该函数作用:获取sendMessageQueue返回给native,由于android不能直接获取返回的内容,所以使用url shouldOverrideUrlLoading 的方式返回内容
  function _fetchQueue() {
    var messageQueueString = JSON.stringify(sendMessageQueue);
    sendMessageQueue = [];
    //android can't read directly the return data, so we can reload iframe src to communicate with java
    if (messageQueueString !== '[]') {
      bizMessagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://return/_fetchQueue/' + encodeURIComponent(messageQueueString);
    }
  }

  //提供给native使用,
  function _dispatchMessageFromNative(messageJSON) {
    setTimeout(function () {
      var message = JSON.parse(messageJSON);
      var responseCallback;
      //java call finished, now need to call js callback function
      if (message.responseId) {
        responseCallback = responseCallbacks[message.responseId];
        if (!responseCallback) {
          return;
        }
        responseCallback(message.responseData);
        delete responseCallbacks[message.responseId];
      } else {
        //直接发送
        if (message.callbackId) {
          var callbackResponseId = message.callbackId;
          responseCallback = function (responseData) {
            _doSend({
              responseId: callbackResponseId,
              responseData: responseData
            });
          };
        }

        var handler = SeeklaneJsBridge._messageHandler;
        if (message.handlerName) {
          handler = messageHandlers[message.handlerName];
        }
        //查找指定handler
        try {
          handler(message.data, responseCallback);
        } catch (exception) {
          /*
          if (typeof console != 'undefined') {
              console.log("SeeklaneJsBridge: WARNING: javascript handler threw.", message, exception);
          }
          */
        }
      }
    });
  }

  //提供给native调用,receiveMessageQueue 在会在页面加载完后赋值为null,所以
  function _handleMessageFromNative(messageJSON) {
    //console.log("receiveMessageQueue,   "+messageJSON);
    if (receiveMessageQueue) {
      receiveMessageQueue.push(messageJSON);
    }
    _dispatchMessageFromNative(messageJSON);

  }

  var SeeklaneJsBridge = window.SeeklaneJsBridge = {
    init: init,
    send: send,
    registerHandler: registerHandler,
    callHandler: callHandler,
    _fetchQueue: _fetchQueue,
    _handleMessageFromNative: _handleMessageFromNative
  };


  var callbackFunction = function (callback, data) {
    if (callback) {
      var jsonData = JSON.parse(data);
      if (jsonData.success) {
        typeof callback.success === "function" && callback.success(jsonData.success);
      }
      if (jsonData.fail) {
        typeof callback.fail === "function" && callback.fail(jsonData.fail);
      }
      if (jsonData.complete) {
        typeof callback.complete === "function" && callback.complete(jsonData.complete);
      }
    }
  };


  var sensorCallHandler = function (eventName, callback, options) {
    //call native method
    SeeklaneJsBridge.callHandler(
      eventName
      , options
      , function (responseData) {
        callbackFunction(callback, responseData);
      }
    );
  };

  var dataUpdateHandler = function (eventName, callback, responseData) {
    SeeklaneJsBridge.registerHandler(eventName, function (data, responseCallback) {
      if (typeof callback === "function") {
        var jsonData = JSON.parse(data);
        if (typeof responseCallback === "function") {
          jsonData.responseCallback = responseCallback;
        }

        callback(jsonData);
      }
      if (typeof responseCallback === "function" && responseData) {
        responseCallback(responseData);
      }
    });

  };

  /*var callJSeeklane = function(callback) {
      if (window.SeeklaneJsBridge) {
          callback(SeeklaneJsBridge)
      } else {
          document.addEventListener(
              'SeeklaneJsBridgeReady'
              , function() {
                  callback(SeeklaneJsBridge)
              },
              false
          );
      }
  };

  callJSeeklane(function(){

  });*/

  SeeklaneJsBridge.init(function (message, responseCallback) {
    console.log('JS got a message', message);
    var data = {
      'Javascript Responds': '测试中文!'
    };

    if (responseCallback) {
      console.log('JS responding with', data);
      responseCallback(data);
    }
  });


  if(!window.jSeeklane) {
      window.jSeeklane = {};
  }
  var jSeeklane = window.jSeeklane;

  jSeeklane.startBeaconSearch = function (callback, options) {
    sensorCallHandler('startBeaconSearch', callback, options);
  };

  jSeeklane.stopBeaconSearch = function (callback, options) {
    sensorCallHandler('stopBeaconSearch', callback, options);
  };

  jSeeklane.onBeaconUpdate = function (callback, responseData) {
    dataUpdateHandler("onBeaconUpdate", callback, responseData);
  };

    jSeeklane.startWifiSearch = function (callback, options) {
      sensorCallHandler('startWifiSearch', callback, options);
    };

    jSeeklane.stopWifiSearch = function (callback, options) {
      sensorCallHandler('stopWifiSearch', callback, options);
    };

  jSeeklane.onWifiUpdate = function (callback, responseData) {
    dataUpdateHandler("onWifiUpdate", callback, responseData);
  };

  jSeeklane.startGeoLocation = function (callback, options) {
    sensorCallHandler('startGeoLocation', callback, options);
  };

  jSeeklane.stopGeoLocation = function (callback, options) {
    sensorCallHandler('stopGeoLocation', callback, options);
  };

  jSeeklane.onGeoLocationUpdate = function (callback, responseData) {
    dataUpdateHandler("onGeoLocationUpdate", callback, responseData);
  };

  jSeeklane.setUserInfo = function(callback, responseData) {
    dataUpdateHandler("setUserInfo", callback, responseData);
  };

  jSeeklane.startCompass = function (callback, options) {
    sensorCallHandler('startCompass', callback, options);
  };

  jSeeklane.stopCompass = function (callback, options) {
    sensorCallHandler('stopCompass', callback, options);
  };

  jSeeklane.onCompassUpdate = function (callback, responseData) {
    dataUpdateHandler("onCompassUpdate", callback, responseData);
  };

  jSeeklane.onBeaconServiceChange = function (callback, responseData) {
    dataUpdateHandler("onBeaconServiceChange", callback, responseData);
  };

  jSeeklane.mapConfigReady = function (callback, options) {
    sensorCallHandler('mapConfigReady', callback, options);
  };


  jSeeklane.navigationDistanceCallBack = function (callback, options) {
    sensorCallHandler('navigationDistanceCallBack', callback, options);
  };

  jSeeklane.positionStatusCallBack = function (callback, options) {
    sensorCallHandler('positionStatusCallBack', callback, options);
  };

  jSeeklane.hasNativeMethod = function (callback, options) {
      sensorCallHandler('hasNativeMethod', callback, options);
  };

  jSeeklane.bindMessage = function (callback, responseData) {
      dataUpdateHandler("bindMessage", callback, responseData);
  };

  jSeeklane.postMessage = function(options, callback) {
      if(typeof options === "object") {
          if(typeof options.value === "object") {
            options.value = JSON.stringify(options.value);
          }
          options = JSON.stringify(options);
      }
      sensorCallHandler("postMessage", callback, options);
  };

  var doc = document;
  _createQueueReadyIframe(doc);
  _createQueueReadyIframe4biz(doc);
  var readyEvent = doc.createEvent('Events');
  readyEvent.initEvent('SeeklaneJsBridgeReady');
  readyEvent.bridge = SeeklaneJsBridge;
  doc.dispatchEvent(readyEvent);


})();