/*
 * @Author: thy
 * @Date: 2023-10-26 14:56:41
 * @LastEditors: thy
 * @LastEditTime: 2023-12-07 15:41:56
 * @Description: file content
 * @FilePath: \dsk-operate-ui\src\utils\postMessageBridge\bridge\index.js
 */

import EventCenter from "./eventCenter";
import { messageHandlers } from "@/utils/postMessageBridge/action";
import chalk from "@alita/chalk";
window.alitadebug = true;

class PostMessageBridge {
  // 当前系统
  _currentSystem = null;
  // 当前系统域
  _currentOriginUrl = null;
  // 目标系统
  _targetSystem = null;
  // 目标域
  _targetOriginUrl = null;
  // 事件调度中心
  _eventCenter = null;
  // 当前vue实例
  _vueIns = null;
  // 处理函数
  _messageHandlers = null;
  //通信是否建立成功
  _communication = false;

  constructor() { }

  /**
   * 
   * @param {{ 
  * currentSystem : Window || undefined;
  * currentOriginUrl : string;
  * targetSystem : Window || undefined;
  * targetOriginUrl : string || undefined;
  * vueIns : any;
  * }} options 
  */
  async init(options) {
    try {
      this._currentSystem = options.currentSystem;
      this._currentOriginUrl = options.currentOriginUrl || location.origin;
      this._targetSystem = options.targetSystem;
      this._targetOriginUrl = options.targetOriginUrl || "*";
      this._vueIns = options.vueIns || null;
      this._messageHandlers = messageHandlers;
      this._eventCenter = new EventCenter(this._vueIns);
      this._currentSystem.removeEventListener("message", this.messageListener.bind(this), false);
      this._currentSystem.addEventListener("message", this.messageListener.bind(this), false);
      // 初始化完毕
      process.env.ENV != "production" ? chalk.ready(chalk.bgGreen("通信桥梁初始化完毕")) : true;
    } catch (error) {
      console.log(error);
    }
  }

  getVueInstance(insArray, current) {
    if (insArray?.length) {
      const result = insArray.find(item => {
        if (item.$children && item.$children?.length) {
          return this.getVueInstance(item.$children, current);
        }
        return item.$route == current;
      });
      return result;
    }
  }

  /**
   * 触发message 时执行的函数
   * @param {MessageEvent} event 
   * @returns 
   */
  messageListener(event) {
    new Promise(async (resolve, reject) => {
      try {
        const { data, origin, source } = event;
        // 判断来源 必须 来自子系统
        if (origin !== this._targetOriginUrl || source !== this._targetSystem?.contentWindow) return;
        const { callbackId, action, method, params = {}, url, title, id } = data;
        if(callbackId) console.log(callbackId,"回调ID","需要执行的方法",method);
        //兼容插件老式写法
        if (url || title || id) {
          this._vueIns.$tab.openPage(title, url);
          return resolve();
        }
        // 未获取到当前交互id 不执行调用
        if (!callbackId) return;
        // 有注册回调 执行回调
        if (this._eventCenter.getTargetHandler(callbackId)) {
          resolve(this._eventCenter.executeHandler(callbackId, params));
        } else {
          // 订阅消息
          const result = await this.subscribe(action, method, params);
          resolve(result);
        }
      } catch (error) {
        console.log(error);
        reject(error);
      }
    });
  };

  /**
   * 发布消息
   * @param {Object} options 
   * @param {Function} callback 
   */
  async publish(options, callback) {
    if (!options || !callback) return;
    if (!options.action) throw new Error("缺少action参数");
    if (!options.method) throw new Error("缺少method参数");
    if (Object.prototype.toString.call(callback) != "[object Function]") return console.warn("传入的回调不是一个函数");
    options.params = options.params || {};
    // 绑定到vue实例
    const bfn = callback.bind(this._vueIns);
    const callbackId = await this._eventCenter.registerHandler(bfn);
    const { params, ...rest } = options;
    process.env.ENV != "production" ? chalk.log(chalk.bgBlack(`发布消息：\n回调ID:${callbackId}\n命中模块:${options.action}\n命中方法:${options.method}\n传递参数:\n${JSON.stringify(params)}`)) : null;
    this._targetSystem?.contentWindow?.postMessage({
      callbackId,
      ...rest,
      params,
    }, { targetOrigin: this._targetOriginUrl });
    return callbackId;
  }

  /**
   * 订阅消息
   * @param {string} action 执行的模块
   * @param {string} method 执行的方法
   * @param {Object} params 参数
   * @returns 
   */
  async subscribe(action, method, params) {
    try {
      const fn = this._messageHandlers[action] ? this._messageHandlers[action][method] ? this._messageHandlers[action][method] : null : null;
      // 绑定到vue实例
      const result = fn ? await this._messageHandlers[action][method].call(this._vueIns, params) : null;
      return result;
    } catch (error) {
      console.log(router);
    }
  }
}

// 单例模式
export const pmb = new PostMessageBridge();

export default PostMessageBridge;