import MessageEventBus from "./MessageEventBus";
import {isBackgroundScript, isPopupScript} from '../utils/Utils'
import { SendMessage } from "../utils/ResponseUtils";
import IMessageInterface from '../interface/IMessageInterface'
export class PortEventBus extends MessageEventBus implements IMessageInterface{
  script='content';
  port:chrome.runtime.Port|undefined
  portTab:chrome.runtime.Port|undefined
  popupListener:boolean=false;
  constructor (script?:string) {
    super();
    let defaultScript='content'
    if(isBackgroundScript()){
      defaultScript='background'
    }else if(isPopupScript()){
      defaultScript='popup'
    }
    this.script=script||defaultScript;//当前脚本
    this.connect()
  }
  /**
   * 链接(监听)
   */
  connect(){
    let _this=this;
    if(['popup','background'].indexOf(_this.script)>-1){//当是background和popup的时候就是初始化和当前tab的连接
      _this.getCurrentTabs((tabs:any)=>{
        const tabId=tabs.length ? tabs[0].id: null
        if(tabId){//
          _this.portTab = chrome.tabs.connect(tabId, {name: _this.script});
          // console.log('_this.portTab---connect---',tabId,this.portTab)
          _this.portTab.onMessage.addListener(function(requests) {
            // console.log('port onMessage---',requests)
            _this.handler(requests)
          });
          _this.popupListener=true;
        }else{//没有activeId----如果是background.js中$portBus正常获取不到tabId
          this.popListener();//监听tabs.onActivated
        }
      })
    }

    //初始化和popup和background的连接
    // 监听长连接
    let port=chrome.runtime.connect({name:this.script});
    this.port=port;
    // console.log('connect------')
    this.port.onMessage.addListener(function(requests) {
      // console.log('port onMessage---',requests)
      _this.handler(requests)
    });
    this.listener()
    return this
    
  }
  /**
   * contentScript监听
   */
  popListener(){
    let _this=this;
    chrome.tabs.onActivated.addListener(
      ()=>{//
        if(this.popupListener){
          return;//已经监听了
        }
        _this.getCurrentTabs((tabs:any)=>{
          const tabId=tabs.length ? tabs[0].id: null
          _this.popupListener=true;
          _this.portTab = chrome.tabs.connect(tabId, {name: _this.script});
          // console.log('_this.portTab---popListener-----',this.portTab)
          _this.portTab.onMessage.addListener(function(requests) {
            // console.log('port onMessage---',requests)
            _this.handler(requests)
          });
        });
      },
    )
    return this
  }


  /**
   * 需要监听用来接收消息
   */
  listener(){
    let _this=this;
    chrome.runtime.onConnect.addListener((port)=>{
      port.onMessage.addListener((requests)=>{
        // console.log('port onMessage---',requests)
        _this.handler(requests)
      })
    })
    return this
  }

  /**
   * 检查链接
   */
  checkConnect(){
    // console.log('this.connect----',this.port)
    if(this.port==undefined||this.portTab==undefined||this.port.name==''){//空对象的时候自动连接
      this.connect();
    }
    return this
  }
  /**
   * 消息处理
   * @param {*} request 
   */
  async handler(request:SendMessage){
    let type=request.type||''//$emit提交时的事件
    let args=request.message
    if(this.script!==request.script){
      return;
    }
    let _this=this;
    let handler = _this._events.get(type)//所有该类型的函数集合
    if(!handler)return;//无任何监听则退出
    let res='';
    if (Array.isArray(handler)) {
      // 是数组，说明有多个监听者，需要依次触发里边的函数
      for (let i = 0; i < handler.length; ++i) {
        //用call代替apply----有些消息需要确认tabId
        // handler.call(_this, ...args,sender,sendResponse).then(res=>{
        let res=await handler[i].call(_this, ...args)
        //这是无效的发送消息都是通过port  port.postMessage({text: '这里并没有sendResponse！'});
      }
    } else {
      // 单个函数的情况直接触发即可
      //用call代替apply----有些消息需要确认tabId
      // handler.call(_this, ...args,sender,sendResponse).then(res=>{
      let res=await handler.call(_this, ...args)
      //这是无效的发送消息都是通过port  port.postMessage({text: '这里并没有sendResponse！'});
    }
    return this
  }
  
  $emitContent(type: string, ...args: any): Promise<any> {
    if(this.script=='content'){
      return this.$emit(type,...args);
    }
    return new Promise((resolve,reject)=>{
      this.checkConnect();
      // console.log('this.portTab-----',this._script,this.portTab)
      if(this.portTab){
        let message:SendMessage={
          script:'content',
          type: type,//事件名
          message: args
        }
        this.portTab.postMessage(message);
      }else{
        reject('portTab is undefine!')
        return;
        // console.log('portTab is undefine!')
      }
      resolve('')
    })
  }
  $emitBackground(type: string, ...args: any): Promise<any> {
    if(this.script==='background'){
      return this.$emit(type,...args);
    }
    return new Promise((resolve,reject)=>{
      this.checkConnect();
      // console.log('this.portTab-----',this._script,this.portTab)
      if(this.port){
        let message:SendMessage={
          script:'background',
          type: type,//事件名
          message: args
        }
        this.port.postMessage(message);
      }else{
        console.log('port is undefine!')
      }
      resolve('')
    })
  }
  $emitPopup(type: string, ...args: any): Promise<any> {
    if(this.script==='popup'){
      return this.$emit(type,...args);
    }
    return new Promise((resolve,reject)=>{
      this.checkConnect();
      // console.log('this.portTab-----',this._script,this.portTab)
      if(this.port){
        let message:SendMessage={
          script:'popup',
          type: type,//事件名
          message: args
        }
        this.port.postMessage(message);
      }else{
        console.log('port is undefine!')
      }
      resolve('')
    })
  }
  $emitWindow(type: string, ...args: any): Promise<any> {
    throw new Error("Method not support.");
  }
  $emitAllTabs(type: string, ...args: any): Promise<any> {
    throw new Error("Method not support.");
  }
}
const $bus=new PortEventBus()
export default $bus