import { asyncDelay, RandomInt } from "../script/util";
import { AI } from "./AI";
import { NetworkHelper } from "./NetworkHelper";

export class GameServer {
  playerList = [];
  playerMaxNumber = 0;
  networkHelper: NetworkHelper = null;
  nameList = [
    "Chris", "Benny", "Leslie", "Devin", "Sam", "Kerry",
    "Joey", "Hailey", "Fred", "Arrow", "Tony", "Michael",
  ];
  headUrls = [
    "http://staging-teach.cdn.ireadabc.com/0751c28419a0e8ffb1f0e84435b081ce.png",
    "http://staging-teach.cdn.ireadabc.com/f596e586a31ac2813b1702557941c022.png",
    "http://staging-teach.cdn.ireadabc.com/f0f396c52c42239913fd94523db979fa.png",
    "http://staging-teach.cdn.ireadabc.com/9f2d2ef622fa33d4e2abcbdc4b40ab6a.png",
    "http://staging-teach.cdn.ireadabc.com/f40ce4a8630039c4cf48a63fc1399c52.png",
  ];

  params: any;
  gameStatus: any;
  constructor(playerMaxNumber, networkHelper, params) {
    this.playerMaxNumber = playerMaxNumber;
    this.networkHelper = networkHelper;

    this.params = params;

    this._timeoutIds = [];
    this._intervalIds = [];

    this.headUrls = this.headUrls.sort((a, b) => Math.random() - 0.5);
    this.nameList = this.nameList.sort((a, b) => Math.random() - 0.5);

    this.networkHelper.startFrameSync();

    this.gameStatus = {
      round: 0,// 0: 未开始, 1: 游戏中, 2: 已结束
      boats: [],
    };
    for (let i = 0; i < 16; i++) {
      this.gameStatus.boats.push({
        show: false
      });
    }
  }

  async addPlayer(player) {
    console.log("addPlayer");
    this.playerList.push({
      name: this.nameList.splice(0, 1)[0],
      uuid: player.uuid,
      color:
        player.uuid == this.networkHelper.room.roomInfo.owner ? "Blue" : "Red",
      isAI: player.isAI,
      headUrl: this.headUrls.splice(0, 1)[0],
    });

    if (player.isAI) {
      await asyncDelay(1);
      this.networkHelper.sendFrame({
        type: "SERVER_allPlayerInfo",
        playerData: this.playerList,
      });
      if (this.playerList.length == this.playerMaxNumber) {
        this.networkHelper.closeRoom();
        await asyncDelay(0.5);
        this.startGame();
        this.startAI();
      }
    }
  }

  startGame() {
    let idxList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
    const boatList = idxList
      .sort(() => Math.random() - 0.5)
      .splice(0, 8);

    this.gameStatus.round = 1;
    this.gameStatus.boats.forEach((boat, idx) => {
      boat.show = boatList.includes(idx);
    });

    this.networkHelper.sendFrame({
      type: "SERVER_updateStatus",
      status: this.gameStatus,
    });

    console.log('this.params = ', this.params);
    this._timeoutIds.push(setTimeout(() => {
      this.timeOutFlg = true;
      this.checkover();
    }, this.params.roundTime * 1000));
  }

  onPlayerJoin(event) {
    this.addPlayer({
      uuid: event.data.joinPlayerId,
      isAI: false,
    });
  }

  _aiPlayerList = [];
  startMatch() {
    for (let i = 0; i < this.playerMaxNumber; i++) {
      this._timeoutIds.push(
        setTimeout(() => {
          const count = this.playerMaxNumber - this.playerList.length;
          if (count > 0) {
            const playerInfo = {
              uuid: "ai_" + i,
              isAI: true,
              color: "Red",
            };
            this._aiPlayerList.push(new AI(this.networkHelper, playerInfo, this.params));
            this.addPlayer(playerInfo);
          }
        }, RandomInt(10000, 15000))
      );
    }
  }

  async onFrameEvent(data) {
    if (this.gameStatus['gameOver']) {
      return;
    }

    if (data.type == "playerInfo") {
      const player = this.playerList.find(p => p.uuid == data.playerId);
      player.name = data.playerName;
      player.headUrl = data.playerHeadUrl;
      this.networkHelper.sendFrame({
        type: "SERVER_allPlayerInfo",
        playerData: this.playerList,
      });
      if (this.playerList.length == this.playerMaxNumber) {
        this.networkHelper.closeRoom();
        await asyncDelay(0.5);
        this.startGame();
        this.startAI();
      }
    } else if (data.type == "right") {
      if (this.gameStatus.round == 2) {
        return;
      }
      console.log('data.boatIdx = ', data.boatIdx);
      this.gameStatus.boats[data.boatIdx][data.playerId] = 'right';
      this.networkHelper.sendFrame({
        type: "SERVER_updateStatus",
        status: this.gameStatus,
      });
      this.checkover();
    } else if (data.type == "wrong") {
      if (this.gameStatus.round == 2) {
        return;
      }
      console.log('data.boatIdx = ', data.boatIdx);
      this.gameStatus.boats[data.boatIdx][data.playerId] = 'wrong';
      this.networkHelper.sendFrame({
        type: "SERVER_updateStatus",
        status: this.gameStatus,
      });
      this.checkover();
    } else {
      this._aiPlayerList.forEach((ai: AI) => {
        ai.onFrameEvent(data);
      });
    }
  }

  timeOutFlg = false;
  firstCompletePlayerId;
  checkover() {
    if (!this.firstCompletePlayerId) {
      this.playerList.forEach(player => {
        if (this.gameStatus.boats.every(boat => boat[player.uuid])) {
          this.firstCompletePlayerId = player.uuid;
        }
      });
    }

    if (this.gameStatus.boats.some(boat => Object.keys(boat).length != 3)) {
      // 有人没有完成游戏
      if (!this.timeOutFlg) {
        return;
      }
    }
    this.gameStatus.round = 2;
    this.networkHelper.sendFrame({
      type: "SERVER_updateStatus",
      status: this.gameStatus,
    });

    const idScoreMap = {};
    this.gameStatus.boats.forEach(boat => {
      Object.keys(boat).forEach(key => {
        if (boat[key] == 'right') {
          if (!idScoreMap[key]) {
            idScoreMap[key] = 0;
          }
          idScoreMap[key]++;
        }
      });
    });
    let winnerId = null;
    Object.keys(idScoreMap).forEach(key => {
      if (winnerId == null || idScoreMap[key] > idScoreMap[winnerId]) {
        winnerId = key;
      } else if (idScoreMap[key] == idScoreMap[winnerId]) {
        winnerId = this.firstCompletePlayerId;
      }
    });
    this.networkHelper.sendFrame({
      type: "SERVER_playerWin",
      winnerId: winnerId,
    });
  }

  startAI() {
    this.playerList
      .filter((player) => player.isAI == true)
      .forEach((player) => {

      });
  }

  _timeoutIds = null;
  _intervalIds = null;
  // 生命周期
  onDestroy() {
    this._timeoutIds.forEach((id) => {
      clearTimeout(id);
    });
    this._intervalIds.forEach((id) => {
      clearInterval(id);
    });
  }
}
