
if (!Object.keys) {
  Object.keys = (function() {
    'use strict';
    var hasOwnProperty = Object.prototype.hasOwnProperty,
        hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'),
        dontEnums = [
          'toString',
          'toLocaleString',
          'valueOf',
          'hasOwnProperty',
          'isPrototypeOf',
          'propertyIsEnumerable',
          'constructor'
        ],
        dontEnumsLength = dontEnums.length;

    return function(obj) {
      if (typeof obj !== 'function' && (typeof obj !== 'object' || obj === null)) {
        throw new TypeError('Object.keys called on non-object');
      }

      var result = [], prop, i;

      for (prop in obj) {
        if (hasOwnProperty.call(obj, prop)) {
          result.push(prop);
        }
      }

      if (hasDontEnumBug) {
        for (i = 0; i < dontEnumsLength; i++) {
          if (hasOwnProperty.call(obj, dontEnums[i])) {
            result.push(dontEnums[i]);
          }
        }
      }
      return result;
    };
  }());
}

if (!Array.prototype.reduce) {
  Object.defineProperty(Array.prototype, 'reduce', {
    value: function(callback /*, initialValue*/) {
      if (this === null) {
        throw new TypeError( 'Array.prototype.reduce ' +
          'called on null or undefined' );
      }
      if (typeof callback !== 'function') {
        throw new TypeError( callback +
          ' is not a function');
      }

      var o = Object(this);

      var len = o.length >>> 0;

      var k = 0;
      var value;

      if (arguments.length >= 2) {
        value = arguments[1];
      } else {
        while (k < len && !(k in o)) {
          k++;
        }

        if (k >= len) {
          throw new TypeError( 'Reduce of empty array ' +
            'with no initial value' );
        }
        value = o[k++];
      }

      while (k < len) {
        if (k in o) {
          value = callback(value, o[k], k, o);
        }

        k++;
      }

      return value;
    }
  });
}


// 自定义
window.messageHandlers = ['route', 'closeWebview', 'getUserInfo', 'setLoading', 'request','modal', 'share', 'init', 'openBrowser', 'updateActivity', 'toast'];
var EPAL = window.EPAL = {};
var execTimeObj = {};
window.NATIVE_CALLBACK = {};
var originModules = window.webkit.messageHandlers;

function createCb (method, callbacks) {
  var cb = window.NATIVE_CALLBACK;
  var funPath = 'window.NATIVE_CALLBACK.' + method;

  // 初始化
  var methodCb = cb[method];
  if(Object.prototype.toString.call(methodCb) !== '[object Object]') {
    window.NATIVE_CALLBACK[method] = methodCb = {};
  }

  // 执行次数
  var execTime = execTimeObj[method];
  if(execTime) {
    execTime++
  } else {
    execTime = 1;
  }
  execTimeObj[method] = execTime;

  // 遍历所有回调方法
  return Object.keys(callbacks).reduce((obj, key) => {
    var targetKey = key + execTime;

    // 映射赋值函数
    window.NATIVE_CALLBACK[method][targetKey] = methodCb[targetKey] = function (resp) {
      callbacks[key](resp);
    }
    // 定义全局回调字符串
    obj[key] = funPath + '.' + targetKey;
    return obj
  }, {})
}

function nativeRun (method, args) {
  var resolve = args.success,
      reject = args.error;

  // 支持扩展回调函数，如分享场景
  var custom = Object.keys(args).reduce((obj, key) => {
    const fun = args[key];
    if (fun != null && fun instanceof Function) {
      obj[key] = fun;
    }
    return obj;
  }, {});


  // 创建初始callbacks
  var originCb = {
    success: resolve,
    error: reject,
  };
  for(var attr in custom) {
    originCb[attr] = custom[attr];
  }

  var nativeCb = createCb(method, originCb);
  for (var key in nativeCb) {
    args[key] = nativeCb[key];
  }

  if(!originModules[method] || !originModules[method].postMessage) {
    throw new Error('hi man：' + method + ' was not found');
  }
  originModules[method].postMessage(JSON.stringify(args))
}

function hanldeModule () {
  messageHandlers.forEach(handler => {
    EPAL[handler] = function(args) {
      return nativeRun(handler, args || {});
    }
  })
}

hanldeModule();
