import MessageEventBus from "./MessageEventBus";
import {isBackgroundScript, isContentScript, isFunctionAsync, isPopupScript, isPromise} from '../utils/Utils'
import ResponseUtils, { SendMessage,ResponseMessage } from "../utils/ResponseUtils";
import IMessageInterface from "../interface/IMessageInterface";
import { KeyValue } from "../types/KeyValue";
interface SendMessageBridge{
  script:string;//发送方
  bridgeType:string;//桥接消息类型---统一
  type:string;//消息类型---动态
  message:any;//消息数据
}
export class RuntimeEventBus extends MessageEventBus implements IMessageInterface{
  script:string='content'
  types:KeyValue={
    content2AllTabs:'_message_bridge_content2AllTabs_',
  }
  constructor (script?:string) {
    super();
    let defaultScript='content'
    if(isBackgroundScript()){
      defaultScript='background'
    }else if(isPopupScript()){
      defaultScript='popup'
    }
    this.script=script||defaultScript;//当前脚本
    this.listener()
    this.listenerBridge()
  }
  
  listener(): void {
    let _this=this
    chrome.runtime.onMessage.addListener(function(request,sender,sendResponse){
      if(sender.id!=chrome.runtime.id){//不属于当前插件
        return;
      }
      let script=request.script
      if(_this.script!==script){//不是当前脚本的请求
        return;
      }
      _this.handler(request,sender,sendResponse)
      return true;
    });
  }

  /**
   * content2AllTabs需要中转
   */
  listenerBridge(){
    if(this.script==='background'){
      let _this=this
      // console.log('listener bridge-----')
      chrome.runtime.onMessage.addListener(function(request:SendMessageBridge,sender,sendResponse){
        if(sender.id!=chrome.runtime.id&&!_this.crossExtension){//不属于当前插件
          return;
        }
        let script=request.script
        if(_this.script!==script){//不是当前脚本的请求
          return;
        }
        // console.log('bridge-----',_this.script,request)
        switch (request.bridgeType) {
          case _this.types.content2AllTabs:
            _this.$emitAllTabs(request.type,...request.message)
            break;
          default:
            break;
        }
        return true;
      });
    }
  }
  /**
   * 消息处理
   * @param {*} request:any
   * @param {*} sender:chrome.runtime.MessageSender 
   * @param {*} sendResponse:any
   */
  async handler(request:SendMessage,sender:chrome.runtime.MessageSender,sendResponse:any){
    let type=request.type||''//$emit提交时的事件
    let args=request.message
    let _this=this;
    let handler = _this._events.get(type)//所有该类型的函数集合
    if(!handler)return;//无任何监听则退出
      if (Array.isArray(handler)) {
        // 是数组，说明有多个监听者，需要依次触发里边的函数
        for (let i = 0; i < handler.length; ++i) {
          let res:any=''
          if(isFunctionAsync(handler[i])){
            handler[i].call(_this, ...args,sender,sendResponse).then((data:any)=>{
              sendResponse(ResponseUtils.success(data))
            }).catch((e:any)=>{
              sendResponse(ResponseUtils.error(e))//默认发送
            })
          }else{
            res=handler[i].call(_this, ...args,sender,sendResponse)
            if(isPromise(res)){
              res.then((r:any)=>{
                sendResponse(ResponseUtils.success(r))
              }).catch((e:any)=>{
                sendResponse(ResponseUtils.error(e))//默认发送
              })
            }else if(res){
              sendResponse(ResponseUtils.success(res))//发送返回值来实现$emit中Promise返回内容
            }else{
              sendResponse(ResponseUtils.error('未知错误'))//发送返回值来实现$emit中Promise返回内容
            }
          }
        }
      } else {
        // 单个函数的情况直接触发即可
        // let res=await handler.call(_this, ...args,sender,sendResponse)
        let res:any=''
        if(isFunctionAsync(handler)){
          handler.call(_this, ...args,sender,sendResponse).then((data:any)=>{
            sendResponse(ResponseUtils.success(data))
          }).catch((e:any)=>{
            sendResponse(ResponseUtils.error(e))//默认发送
          })
        }else{
          res=handler.call(_this, ...args,sender,sendResponse)
          if(isPromise(res)){
            res.then((r:any)=>{
              sendResponse(ResponseUtils.success(r))
            }).catch((e:any)=>{
              sendResponse(ResponseUtils.error(e))//默认发送
            })
          }else if(res){
            sendResponse(ResponseUtils.success(res))//发送返回值来实现$emit中Promise返回内容
          }else{
            sendResponse(ResponseUtils.error('未知错误'))//发送返回值来实现$emit中Promise返回内容
          }
        }
      }
  }
  $emitContent(type: string, ...args: any): Promise<any> {
    let _this=this
    let _script='content';
    if(_this.script===_script){//
      
      return new Promise((resolve,reject)=>{
        chrome.runtime.sendMessage({
          script:'content',//发送给background的
          type: type,//事件名
          message: args
        },(response:ResponseMessage)=>{
          if(ResponseUtils.isSuccess(response)){
            resolve(response.data)
          }else{
            reject(response.message)
          }
        });
      })
    }
    return new Promise((resolve,reject)=>{//调整成Promise
      _this.getCurrentTabs((tabs:any)=>{
        const tabId=tabs.length ? tabs[0].id: null
        if(!tabId){
          reject('找到激活的tab')
        }
        const message:SendMessage={
          script:_script,
          type: type,//事件名
          message: args
        }
        // console.log('ssss',message)
        chrome.tabs.sendMessage(tabId, message, function(response){
          // console.log('response=====',response);
          if(ResponseUtils.isSuccess(response)){
            resolve(response.data)
          }else{
            reject(response.message)
          }
        });
      })
    })
  }
  $emitBackground(type: string, ...args: any): Promise<any> {
    let _this=this
    let _script='background';
    return new Promise((resolve,reject)=>{
      const message:SendMessage={
        script:_script,
        type: type,//事件名
        message: args
      }
      chrome.runtime.sendMessage(message,(response:ResponseMessage)=>{
        if(ResponseUtils.isSuccess(response)){
          resolve(response.data)
        }else{
          reject(response.message)
        }
      });
    })
  }
  $emitPopup(type: string, ...args: any): Promise<any> {
    let _this=this
    let _script='popup';
    return new Promise((resolve,reject)=>{
      const message:SendMessage={
        script:_script,
        type: type,//事件名
        message: args
      }
      chrome.runtime.sendMessage(message,(response:ResponseMessage)=>{
        if(ResponseUtils.isSuccess(response)){
          resolve(response.data)
        }else{
          reject(response.message)
        }
      });
    })
  }
  $emitWindow(type: string, ...args: any): Promise<any> {
    switch (this.script) {//只支持contentScript
      case 'content':
        return new Promise((resolve,reject)=>{
          window.postMessage({
            script:'window',
            type:type,
            message:args
          })
        })
      default:
        throw new Error("当前页面不支持发送消息给window.");
    }
  }
  $emitAllTabs(type: string, ...args: any): Promise<any> {
    let _this=this
    let _script='content';
    if(_this.script===_script){//contentScript本身
      return new Promise((resolve,reject)=>{
        chrome.runtime.sendMessage({
          bridgeType:_this.types.content2AllTabs,
          script:'background',
          type: type,//事件名
          message: args
        },(response:ResponseMessage)=>{
          // console.log('response=====',response);
          if(ResponseUtils.isSuccess(response)){
            resolve(response.data)
          }else{
            reject(response.message)
          }
        });
      })
    }
    return new Promise((resolve,reject)=>{//调整成Promise
      _this.getTabs((tabs:any)=>{
        // console.log('tabs----',tabs,args)
        if(tabs&&Array.isArray(tabs)&&tabs.length>0){
          for(let i=0;i<tabs.length;i++){
            const tabId=tabs[i].id|| null
            const message:SendMessage={
              script:_script,
              type: type,//事件名
              message: args
            }
            chrome.tabs.sendMessage(tabId, message, function(response){
              // console.log('response=====',response);
              if(i===tabs.length){//最后一个发送完成
                if(ResponseUtils.isSuccess(response)){
                  resolve(response.data)
                }else{
                  reject(response.message)
                }
              }
            });
          }
        }else{
          reject('找到激活的tab')
        }
        
      },{})//{windowType:'normal'}
    })
  }
}
const $bus=new RuntimeEventBus()
export default $bus