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); }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
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); }
import { v4 as uuid } from 'uuid';
import { ERRORMESSAGE } from "../../constant";
import { MessageName } from "../../types";
import { isJsonString } from "../../util";
import { getIframeOrigin, registerSystemEvents, unRegisterSystemEvents } from "../utils/system_events";

/**
 * @author 江跃 <jiangbin.gjb@antgroup.com>
 * @date 2024/9/17
 */
export var EventCenter = /*#__PURE__*/function () {
  function EventCenter() {
    _classCallCheck(this, EventCenter);
    _defineProperty(this, "events", void 0);
    _defineProperty(this, "iframes", void 0);
    _defineProperty(this, "instanceId", void 0);
    this.events = new Map();
    this.iframes = [];
  }

  /**
   * Initializes the event center
   */
  _createClass(EventCenter, [{
    key: "init",
    value: function init(initOptions, instanceId, sdkMetaData) {
      this.instanceId = instanceId;
      this.handleAppMessage = this.handleAppMessage.bind(this);
      window.addEventListener('message', this.handleAppMessage);
      registerSystemEvents(this);
    }

    /**
     * Cleans up event listeners when the event center is destroyed.
     */
  }, {
    key: "destroy",
    value: function destroy() {
      window.removeEventListener('message', this.handleAppMessage);
      this.iframes = [];
      unRegisterSystemEvents(this);
    }

    /**
     * Placeholder for future update logic.
     */
  }, {
    key: "update",
    value: function update() {
      // TODO:
    }

    /**
     * Sets the iframe container and its domain.
     * @param iframe - The HTMLIFrameElement that serves as the container.
     * @param domain - The domain of the app.
     */
  }, {
    key: "addIFrame",
    value: function addIFrame(iframe) {
      this.iframes.push({
        ref: iframe,
        origin: getIframeOrigin(iframe)
      });
    }

    /**
     * Cleans iframes when web app close
     */
  }, {
    key: "cleanIFrames",
    value: function cleanIFrames() {
      this.iframes = [];
    }
  }, {
    key: "removeIFrame",
    value: function removeIFrame(iframe) {
      var index = this.iframes.findIndex(function (item) {
        return item.origin === getIframeOrigin(iframe);
      });
      if (index !== -1) {
        this.iframes.splice(index, 1);
      }
    }

    /**
     * Handles messages received from the app.
     * @param e - The message event.
     */
  }, {
    key: "handleAppMessage",
    value: function handleAppMessage(e) {
      var _e$data;
      if (!this.iframes.some(function (iframe) {
        return iframe.origin === e.origin;
      })) return;
      if (((_e$data = e.data) === null || _e$data === void 0 ? void 0 : _e$data.source) === 'react-devtools-content-script') {
        return; // Ignore messages from React DevTools
      }
      var isJson = isJsonString(e.data);
      if (isJson) {
        var _eventPayload = JSON.parse(e.data);
        if (_eventPayload.context.event && _eventPayload.context.event !== 'onLog') {}
        if (!this.checkEventCompliant(_eventPayload)) {
          return;
        }
        this._handleAppMessage(_eventPayload);
      } else {
        console.error(ERRORMESSAGE.NOT_JSON_FORMAT);
      }
    }
  }, {
    key: "checkEventCompliant",
    value: function checkEventCompliant(eventPayload) {
      // connect element场景下，多子iframes共用AntomCore中生成的instanceId，此时将发送事件方instanceId与iframes中instanceId做比较看是否在其中
      // 非connect场景下，直接将发送事件方instanceId与AntomCore的instanceId做比较
      if (eventPayload.name !== MessageName.APP_TO_SDK) {
        return false;
      }
      var iframesInstanceIds = this.iframes.map(function (iframe) {
        var _iframe$ref;
        if (!new URL((_iframe$ref = iframe.ref) === null || _iframe$ref === void 0 ? void 0 : _iframe$ref.src)) {
          return;
        }
        return new URL(iframe.ref.src).searchParams.get('instanceId');
      }).filter(Boolean);
      if (eventPayload.instanceId !== this.instanceId && !iframesInstanceIds.includes(eventPayload.instanceId)) {
        return false;
      }
      return true;
    }

    /**
     * Processes the application message and emits the associated event.
     * @param data - Parsed EventPayload from the app.
     */
  }, {
    key: "_handleAppMessage",
    value: function _handleAppMessage(eventPayload) {
      var context = eventPayload.context;
      var event = context.event,
        data = context.data;
      this.emit(event, data, eventPayload);
    }

    /**
     * Listens to an event by adding a callback function.
     * @param name - The name of the event to listen for.
     * @param func - The callback function to execute when the event is emitted.
     * @param isAppend - Append to event handlers as chain, default value is false
     */
  }, {
    key: "listen",
    value: function listen(name, func) {
      var isAppend = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
      var eventList = isAppend ? this.events.get(name) || [] : [];
      eventList.push({
        func: func
      });
      this.events.set(name, eventList);
    }

    /**
     * Unsubscribes from an event. If a function is provided, only that function is removed.
     * @param name - The name of the event to unlisten to.
     * @param func - The optional callback function to remove.
     */
  }, {
    key: "unlisten",
    value: function unlisten(name, func) {
      if (func) {
        if (this.events.has(name)) {
          var eventList = this.events.get(name);
          eventList = eventList.filter(function (item) {
            return item.func !== func;
          });
          this.events.set(name, eventList);
        }
      } else {
        this.events.delete(name);
      }
    }

    /**
     * Emits an event, executing all associated callback functions.
     * @param name - The name of the event to emit.
     * @param data - The event data to pass to the event listeners.
     */
  }, {
    key: "emit",
    value: function emit(name, data, eventPayload) {
      if (this.events.has(name)) {
        var eventList = this.events.get(name);
        eventList.forEach(function (item) {
          item.func(data, eventPayload);
        });
      }
    }

    /**
     * Registers a callback for an event and immediately dispatches the event to the app.
     * @param payloadContext - The context containing event information and callback ID.
     * @param func - The callback function to execute when the event is emitted.
     */
  }, {
    key: "emitAndListen",
    value: function emitAndListen(payloadContext, func) {
      if (!payloadContext.eventCallbackId) {
        payloadContext.eventCallbackId = uuid();
      }
      this.listen(payloadContext.eventCallbackId, func);
      this.dispatchToApp(payloadContext);
    }
  }, {
    key: "queryParse",
    value: function queryParse(url) {
      var qs = {};
      var urlString = url;
      if (!urlString) {
        urlString = window.location.href;
      }
      urlString.replace(/([^?=&#]+)(=([^&#]*))?/g, function (_$0, $1, _$2, $3) {
        if ($3 === undefined) {
          return '';
        }
        qs[$1] = decodeURIComponent($3);
        return qs[$1];
      });
      return qs;
    }

    /**
     * Dispatches the event payload to the app via postMessage.
     * @param payloadContext - The context containing event to be dispatched.
     */
  }, {
    key: "dispatchToApp",
    value: function dispatchToApp(payloadContext) {
      var _this$iframes,
        _this = this;
      var data = {
        name: MessageName.SDK_TO_APP,
        context: payloadContext,
        instanceId: this.instanceId
      };
      (_this$iframes = this.iframes) === null || _this$iframes === void 0 || _this$iframes.forEach(function (iframe) {
        var _iframe$origin;
        if (!iframe.ref.contentWindow) {
          console.error('get app contentWindow error', iframe);
          return;
        }
        var _ref = _this.queryParse(iframe.ref.src) || {},
          instanceId = _ref.instanceId;
        iframe.ref.contentWindow.postMessage(JSON.stringify(_objectSpread(_objectSpread({}, data), {}, {
          instanceId: instanceId
        })), (_iframe$origin = iframe.origin) !== null && _iframe$origin !== void 0 ? _iframe$origin : '*');
      });
    }
  }, {
    key: "isExist",
    value: function isExist(name) {
      return this.events.has(name);
    }
  }]);
  return EventCenter;
}();