function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
/**
 * Proxy代理层
 * **/
import ProxyPolyfillBuilder from 'proxy-polyfill/src/proxy';
import { EConstructorName, instanceApiMap } from "./constant";
import { supportsDefineProperty, supportsProxy } from "./utils/common";
import { setDebugContext } from "./utils/debugger";
import { loadSdk, newActualInstance } from "./utils/loadSDK";
import { consoleLogger, logger } from "./utils/logger";
import { setProxyEndTime, setProxyStartTime } from "./utils/proxyPerformance";

// eslint-disable-next-line

// eslint-disable-next-line

// eslint-disable-next-line

// eslint-disable-next-line
export function createBaseProxy(constructorName) {
  var _newProxyInstance = function _newProxyInstance(self) {
    return new Proxy(self, {
      get: function get(target, prop) {
        // 过滤 promise相关的方法，兼容商户 Promise 包装 api 的形式
        var promiseFunctionName = ['then', 'catch', 'finally'];
        // 如果是内部属性或方法，直接返回
        if (prop in target || _typeof(prop) === 'symbol' || promiseFunctionName.includes(prop)) {
          return target[prop];
        }

        // 返回一个代理方法
        return function () {
          for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
            args[_key] = arguments[_key];
          }
          // 已存在真实实例，直接调用
          if (self.hasActualInstance && self.actualInstance) {
            var _self$actualInstance;
            return (_self$actualInstance = self.actualInstance)[prop].apply(_self$actualInstance, args);
          } else {
            // SDK未加载，记录调用
            return new Promise(function (resolve, reject) {
              consoleLogger.log("Cache API [".concat(constructorName, ".").concat(prop, "]"));
              self.pendingCalls.push({
                method: prop,
                args: args,
                resolve: resolve,
                reject: reject
              });
            });
          }
        };
      }
    });
  };
  var _newProxyInstanceWithPolyfill = function _newProxyInstanceWithPolyfill(self) {
    var proxyConstructor = ProxyPolyfillBuilder();

    // 创建一个只读,不可调用,不可枚举的临时api,用于被proxyPolyfill捕获
    var CAPTURED__API_TEMP_VALUE = Symbol('CAPTURED__API_TEMP_VALUE');
    var needCapturedApis = instanceApiMap[constructorName];
    needCapturedApis.forEach(function (api) {
      Object.defineProperty(self, api, {
        value: CAPTURED__API_TEMP_VALUE,
        writable: false,
        enumerable: false,
        configurable: false
      });
    });
    return new proxyConstructor(self, {
      get: function get(target, prop) {
        var proxyFunc = function proxyFunc() {
          for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
            args[_key2] = arguments[_key2];
          }
          // 已存在真实实例，直接调用
          if (self.hasActualInstance && self.actualInstance) {
            var _self$actualInstance2;
            return (_self$actualInstance2 = self.actualInstance)[prop].apply(_self$actualInstance2, args);
          } else {
            // SDK未加载，记录调用
            return new Promise(function (resolve, reject) {
              consoleLogger.log("Cache API [".concat(constructorName, ".").concat(prop, "]"));
              self.pendingCalls.push({
                method: prop,
                args: args,
                resolve: resolve,
                reject: reject
              });
            });
          }
        };

        // 如果是需要代理的API  则返回一个代理方法
        if ((target === null || target === void 0 ? void 0 : target[prop]) === CAPTURED__API_TEMP_VALUE) {
          return proxyFunc;
        }
        // 如果是无需被代理的内部属性或方法,直接返回
        if (prop in target || _typeof(prop) === 'symbol') {
          return target[prop];
        }
        // 兜底
        return proxyFunc;
      }
    });
  };

  /***构造一个虚拟错误对象来模拟产品实例,其中所有的API都会在.then中返回错误对象*/
  var _newInstanceForError = function _newInstanceForError(errorObj) {
    var instanceForError = {};
    var needCapturedApis = instanceApiMap[constructorName];
    needCapturedApis.forEach(function (api) {
      instanceForError[api] = function () {
        return Promise.resolve(errorObj);
      };
    });
    return instanceForError;
  };
  var BaseProxy = /*#__PURE__*/function () {
    // 返回代理实例对象
    function BaseProxy(_newProps, debugProps) {
      var _this = this;
      _classCallCheck(this, BaseProxy);
      _defineProperty(this, "hasActualInstance", false);
      _defineProperty(this, "pendingCalls", []);
      _defineProperty(this, "actualInstance", null);
      _defineProperty(this, "proxyInstance", null);
      _defineProperty(this, "startTime", 0);
      _defineProperty(this, "onCreateInstanceError", function (newProps) {
        // 不同实例进行不同的错误处理方案
        if (constructorName === EConstructorName.AMSElement) {
          _this.throwErrorWithPromise({
            error: {
              code: 'UI_STATE_ERROR',
              message: 'create_actual_instance_error'
            }
          });
        } else if (constructorName === EConstructorName.AMSEasyPay) {
          _this.throwErrorWithOnEventCallback({
            code: 'SDK_INTERNAL_ERROR',
            message: 'create_actual_instance_error'
          }, newProps);
        } else {
          _this.throwErrorWithOnEventCallback({
            code: 'SDK_INTERNAL_ERROR',
            message: 'create_actual_instance_error'
          }, newProps);
        }
      });
      _defineProperty(this, "onLoadSDKError", function (newProps) {
        if (constructorName === EConstructorName.AMSElement) {
          _this.throwErrorWithPromise({
            error: {
              code: 'INITIALIZE_WEB_TIMEOUT',
              message: 'load_sdk_resource_error'
            }
          });
        } else if (constructorName === EConstructorName.AMSEasyPay) {
          _this.throwErrorWithOnEventCallback({
            code: 'SDK_INTERNAL_ERROR',
            message: 'load_sdk_resource_error'
          }, newProps);
        } else {
          _this.throwErrorWithOnEventCallback({
            code: 'SDK_INTERNAL_ERROR',
            message: 'load_sdk_resource_error'
          }, newProps);
        }
      });
      this.startTime = Date.now();
      // 初始化debug参数
      setDebugContext(debugProps);
      // 记录开始时间
      setProxyStartTime(constructorName, this.startTime);
      // 创建代理实例
      this.proxyInstance = this.newProxyInstance();
      // 加载sdk并创建真实实例
      this.loadSDKAndCreateInstance(constructorName, _newProps);
      logger.logInfo({
        title: 'create_proxy_instance_success'
      }, {
        constructorName: constructorName
      });
      return this.proxyInstance;
    }

    // 初始化loader并开始加载sdk  创建实例,并执行所有待处理的调用
    _createClass(BaseProxy, [{
      key: "loadSDKAndCreateInstance",
      value: function loadSDKAndCreateInstance(constructorName, newProps) {
        var _this2 = this;
        loadSdk().then(function (_ref) {
          var loadType = _ref.loadType;
          try {
            var actualInstance = newActualInstance(constructorName, newProps);
            var newActualInstanceDuration = Date.now() - _this2.startTime;
            // 记录结束时间
            setProxyEndTime(constructorName, Date.now());
            // 上报newProxy到初始化真实sdk实例花费时间,忽略SDK缓存场景
            logger.logInfo({
              title: 'loadSDK_and_create_actual_instance'
            }, {
              constructorName: constructorName,
              loadDuration: loadType === 'network' ? newActualInstanceDuration : undefined
            });
            // 热更新全流程成功率监控
            logger.logInfo({
              title: 'create_antom_instance'
            }, {
              constructorName: constructorName,
              result: 'Y'
            });
            consoleLogger.log('create_actual_instance_success');
            _this2.actualInstance = actualInstance;
            _this2.hasActualInstance = true;
            _this2.executePendingCalls();
          } catch (error) {
            logger.logInfo({
              title: 'create_antom_instance'
            }, {
              constructorName: constructorName,
              result: 'N'
            });
            _this2.onCreateInstanceError(newProps);
          }
        }).catch(function () {
          logger.logInfo({
            title: 'create_antom_instance'
          }, {
            constructorName: constructorName,
            result: 'N'
          });
          _this2.onLoadSDKError(newProps);
        });
      }

      // 创建代理实例
    }, {
      key: "newProxyInstance",
      value: function newProxyInstance() {
        // 检测浏览器API兼容性
        var isProxySupports = supportsProxy();
        var isDefinePropertySupports = supportsDefineProperty();
        if (!isProxySupports && !isDefinePropertySupports) {
          logger.logError({
            title: 'create_proxy_instance_error'
          }, {
            constructorName: constructorName
          });
          consoleLogger.error('The browser does not support either Proxy or Object.defineProperty.');
        }
        try {
          // eslint-disable-next-line @typescript-eslint/no-this-alias
          var self = this;

          // 如果浏览器不支持Proxy,则使用Polyfill降级 https://github.com/GoogleChrome/proxy-polyfill,
          // 注意: Polyfill降级方案需要预先定义需要捕获的api。
          if (isProxySupports) {
            return _newProxyInstance(self);
          } else {
            logger.logInfo({
              title: 'proxy_api_not_support'
            });
            return _newProxyInstanceWithPolyfill(self);
          }
        } catch (e) {
          logger.logError({
            title: 'create_proxy_instance_error'
          }, {
            errorMessage: e,
            constructorName: constructorName
          });
          consoleLogger.error('The browser does not support either Proxy or Object.defineProperty.');
        }
      }

      // 执行所有待处理的调用
    }, {
      key: "executePendingCalls",
      value: function executePendingCalls() {
        while (this.pendingCalls.length > 0) {
          if (!this.actualInstance) return;
          var pendingCall = this.pendingCalls.shift();
          if (!pendingCall) return;
          var method = pendingCall.method,
            args = pendingCall.args,
            resolve = pendingCall.resolve,
            reject = pendingCall.reject;
          try {
            var _this$actualInstance;
            var result = (_this$actualInstance = this.actualInstance)[method].apply(_this$actualInstance, _toConsumableArray(args));
            consoleLogger.log("call API [".concat(constructorName, ".").concat(method, "]"));
            resolve(result);
          } catch (error) {
            logger.logError({
              title: 'call_pending_method_error'
            }, {
              errorMessage: error,
              constructorName: constructorName,
              method: method
            });
            reject(error);
          }
        }
      }
      // 拒绝所有待处理的调用
    }, {
      key: "rejectPendingCalls",
      value: function rejectPendingCalls(error) {
        while (this.pendingCalls.length > 0) {
          var pendingCall = this.pendingCalls.shift();
          if (!pendingCall) return;
          var reject = pendingCall.reject;
          reject(error);
        }
      }
    }, {
      key: "throwErrorWithPromise",
      value:
      // 使用Promise.then来抛出错误对象 构造一个虚拟错误对象来模拟产品实例,其中所有的API都会在.then中返回错误对象
      function throwErrorWithPromise(errorObj) {
        var _errorObj$error;
        var message = errorObj === null || errorObj === void 0 || (_errorObj$error = errorObj.error) === null || _errorObj$error === void 0 ? void 0 : _errorObj$error.message;
        var instanceForError = _newInstanceForError(errorObj);
        this.actualInstance = instanceForError;
        this.hasActualInstance = true;
        this.executePendingCalls();
        logger.logError({
          title: message
        }, {
          errorMessage: message,
          constructorName: constructorName
        });
        consoleLogger.error(message);
      }

      // 使用onEventCallback向外抛出SDK内部错误
    }, {
      key: "throwErrorWithOnEventCallback",
      value: function throwErrorWithOnEventCallback(errorObj, newProps) {
        var onEventCallbackFn = newProps === null || newProps === void 0 ? void 0 : newProps.onEventCallback;
        var message = errorObj.message;
        if (typeof onEventCallbackFn === 'function') {
          onEventCallbackFn === null || onEventCallbackFn === void 0 || onEventCallbackFn.call(null, errorObj);
        }
        logger.logError({
          title: message
        }, {
          errorMessage: message,
          constructorName: constructorName
        });
        consoleLogger.error(message);
      }
    }]);
    return BaseProxy;
  }();
  return BaseProxy;
}