import { RandomInt } from "./util";

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

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

  async init(roomType: string, maxPlayers: number) {
    await this.initRoom();
    return await this.joinRoom(roomType, maxPlayers);
  }

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

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

  listenerInited = false;

  room: any;
  client: any;
  async initRoom() {
    const client = new globalThis.Play.Client({
      appId: "JCKc6bU8FywdjIPupjNH8Jwx-gzGzoHsz",
      appKey: "WUrRDpb46z2qFLsUNbhknYcP",
      userId: `${new Date().getTime()}_${RandomInt(100000000)}`,
      playServer: 'https://lyn5nahs.lc-cn-n1-shared.com'
    });
    console.log('client = ', client);
    await client.connect();
    this.client = client;
    console.log('连接成功');
  }

  player: any;
  joinRoom(roomType: string, maxPlayers: number) {
    return new Promise((resolve, reject) => {
      const roomProp = { roomType, maxPlayers };
      this.client.joinRandomRoom({
        matchProperties: roomProp,
      }).then((room) => {
        resolve(this.onJoinRoomSuccess(room));
      }).catch((error) => {
        console.log('加入房间失败');
        if (error.code == 4301) {
          const options = {
            visible: true,
            playerTtl: 0,
            emptyRoomTtl: 0,
            maxPlayerCount: maxPlayers,
            customRoomProperties: roomProp,
            customRoomPropertyKeysForLobby: ['roomType', 'maxPlayers'],
            flag: globalThis.Play.CreateRoomFlag.MasterUpdateRoomProperties
          };
          this.client.createRoom({
            roomOptions: options,
          }).then((room) => {
            resolve(this.onJoinRoomSuccess(room));
          }).catch((error) => {
            console.error(error.code, error.detail);
          });
        }
      });
    });
  }

  onJoinRoomSuccess(room: globalThis.Play.Room) {
    console.log('加入房间成功 room = ', room);
    const playerMe = room.playerList.find(player => player.isLocal);
    const masterPlayer = room.playerList.find(player => player.isMaster);
    const masterId = masterPlayer.userId;
    const playerId = playerMe.userId;
    this.room = new FakeRoom(masterId);
    this.room.players.push(this.room.player);
    this.player = this.room.player;

    this.client.on(globalThis.Play.Event.PLAYER_ROOM_LEFT, (event) => {
      this.onLeaveRoom({ data: { leavePlayerId: event.leftPlayer.userId } });
    });
    this.client.on(globalThis.Play.Event.PLAYER_ROOM_JOINED, (event) => {
      this.onJoinRoom({ playerId: event.newPlayer.userId });
    });
    this.client.on(globalThis.Play.Event.CUSTOM_EVENT, (event) => {
      this.onRecvFrame({ data: event.eventData });
    });
    // this.room.onDisconnect(this.onDisconnect.bind(this));
    // this.room.onDismiss(this.onDisconnect.bind(this));
    return playerId;
  }

  async leaveRoom() {
    await this.client.close();
    console.log("退房成功");
  }

  async dismissRoom() {
    if (this.room.ownerId == this.player.id) {
      console.log("房间已解散");
    }
  }

  async closeRoom() {
    // 设置房间不可见
    await this.client.setRoomVisible(false);
    console.log(this.client.room.visible);
  }

  async startFrameSync() {
    console.log("开始帧同步成功");
  }

  async stopFrameSync() {
    console.log("停止帧同步成功");
  }

  sendFrame(data: any) {
    this.client.sendEvent(0, { frame: { items: [{ data: data }] } }, {
      receiverGroup: globalThis.Play.ReceiverGroup.All,
    });
  }

  onJoinRoom(event) {
    console.log("新玩家加入", event);
    if (this._eventListeners["playerJoin"]) {
      this._eventListeners["playerJoin"](event);
    }
    this.room.players.forEach(player => {
      console.log('player.playerId = ', player.playerId);
    });
  }
  onLeaveRoom(event) {
    console.log("onLeaveRoom");
    if (this._eventListeners["playerLeave"]) {
      this._eventListeners["playerLeave"](event);
    }
    console.log("玩家退出", event.data.leavePlayerId);
  }
  onRecvFromClient() { }

  onDisconnect(event) {
    this.log("玩家掉线了: " + JSON.stringify(event));
    if (this._eventListeners["playerOffLine"]) {
      this._eventListeners["playerOffLine"](event);
    }
  }

  onRecvFrame(event) {
    if (this._eventListeners["frameEvent"]) {
      this._eventListeners["frameEvent"](event);
    }
  }
  onStartFrameSync(event) {
    console.log('onStartFrameSync');
    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();
  });
}

class FakeRoom {
  ownerId;
  players = [];
  player: any;
  roomInfo;
  constructor(playerId) {
    this.player = { playerId: playerId };
    this.ownerId = playerId;
    this.roomInfo = { owner: playerId }
  }
}