const upNativeComm = {};
const cmdQueue = {};
const SCHEME = "up";

let count = new Date().getTime();

upNativeComm.exec = function exec(cmd, option) {
  option = option || {};
  count += 1;
  const callbackId = count;
  option.callbackId = callbackId;
  cmdQueue[callbackId] = option.callback || function callback() {};
  delete option.callback;
  const url = `${SCHEME}://["${cmd}",${callbackId},${JSON.stringify(option)}]`;
  prompt("TITLE", url);
};

window.nativeCallback = function nativeCallback(callbackId, code, option) {
  if (cmdQueue[callbackId]) {
    cmdQueue[callbackId](code, option);
  }
};

// /////////////////////////////////// 浜嬩欢鏈哄埗 ///////////////////////////////////

// 閫氱煡瀹㈡埛绔簨浠朵俊鎭�
function notifyEvent(option) {
  const cmd = "up.event";
  upNativeComm.exec(cmd, option);
}

/**
 * 鍒涘缓鍘熺敓鐨別vent瀵硅薄(鍏ㄥ眬鍑芥暟)
 * @param type 绫诲瀷
 * @param data 鏁版嵁
 * @returns {Event}
 */
window.gCreateEvent = function gCreateEvent(type, data) {
  const event = document.createEvent("Events");
  event.initEvent(type, false, false);
  if (data) {
    for (const i in data) {
      if (Object.prototype.hasOwnProperty.call(data, i)) {
        event[i] = data[i];
      }
    }
  }
  return event;
};

// 涓€涓被鍨嬩簨浠跺搴斾竴涓狤ventMeta瀹炰緥
const EventMeta = function EventMeta(type) {
  this.type = type;
  this.handleMap = {}; // 澶勭悊鍑芥暟Map
  this.count = 0;
  this.onHandleCountChange = null;
};

// 鍏ㄥ眬鍑芥暟
window.gEventHandleMap = {
  create(type) {
    window.gEventHandleMap[type] = new EventMeta(type);
    return window.gEventHandleMap[type];
  },
  count: 0, // 鍙ユ焺鏍囪瘑
};

EventMeta.prototype.addEvent = function addEvent(handle) {
  let flag = handle.upEventFlag;
  if (!flag) {
    window.gEventHandleMap.count += 1;
    flag = window.gEventHandleMap.count;
    handle.upEventFlag = flag;
  }

  // 鍚屼竴涓被鍨嬩簨浠剁粦瀹氬涓浉鍚岀殑澶勭悊鍑芥暟锛屽彧鎵ц涓€娆★紝鑻ユ兂鎵ц澶氭锛屽繀椤婚噰鐢ㄥ尶鍚嶇殑鏂瑰紡
  if (!this.handleMap[flag]) {
    this.handleMap[flag] = handle;
    this.count += 1;
    if (this.count === 1) {
      if (this.onHandleCountChange) {
        this.onHandleCountChange();
      }
    }
  }
};

EventMeta.prototype.removeEvent = function removeEvent(handle) {
  const flag = handle.upEventFlag;
  if (this.handleMap[flag]) {
    delete this.handleMap[flag];
    this.count -= 1;
    if (this.count === 0) {
      if (this.onHandleCountChange) {
        this.onHandleCountChange();
      }
    }
  }
};

EventMeta.prototype.fire = function fire(e) {
  if (this.count) {
    // copy澶勭悊鍑芥暟锛岄槻姝㈠湪璋冪敤澶勭悊鍑芥暟鐨勮繃绋嬩腑handleMap鍙戠敓鏀瑰彉
    const handles = [];
    let i = 0;
    const keys = Object.keys(this.handleMap);
    for (i = 0; i < keys.length; i += 1) {
      handles.push(this.handleMap[keys[i]]);
    }

    for (i = 0; i < handles.length; i += 1) {
      handles[i](e);
    }
  }
};

// 娉ㄥ唽浜嬩欢(瀵瑰API)
upNativeComm.addEventListener = function addEventListener(type, handle) {
  let eventInstance = window.gEventHandleMap[type];
  if (!eventInstance) {
    eventInstance = window.gEventHandleMap.create(type);
    eventInstance.onHandleCountChange = function onHandleCountChange() {
      // 閫氱煡瀹㈡埛绔�
      notifyEvent({
        count: this.count,
        type,
      });
    };
  }

  eventInstance.addEvent(handle);
};

// 绉婚櫎浜嬩欢(瀵瑰API)
upNativeComm.removeEventListener = function removeEventListener(type, handle) {
  const eventInstance = window.gEventHandleMap[type];
  if (eventInstance) {
    eventInstance.removeEvent(handle);
  }
};

// 鍏ㄥ眬鍑芥暟浜嬩欢瑙﹀彂鍚庯紝瀹㈡埛绔皟鐢ㄧ殑鍑芥暟
window.nativeFireEvent = function nativeFireEvent(type, param) {
  const instance = window.gEventHandleMap[type];
  if (instance) {
    const evt = window.gCreateEvent(type, param);
    instance.fire(evt);
  }
};

window.upPCNativeComm = upNativeComm;
