export class NetworkHelper {
  _eventListeners: any = {};
  ctor() {}

  on(eventName, func) {
    this._eventListeners[eventName] = func;
  }

  async init(roomType: string, maxPlayers: number) {
    try {
      this.initRoom();
      await this.initListener();
      return await this.joinRoom(roomType, maxPlayers);
    } catch (e) {
      // return null;
    }
  }

  async startGame() {
    await this.startFrameSync();
    await this.closeRoom();
  }

  async stopGame() {
    await this.stopFrameSync();
    await this.closeRoom();
    await this.leaveRoom();
  }

  getRoomInfo() {
    return this.room.roomInfo;
  }

  listenerInited = false;

  initListener() {
    this.log("MGOBE.Player.id = " + MGOBE.Player.id);
    this.log("MGOBE.Player.openId = " + MGOBE.Player.openId);
    if (MGOBE.Player.id !== undefined) {
      return;
    }

    // MGOBE.Listener;
    return new Promise((resolve, reject) => {
      const gameId = "obg-i4ql53h1"; //替换为控制台上的 游戏 ID
      const openId = "openid_op_16" + Math.random();

      const gameInfo: MGOBE.types.GameInfoPara = {
        gameId: gameId,
        openId: openId,
        createSignature: (callback) => {
          this.callNetworkApiGet(
            "http://staging-teach.ireadabc.com",
            "/api/oxford/game/v1/config",
            {
              gameid: gameId,
              openid: openId,
            },
            (data) => {
              callback(JSON.parse(data));
            }
          );
        },
      };

      const serverUrl = "i4ql53h1.wxlagame.com"; //替换为控制台上的 域名
      const config = {
        url: serverUrl,
        reconnectMaxTimes: 3,
        reconnectInterval: 1000,
        resendInterval: 1000,
        resendTimeout: 5000,
        cacertNativeUrl: "",
      };

      MGOBE.DebuggerLog.enable = false;
      // 如果是原生平台，则加载 Cert 证书，否则会提示 WSS 错误
      if (cc.sys.isNative) {
        let cacertFile;
        const cacertNode = cc.find("cacertNode");
        if (cacertNode) {
          cacertFile = cacertNode.getComponent("cacert").cacertFile;
        }

        if (!cacertFile) {
          console.log("没有cacertFile!!!");
        }
        config.cacertNativeUrl =
          cc.loader.md5Pipe && cc.ENGINE_VERSION < "2.4.0"
            ? cc.loader.md5Pipe.transformURL(cacertFile.nativeUrl)
            : cacertFile.nativeUrl;
      }

      this.log("initListener");

      MGOBE.Listener.init(gameInfo, config, async (event) => {
        this.log(JSON.stringify(event));
        if (event.code !== 0) {
          this.log("初始化失败: " + event.code);
          reject();
          return;
        }
        this.listenerInited = true;
        this.log("初始化成功");
        resolve(null);
      });

      this.log("initListener2");
    });
  }

  room: MGOBE.Room;
  initRoom() {
    this.room = new MGOBE.Room();
    MGOBE.Listener.add(this.room);
    this.room.onJoinRoom = this.onJoinRoom.bind(this);
    this.room.onLeaveRoom = this.onLeaveRoom.bind(this);
    this.room.onRecvFromClient = this.onRecvFromClient.bind(this);
    this.room.onChangePlayerNetworkState =
      this.onChangePlayerNetworkState.bind(this);
    this.room.onRecvFrame = this.onRecvFrame.bind(this);
    this.room.onStartFrameSync = this.onStartFrameSync.bind(this);
    this.room.onStopFrameSync = this.onStopFrameSync.bind(this);
    this.room.onRecvFromGameSvr = this.onRecvFromGameSvr.bind(this);
    console.log("this.room = " + JSON.stringify(this.room.roomInfo));
  }

  player;
  joinRoom(roomType: string, maxPlayers: number, customData: string = "") {
    return new Promise((resolve, reject) => {
      const playerName = "Tom" + Math.random();
      const playerInfo = {
        name: playerName,
        customPlayerStatus: 0,
        customProfile: customData,
      };

      const matchRoomPara = {
        playerInfo,
        maxPlayers: maxPlayers,
        roomType: roomType,
      };

      this.room.matchRoom(matchRoomPara, async (event) => {
        // console.log(JSON.stringify(event))
        if (event.code !== 0) {
          this.log("匹配失败");
          reject(event);
          return;
        }
        this.log("匹配成功: " + event.data.roomInfo.id);
        const player = event.data.roomInfo.playerList.find(
          (player) => player.name == playerName
        );
        this.player = player;
        if (this.checkRoomOwnerOffLine()) {
          if (this._eventListeners["playerOffLine"]) {
            this._eventListeners["playerOffLine"](event);
          }
          this.log("房主掉线了");
          resolve(null);
          return;
        }
        resolve(player.id);
      });
    });
  }

  leaveRoom() {
    return new Promise((resolve, reject) => {
      this.room.leaveRoom({}, (event) => {
        console.log(JSON.stringify(event));
        if (event.code === 0) {
          console.log("退房成功" + this.room.roomInfo.id);
          // this.room.initRoom();
          resolve(null);
        } else {
          console.log("退房失败");
        }
      });
    });
  }

  dismissRoom() {
    const roomInfo = this.room.roomInfo;
    const player = roomInfo.playerList.find(
      (player) => player.name == this.player.name
    );
    if (roomInfo.owner == player.id) {
      return new Promise((resolve, reject) => {
        this.room.dismissRoom({}, (res) => {
          console.log("房间已解散");
        });
      });
    }
  }

  closeRoom() {
    return new Promise((resolve, reject) => {
      this.room.changeRoom({ isForbidJoin: true }, (event) => {
        console.log("关门");
        // console.log(JSON.stringify(event))
        resolve(null);
      });
    });
  }

  sendMessage() {
    const sendToClientPara = {
      recvType: MGOBE.ENUM.RecvType.ROOM_ALL,
      recvPlayerList: [],
      msg: "hello" + Math.random(),
    };
    this.room.sendToClient(sendToClientPara, (event) => console.log(event));
  }

  startFrameSync() {
    return new Promise((resolve, reject) => {
      this.room.startFrameSync({}, (event) => {
        console.log(JSON.stringify(event));
        if (event.code === 0) {
          cc.log("开始帧同步成功，请到控制台查看具体帧同步信息");
          resolve(null);
        } else {
          reject();
        }
      });
    });
  }

  stopFrameSync() {
    return new Promise((resolve, reject) => {
      if (!this.room) {
        resolve(null);
        return;
      }
      this.room.stopFrameSync({}, (event) => {
        console.log(JSON.stringify(event));
        if (event.code === 0) {
          console.log("停止帧同步成功");
          resolve(null);
        } else {
          console.log("停止帧同步失败");
          reject(event.code);
        }
      });
    });
  }

  sendToServer() {
    const sendToGameServerPara = {
      data: {
        cmd: 1,
      },
    };
    this.room.sendToGameSvr(sendToGameServerPara, (event) =>
      console.log(event)
    );
  }

  sendFrame(data: any) {
    console.log('sendFrame: ' + JSON.stringify(data));
    this.room.sendFrame({ data }, (err) => {
      if (err.code != 0) {
        console.log("err", err);
      }
    });
  }

  onJoinRoom(event) {
    if (this._eventListeners["playerJoin"]) {
      this._eventListeners["playerJoin"](event);
    }
    console.log("新玩家加入", event.data.joinPlayerId);
  }
  onLeaveRoom(event) {
    console.log("onLeaveRoom");
    if (this._eventListeners["playerLeave"]) {
      this._eventListeners["playerLeave"](event);
    }
    console.log("玩家退出", event.data.leavePlayerId);
  }
  onRecvFromClient() {}

  checkRoomOwnerOffLine() {
    return this.room.roomInfo.playerList.some(player=>{
      return (
        player.commonNetworkState == MGOBE.types.NetworkState.COMMON_OFFLINE ||
        player.relayNetworkState == MGOBE.types.NetworkState.RELAY_OFFLINE
      );
    })
    
  }
  onChangePlayerNetworkState(event) {
    this.log("玩家网络变化: " + JSON.stringify(event));
    if (this.checkRoomOwnerOffLine()) {
      if (this._eventListeners["playerOffLine"]) {
        this._eventListeners["playerOffLine"](event);
      }
      this.log("房主掉线了");
    }
  }

  onRecvFrame(event) {
    if (this._eventListeners["frameEvent"]) {
      this._eventListeners["frameEvent"](event);
    }
  }
  onStartFrameSync(event) {
    if (this._eventListeners["gameStart"]) {
      this._eventListeners["gameStart"](event);
    }
  }
  onStopFrameSync(event) {}
  onRecvFromGameSvr() {}

  async onDestroy() {
    try {
      console.log("onDestroy1");
      MGOBE.Listener.clear();
      this.stopFrameSync();
      this.closeRoom();
      this.dismissRoom();
      this.leaveRoom();
      console.log("onDestroy2");
    } catch (e) {
      console.log(JSON.stringify(e));
    }
  }

  log(str) {
    const node = cc.find("middleLayer");
    if (node) {
      node.getComponent("middleLayer").log(str);
    } else {
      cc.log(str);
    }
  }

  callNetworkApiGet(baseUrl, uri, data, callBack) {
    let queryStr = "?";
    const params = [];
    for (const key in data) {
      if (Object.hasOwnProperty.call(data, key)) {
        params.push(`${key}=${data[key]}`);
      }
    }
    queryStr += params.join("&");
    const xhr = new XMLHttpRequest();
    xhr.onreadystatechange = () => {
      if (xhr.readyState == 4 && xhr.status >= 200 && xhr.status < 400) {
        callBack(xhr.responseText);
      }
    };
    const url = `${baseUrl}${uri}${queryStr}`;
    console.log("url = " + url);
    xhr.open("GET", url, true);
    xhr.send();
  }
}

export function asyncDelay(time) {
  return new Promise((resolve, reject) => {
    cc.tween(cc.find("Canvas"))
      .delay(time)
      .call(() => {
        resolve(null);
      })
      .start();
  });
}
