import {
  asyncDelay,
  asyncPlayDragonBoneAnimation,
  asyncTweenTo,
  onHomeworkFinish,
  RandomInt,
} from "../script/util";
import { MyCocosSceneComponent } from "../script/MyCocosSceneComponent";
import { NetworkHelper } from "../script/NetworkHelper";
import { GameServer } from "../script/Server";

let win: any = window;
let courseware = win.courseware;
const { ccclass, property } = cc._decorator;

@ccclass
export default class SceneComponent extends MyCocosSceneComponent {
  @property(cc.Prefab)
  loadingLayerPrefab = null;

  addPreloadImage() {
    // TODO 根据自己的配置预加载图片资源
    // this._imageResList.push({ url: this.data.pic_url });
  }

  addPreloadAudio() {
    // TODO 根据自己的配置预加载音频资源
    this.data.gameStartAudio && this._audioResList.push({ url: this.data.gameStartAudio });
    this.data.gameLoadingAudio && this._audioResList.push({ url: this.data.gameLoadingAudio });
    this.data.waitingWheel && this._audioResList.push({ url: this.data.waitingWheel });
    this.data.waitingPiece && this._audioResList.push({ url: this.data.waitingPiece });
    this.data.waitingTurn && this._audioResList.push({ url: this.data.waitingTurn });
  }

  addPreloadAnima() { }

  onLoadEnd() {
    // TODO 加载完成后的逻辑写在这里, 下面的代码仅供参考

    this.log("onLoadEnd");
    this.initData();
    this.initView();
    this.initListener();
  }

  _status = {
    Red: 0,
    Blue: 0,
    letter: "",
    current: "Red",
  };
  playerId;
  isRoomOwner;
  server: GameServer;
  networkHelper: NetworkHelper;
  recordWaitCount;
  async initData() {
    this.networkHelper = new NetworkHelper();
    this.initNetworkListener();
    do {
      this.playerId = await this.networkHelper.init("l2_boardgame2_tree", 2);
      if (this.playerId === null) {
        console.log("onDestroy");
        this.networkHelper.onDestroy();
      }
      console.log("this.playerId = " + this.playerId);
    } while (this.playerId === null);

    const room = this.networkHelper.room;
    if (this.playerId == room.roomInfo.owner) {
      console.log("房主");
      this.isRoomOwner = true;
      this.server = new GameServer(2, this.networkHelper);
      this.server.jumpList = this.getJumpList();
      await this.networkHelper.startFrameSync();
      this.server.addPlayer({
        uuid: this.playerId,
        isAI: false,
      });
      this.server.startMatch();
    }
    await this.initHeadImgAndName();
    this.recordWaitCount = 0;
  }

  async initHeadImgAndName() {
    const playerInfo: any = {
      playerHeadUrl: "http://staging-teach.cdn.ireadabc.com/0751c28419a0e8ffb1f0e84435b081ce.png",
      playerName: "test",
    };
    const middleLayer = cc.find("middleLayer");
    if (middleLayer) {
      const middleLayerComponent = middleLayer.getComponent("middleLayer");
      if (middleLayerComponent.getUserInfo && middleLayerComponent.getHeadUrl) {
        const kidInfo = await middleLayerComponent.getUserInfo();
        const playerHeadUrl = middleLayerComponent.getHeadUrl(kidInfo.avatar_url || kidInfo.id);
        playerInfo.playerHeadUrl = playerHeadUrl;
        playerInfo.playerName = kidInfo.nick_name || '拼读达人';
      }
    }
    this.networkHelper.sendFrame({
      type: "playerInfo",
      playerId: this.playerId,
      playerName: playerInfo.playerName,
      playerHeadUrl: playerInfo.playerHeadUrl,
    });
  }

  initView() {
    this.addComponents();
    this.hideVoice();
    this.initBg();
    this.initLoadingLayer();
    this.initPiece();
  }
  addComponents() {
    cc.find('Canvas/bg/chessBoard/boardItems').children.forEach(node => {
      let itemData = node.getComponent("BoardGame2_ItemData");
      if (!itemData) {
        itemData = node.addComponent('BoardGame2_ItemData');
        let name = node.name;
        console.log(name);
        if (name == 'start' || name == 'end') {

        } else {
          let arr = name.split('_');
          itemData.letter = arr[1];
          itemData.idx = Number(arr[0]);
          itemData.word = arr[1];
          itemData.jump = 0;
        }
      }
    });
  }

  getJumpList() {
    const jumpList = [];
    cc.find('Canvas/bg/chessBoard/boardItems').children.forEach(node => {
      const itemData = node.getComponent("BoardGame2_ItemData");
      if (itemData.jump) {
        const from = itemData.idx;
        const to = itemData.jump;
        jumpList.push({ from, to });
      }
    });
    return jumpList;
  }

  initBg() {
    const canvas = cc.find("Canvas");
    const bgImg = cc.find("Canvas/bgImg");
    bgImg.scale = Math.max(
      canvas.width / bgImg.width,
      canvas.height / bgImg.height
    );

    const bg = cc.find("Canvas/bg");
    bg.scale = Math.min(canvas.width / bg.width, canvas.height / bg.height);

    const chessBoardBg = cc.find("Canvas/bg/chessBoard/bg");

    const offsetX =
      (chessBoardBg.width * chessBoardBg.scaleX) / 2 +
      (canvas.width - chessBoardBg.width * chessBoardBg.scaleX) / 4;
    const lifeblue = cc.find("Canvas/bg/Lifeblue");
    lifeblue.x = offsetX;
    const lifered = cc.find("Canvas/bg/Lifered");
    lifered.x = -offsetX;
  }

  loadingLayer;
  initLoadingLayer() {
    const loadingLayerBase = cc.find("Canvas/bg/loadingLayerBase");

    const loadingLayerNode = cc.instantiate(this.loadingLayerPrefab);
    loadingLayerBase.addChild(loadingLayerNode);

    this.loadingLayer = loadingLayerNode.getComponent("BoardGame_tree_LoadingLayer");
    this.loadingLayer.setMaxPlayerNumber(2);
    this.loadingLayer.onLoadFinished(() => {
      this.playAudioByUrl(this.data.gameStartAudio);
    });

    this.playAudioByUrl(this.data.gameLoadingAudio);
  }

  blinkTheDice() {
    const dice = cc.find("Canvas/bg/chessBoard/diceBg/hatBlink");
    cc.tween(dice)
      .set({ opacity: 0 })
      .to(0.2, { opacity: 255 })
      .to(0.2, { opacity: 0 })
      .union()
      .repeatForever()
      .start();

    cc.find("Canvas/bg/chessBoard/diceBg").children.forEach((node) => {
      cc.tween(node)
        .set({ scale: 1 })
        .to(0.2, { scale: 1.1 })
        .to(0.2, { scale: 1.0 })
        .union()
        .repeatForever()
        .start();
    });

    const dice2 = cc.find("Canvas/bg/chessBoard/diceBg/dice");
    dice2["canClick"] = true;
  }

  stopBlinkTheDice() {
    const dice = cc.find("Canvas/bg/chessBoard/diceBg/hatBlink");
    dice.stopAllActions();
    cc.find("Canvas/bg/chessBoard/diceBg").children.forEach((node) => {
      node.stopAllActions();
      node.scale = 1;
      node.opacity = 255;
    });
    const dice2 = cc.find("Canvas/bg/chessBoard/diceBg/dice");
    dice2["canClick"] = false;
  }

  greyDice() {
    cc.find("Canvas/bg/chessBoard/diceBg").children.forEach((node) => {
      node.color = cc.color(150, 150, 150);
    });
  }

  stopGreyDice() {
    cc.find("Canvas/bg/chessBoard/diceBg").children.forEach((node) => {
      node.color = cc.color(255, 255, 255);
    });
  }

  initPiece() {
    const offsetX = { Red: -45, Blue: 45 };
    const offsetY = { Red: -90, Blue: -90 };
    const board = cc.find("Canvas/bg/chessBoard/boardItems");

    const pieceNodeRed = cc.find(`Canvas/bg/chessBoard/pieceRed`);
    const startIdxRed = this._status["Red"];
    const boardNodeRed = board.children[startIdxRed];
    pieceNodeRed.x = boardNodeRed.x + offsetX.Red;
    pieceNodeRed.y = boardNodeRed.y + offsetY.Red;

    const pieceNodeBlue = cc.find(`Canvas/bg/chessBoard/pieceBlue`);
    const startIdxBlue = this._status["Blue"];
    const boardNodeBlue = board.children[startIdxBlue];
    pieceNodeBlue.x = boardNodeBlue.x + offsetX.Blue;
    pieceNodeBlue.y = boardNodeBlue.y + offsetY.Blue;
  }

  initListener() {
    const btn = cc.find("Canvas/bg/New Button");
    btn.on("click", async () => {
      // const idx = RandomInt(6);
      // await this.rollTheDice(idx);
      // this._status.letter = ["1", "2", "3", "1", "2", "3"][idx];
      // //执行位移
    });

    const dice = cc.find("Canvas/bg/chessBoard/diceBg/dice");
    dice.on("click", () => {
      if (this._status.letter != "") {
        return;
      }
      if (!dice["canClick"]) {
        return;
      }
      const playerMe = this.allPlayerList.find(
        (player) => player.uuid == this.playerId
      );

      if (this._status.current == playerMe.color) {
        this.networkHelper.sendFrame({
          type: "roll",
          uuid: playerMe.uuid,
        });
      }
    });

    const pieceBlue = cc.find("Canvas/bg/chessBoard/pieceBlue");
    this.addPieceTouchEventListener(pieceBlue, "Blue");

    const pieceRed = cc.find("Canvas/bg/chessBoard/pieceRed");
    this.addPieceTouchEventListener(pieceRed, "Red");

    const coolCat = cc.find("Canvas/bg/tree/catBase/cat");
    const catBtn = cc.find("Canvas/bg/tree/catBase/catBtn");
    catBtn.on("click", async () => {
      asyncPlayDragonBoneAnimation(coolCat, "begin");
      const playerMe = this.allPlayerList.find((player) => player.uuid == this.playerId);
      if (this.audioId) cc.audioEngine.stop(this.audioId);
      if (playerMe.color == this._status.current) {
        if (this._status.letter == "") {
          this.audioId = await this.playAudioByUrl(this.data.waitingWheel);
        } else {
          this.audioId = await this.playAudioByUrl(this.data.waitingPiece);
        }
      } else {
        this.audioId = await this.playAudioByUrl(this.data.waitingTurn);
      }
      asyncPlayDragonBoneAnimation(coolCat, "normal", 0);
    });
  }
  private audioId: any;

  addPieceTouchEventListener(node: cc.Node, color) {
    return;
    // node.on(cc.Node.EventType.TOUCH_START, (event: cc.Event.EventTouch) => {
    //   const playerMe = this.allPlayerList.find(
    //     (player) => player.uuid == this.playerId
    //   );
    //   if (playerMe.color != this._status.current) {
    //     this.blinkPiece(node);
    //     return;
    //   }
    //   if (this._status.current != color) {
    //     this.blinkPiece(node);
    //     return;
    //   }
    //   if (this._status.letter == "") {
    //     this.blinkPiece(node);
    //     return;
    //   }
    //   if (node["cantMove"]) {
    //     this.blinkPiece(node);
    //     return;
    //   }
    //   this.stopRollPiece(node);
    //   node["touchStartPos"] = {
    //     nodeX: node.x,
    //     nodeY: node.y,
    //     touchX: event.getLocation().x,
    //     touchY: event.getLocation().y,
    //   };
    //   node.zIndex = 1;
    //   this.showStars(node);
    // });
    // node.on(cc.Node.EventType.TOUCH_MOVE, (event: cc.Event.EventTouch) => {
    //   const playerMe = this.allPlayerList.find(
    //     (player) => player.uuid == this.playerId
    //   );
    //   if (playerMe.color != this._status.current) {
    //     return;
    //   }
    //   if (this._status.current != color) {
    //     return;
    //   }
    //   if (this._status.letter == "") {
    //     return;
    //   }
    //   if (node["cantMove"]) {
    //     return;
    //   }
    //   const pos = event.getLocation();
    //   const touchStartPos = node["touchStartPos"];
    //   const worldNodePos = node.parent.convertToWorldSpaceAR(
    //     cc.v2(touchStartPos.nodeX, touchStartPos.nodeY)
    //   );
    //   const nodePos = node.parent.convertToNodeSpaceAR(
    //     cc.v2(
    //       worldNodePos.x + pos.x - touchStartPos.touchX,
    //       worldNodePos.y + pos.y - touchStartPos.touchY
    //     )
    //   );
    //   node.setPosition(nodePos);
    // });
    // node.on(cc.Node.EventType.TOUCH_END, async (event: cc.Event.EventTouch) => {
    //   const playerMe = this.allPlayerList.find(
    //     (player) => player.uuid == this.playerId
    //   );
    //   if (playerMe.color != this._status.current) {
    //     return;
    //   }
    //   if (this._status.current != color) {
    //     return;
    //   }
    //   if (this._status.letter == "") {
    //     return;
    //   }
    //   if (node["cantMove"]) {
    //     return;
    //   }
    //   node["cantMove"] = true;
    //   if (this.checkNodeInRightBlock(node, color)) {
    //     const idx = this.getNextRightIdx();
    //     const playerMe = this.allPlayerList.find(
    //       (player) => player.uuid == this.playerId
    //     );
    //     this.networkHelper.sendFrame({
    //       type: "right",
    //       idx: idx,
    //       uuid: playerMe.uuid,
    //       color: playerMe.color,
    //     });
    //   } else {
    //     const playerMe = this.allPlayerList.find(
    //       (player) => player.uuid == this.playerId
    //     );
    //     this.networkHelper.sendFrame({
    //       type: "wrong",
    //       uuid: playerMe.uuid,
    //       color: playerMe.color,
    //     });
    //   }
    // });
    // node.on(cc.Node.EventType.TOUCH_CANCEL, async (event: cc.Event.EventTouch) => {
    //   const playerMe = this.allPlayerList.find(
    //     (player) => player.uuid == this.playerId
    //   );
    //   if (playerMe.color != this._status.current) {
    //     return;
    //   }
    //   if (this._status.current != color) {
    //     return;
    //   }
    //   if (this._status.letter == "") {
    //     return;
    //   }
    //   if (node["cantMove"]) {
    //     return;
    //   }
    //   node["cantMove"] = true;
    //   if (this.checkNodeInRightBlock(node, color)) {
    //     const idx = this.getNextRightIdx();
    //     const playerMe = this.allPlayerList.find(
    //       (player) => player.uuid == this.playerId
    //     );
    //     this.networkHelper.sendFrame({
    //       type: "right",
    //       idx: idx,
    //       uuid: playerMe.uuid,
    //       color: playerMe.color,
    //     });
    //   } else {
    //     const playerMe = this.allPlayerList.find(
    //       (player) => player.uuid == this.playerId
    //     );
    //     this.networkHelper.sendFrame({
    //       type: "wrong",
    //       uuid: playerMe.uuid,
    //       color: playerMe.color,
    //     });
    //   }
    // });
  }

  blinkPiece(node) {
    if (node['rightTween']) {
      return;
    }
    node.stopAllActions();
    cc.tween(node)
      .set({ scale: 1 })
      .to(0.05, { scale: 1.05 })
      .to(0.05, { scale: 1 })
      .start();
  }

  rollPiece(node: cc.Node) {
    node.stopAllActions();
    // cc.tween(node)
    //   .set({ scale: 1, angle: 0 })
    //   .to(0.1, { angle: -10 })
    //   .to(0.2, { angle: 10 })
    //   .to(0.1, { angle: 0 })
    //   .delay(1)
    //   .union()
    //   .repeatForever()
    //   .start();

    //子节点放大效果
    // const board = cc.find("Canvas/bg/chessBoard/boardItems");
    // board.children.forEach((child: cc.Node, idx, list) => {
    //   cc.tween(child)
    //     .set({ scale: 1.34 })
    //     .delay(idx * 0.1)
    //     .to(0.1, { scale: 1.5 })
    //     .to(0.1, { scale: 1.34 })
    //     .delay(list.length * 0.2 - idx * 0.2)
    //     .start();
    // });
  }
  stopRollPiece(node) {
    node.scale = 1;
    node.angle = 0;
    node.stopAllActions();
  }
  rollPieceOnce(node: cc.Node) {
    node.stopAllActions();
    cc.tween(node)
      .set({ scale: 1, angle: 0 })
      .to(0.1, { angle: -10 })
      .to(0.2, { angle: 10 })
      .to(0.1, { angle: 0 })
      .start();
  }

  getCurrentBlock() {
    const board = cc.find("Canvas/bg/chessBoard/boardItems");
    const startIdx = this._status[this._status.current];
    return board.children[startIdx]
  }
  getRightBlock() {
    const board = cc.find("Canvas/bg/chessBoard/boardItems");
    const startIdx = this._status[this._status.current];
    // console.log("startIdx = " + JSON.stringify(startIdx));
    for (let i = startIdx + 1; i < board.children.length; i++) {
      const targetNode = board.children[i];
      const itemData = targetNode.getComponent("BoardGame2_ItemData");

      if (itemData.letter.toLowerCase() == this._status.letter.toLowerCase()) {
        return targetNode;
        // if(itemData.jump!=""){
        //   const jtNode=board.children[parseInt(itemData.jump)];
        //   return jtNode;
        // }
        // else{
        //   return targetNode;          
        // }  
      }
    }
    return null;
  }

  jumpBlock(idx) {
    const board = cc.find("Canvas/bg/chessBoard/boardItems");
    const targetNode = board.children[idx];
    return targetNode;
  }

  getNextRightIdx() {
    const board = cc.find("Canvas/bg/chessBoard/boardItems");
    const startIdx = this._status[this._status.current];
    for (let i = startIdx + 1; i < board.children.length; i++) {
      const targetNode = board.children[i];
      const itemData = targetNode.getComponent("BoardGame2_ItemData");
      if (itemData.letter.toLowerCase() == this._status.letter.toLowerCase()) {
        return i;
      }
    }
    return -1;
  }

  checkNodeInRightBlock(node, color) {
    const board = cc.find("Canvas/bg/chessBoard/boardItems");
    const startIdx = this._status[color];

    for (let i = startIdx + 1; i < board.children.length; i++) {
      const targetNode = board.children[i];
      const itemData = targetNode.getComponent("BoardGame2_ItemData");

      if (itemData.letter.toLowerCase() == this._status.letter.toLowerCase()) {
        if (targetNode.getBoundingBox().intersects(node.getBoundingBox())) {
          return true;
        }
        return false;
      }
    }
    return false;
  }

  showStars(node) {
    cc.tween(node)
      .delay(0.07)
      .call(() => {
        const light = cc.instantiate(cc.find("nodes/light"));
        light.parent = node.parent;
        cc.tween(light)
          .set({
            x: node.x + RandomInt(200) - 100,
            y: node.y + 50,
            scale: 0,
          })
          .by(
            1,
            {
              y: 200 + RandomInt(200) - 100,
              scale: 0.7 + 0.3 * Math.random(),
            },
            { easing: "cubicOut" }
          )
          .removeSelf()
          .start();
      })
      .union()
      .repeatForever()
      .start();
  }

  async pieceFindRightBlock(rightBlock, idx) {
    const color = this._status.current;
    const piece = cc.find(`Canvas/bg/chessBoard/piece${color}`);

    // console.log(idx + "_进度条高：" + targetHeight);
    const offsetX = { Red: -45, Blue: 45 };
    const offsetY = { Red: -90, Blue: -90 };

    this._status[color] = idx;

    piece.zIndex = 1;
    this.showStars(piece);

    piece['rightTween'] = true;
    this.playLocalAudio("落子");
    await asyncTweenTo(piece, 1, {
      x: rightBlock.x + offsetX[color],
      y: rightBlock.y + offsetY[color],
    });
    piece['rightTween'] = false;

    for (let i = 0; i < 20; i++) {
      const star = cc.instantiate(cc.find("nodes/star"));
      star.parent = piece.parent;
      cc.tween(star)
        .set({
          x: piece.x,
          y: piece.y + 50,
          scale: 0,
        })
        .to(
          0.5,
          {
            x: piece.x + RandomInt(400) - 200,
            y: piece.y + 50 + RandomInt(400) - 200,
            scale: 0.3 + 0.2 * Math.random(),
            angle: RandomInt(720),
          },
          { easing: "cubicOut" }
        )
        .removeSelf()
        .start();
    }

    piece.stopAllActions();
    piece.zIndex = 0;
  }

  updateProgress(idx) {
    const color = this._status.current;
    return new Promise(async (resolve, reject) => {
      const board = cc.find("Canvas/bg/chessBoard/boardItems");
      const prograssbar = cc.find(
        `Canvas/bg/Life${color.toLowerCase()}/life_${color.toLowerCase()}/mask/prograssbar`
      );
      const mask = cc.find(
        `Canvas/bg/Life${color.toLowerCase()}/life_${color.toLowerCase()}/mask`
      );
      let targetHeight =
        (idx / (board.children.length - 2)) * prograssbar.height;
      const effectNode = cc.find(`Canvas/bg/Life${color.toLowerCase()}/effect`);
      effectNode.active = true;
      asyncTweenTo(mask, 1, { height: targetHeight }, { easing: "cubicInOut" });
      this.playLocalAudio("进度条升高");
      await asyncPlayDragonBoneAnimation(effectNode, "normal", 1);
      effectNode.active = false;
      resolve('');
    });
  }

  updateStatus(status = null) {
    if (status) {
      console.log(status);
      this._status = JSON.parse(JSON.stringify(status));
    } else {
      // console.log("喵喵喵");
    }
    const playerMe = this.allPlayerList.find(
      (player) => player.uuid == this.playerId
    );
    if (playerMe.color == this._status.current) {
      this.stopGreyDice();
      if (this._status.letter == "") {
        this.showYourTurn();
        this.blinkTheDice();
      } else {
        this.stopBlinkTheDice();

        this.rollPiece(this.getCurrentPiece());
      }
    } else {
      this.greyDice();
    }

    // const blueFrame = cc.find("Canvas/bg/Lifeblue/faceFrame");
    // const redFrame = cc.find("Canvas/bg/Lifered/faceFrame");
    // let blinkFrame: cc.Node, stopBlinkFrame: cc.Node;
    // if (this._status.current == "Red") {
    //   blinkFrame = redFrame;
    //   stopBlinkFrame = blueFrame;
    // } else {
    //   blinkFrame = blueFrame;
    //   stopBlinkFrame = redFrame;
    // }
    // blinkFrame.stopAllActions();
    // cc.tween(blinkFrame)
    //   .set({ opacity: 100 })
    //   .to(1.5, { opacity: 255 }, { easing: "cubicOut" })
    //   .to(1.5, { opacity: 100 }, { easing: "cubicIn" })
    //   .union()
    //   .repeatForever()
    //   .start();
    // stopBlinkFrame.stopAllActions();
    // stopBlinkFrame.opacity = 0;

    const blueMask = cc.find("Canvas/bg/Lifeblue/faceMask");
    const redMask = cc.find("Canvas/bg/Lifered/faceMask");
    let blinkMask: cc.Node, stopBlinkMask: cc.Node;
    if (this._status.current == "Red") {
      blinkMask = blueMask;
      stopBlinkMask = redMask;
    } else {
      blinkMask = redMask;
      stopBlinkMask = blueMask;
    }
    blinkMask.active = true;
    stopBlinkMask.active = false;
  }

  getCurrentPiece() {
    if (this._status.current == "Red") {
      return cc.find("Canvas/bg/chessBoard/pieceRed");
    } else {
      return cc.find("Canvas/bg/chessBoard/pieceBlue");
    }
  }

  changeSide() {
    if (this._status.current == "Red") {
      this._status.current = "Blue";
      // console.log("changeSide Blue");
    } else {
      this._status.current = "Red";
      // console.log("changeSide Red");
    }
  }

  showYourTurn() {
    return new Promise((resolve, reject) => {
      const yourTurn = cc.find("Canvas/bg/yourturn");
      yourTurn.active = true;
      cc.tween(yourTurn)
        .set({ opacity: 0, scale: 5 })
        .to(1, { opacity: 255, scale: 2 })
        .delay(0.5)
        .to(0.5, { opacity: 0 })
        .call(() => {
          resolve(null);
        })
        .start();
    });
  }

  async pieceGoBack(node) {
    const touchStartPos = node["touchStartPos"];
    if (!touchStartPos) {
      return;
    }

    this.playLocalAudio("落子");
    await asyncTweenTo(
      node,
      0.7,
      { x: touchStartPos.nodeX, y: touchStartPos.nodeY },
      { easing: "cubicOut" }
    );
    node.stopAllActions();
  }

  getLetterList() {
    const board = cc.find("Canvas/bg/chessBoard/boardItems");
    const startIdx = this._status[this._status.current];
    const letterList = [];
    for (let i = startIdx + 1; i < board.children.length - 1; i++) {
      const targetNode = board.children[i];
      const itemData = targetNode.getComponent("BoardGame2_ItemData");
      const nodeLetter = itemData.letter.toUpperCase();
      if (!letterList.find((letter) => letter == nodeLetter)) {
        letterList.push(nodeLetter);
      }
    }
    return letterList;
  }

  allPlayerList;
  initNetworkListener() {
    this.networkHelper.on("playerJoin", (event) => {
      if (this.server) {
        this.server.onPlayerJoin({ data: { joinPlayerId: event.playerId } });
      }
      cc.log("playerJoin" + JSON.stringify(event));
    });
    this.networkHelper.on("playerLeave", (event) => {
      cc.log("playerLeave" + JSON.stringify(event));
      cc.find("Canvas/bg/PlayerOffLineLayer_tree").active = true;
      this.networkHelper.leaveRoom();
    });
    this.networkHelper.on("playerOffLine", (event) => {
      cc.find("Canvas/bg/PlayerOffLineLayer_tree").active = true;
      this.networkHelper.leaveRoom();
      this.log("playerOffLine" + JSON.stringify(event));
    });
    this.networkHelper.on("gameStart", (event) => { });
    this.networkHelper.on("frameEvent", (event) => {
      event.data.frame.items.forEach(async (item) => {
        if (this.server) {
          this.server.onFrameEvent(item.data);
        }

        if (item.data.type == "SERVER_allPlayerInfo") {
          console.log(
            "SERVER_allPlayerInfo: " + JSON.stringify(item.data.playerData)
          );
          item.data.playerData.forEach((player) => {
            if (!this.allPlayerList) {
              this.allPlayerList = [];
            }

            if (
              !this.allPlayerList.find(
                (listPlayer) => listPlayer.uuid == player.uuid
              )
            ) {
              this.allPlayerList.push({
                uuid: player.uuid,
                name: player.name,
                color: player.color,
                headUrl: player.headUrl,
              });
            }

            this.loadPlayerHeadImage();

            this.loadingLayer.addPlayer(
              player.name,
              player.uuid == this.playerId,
              player.headUrl,
              player.uuid
            );
          });
        } else if (item.data.type == "SERVER_updateStatus") {
          //TODO:调试加速2 默认 3
          await asyncDelay(3);
          console.log(
            "SERVER_updateStatus: " + JSON.stringify(item.data.status)
          );
          this.updateStatus(item.data.status);
        } else if (item.data.type == "SERVER_playerRoll") {
          // console.log("SERVER_playerRoll: " + JSON.stringify(item.data));
          const status = JSON.parse(JSON.stringify(this._status));
          status.letter = item.data.letter;
          console.log("status.letter = " + status.letter);
          // console.log("item.data.letter = " + item.data.letter);
          //根据当前startIdx和下一步的letter位置找 idx
          let letterList = this.getLetterList();
          let idx = letterList.findIndex(letter => letter == status.letter);
          if (idx == -1) {
            console.log("error")
          }
          const startIdx = status[status.current];
          let nextIdx = startIdx + idx + 1;
          // const idx = ["G", "H", "I", "J", "K", "L"].findIndex(
          //   (letter) => letter == status.letter
          // );

          const pieceRed = cc.find("Canvas/bg/chessBoard/pieceRed");
          const pieceBlue = cc.find("Canvas/bg/chessBoard/pieceBlue");
          pieceRed["cantMove"] = true;
          pieceBlue["cantMove"] = true;
          this.stopBlinkTheDice();
          // console.log("status1 = " + JSON.stringify(status));
          await this.rollTheDice(idx);
          pieceRed["cantMove"] = false;
          pieceBlue["cantMove"] = false;
          // console.log("status2 = " + JSON.stringify(status));
          // console.log("this._status = " + JSON.stringify(this._status));
          this.updateStatus(status);
          // console.log("status = " + JSON.stringify(status));
          // console.log("this._status = " + JSON.stringify(this._status));

          // const idx = this.getNextRightIdx();
          const playerMe = this.allPlayerList.find((player) => player.uuid == this.playerId);
          // console.log("idx->" + idx);
          if (status.current == playerMe.color) {
            let rightBlock = this.getRightBlock();
            let idx = this.getNextRightIdx();
            const pieceRed = cc.find("Canvas/bg/chessBoard/pieceRed");
            const pieceBlue = cc.find("Canvas/bg/chessBoard/pieceBlue");
            const node = cc.find(
              `Canvas/bg/chessBoard/piece${status.current}`
            );
            node["touchStartPos"] = {
              nodeX: node.x,
              nodeY: node.y,
              touchX: node.x,
              touchY: node.y,
            };
            let lastIdx = status[playerMe.color];
            pieceRed["cantMove"] = false;
            pieceBlue["cantMove"] = false;
            await this.pieceFindRightBlock(rightBlock, idx);
            let isSuccess = await this.showVoice(rightBlock);
            this.hideVoice();
            if (isSuccess) {
              this.updateProgress(idx);
              this.networkHelper.sendFrame({
                type: "right",
                idx: nextIdx,
                uuid: playerMe.uuid,
                color: playerMe.color,
              });
            } else {
              this._status[playerMe.color] = lastIdx
              this.networkHelper.sendFrame({
                type: "wrong",
                uuid: playerMe.uuid,
                color: playerMe.color,
              });
            }
          }
        } else if (item.data.type == "SERVER_playerRight") {
          console.log("SERVER_playerRight: " + JSON.stringify(item.data));
          const playerMe = this.allPlayerList.find((player) => player.uuid == this.playerId);
          if (this._status.current == playerMe.color) {
            // let rightBlock = this.getRightBlock();
            let rightBlock = this.getCurrentBlock();
            let idx = this.getNextRightIdx();
            const pieceRed = cc.find("Canvas/bg/chessBoard/pieceRed");
            const pieceBlue = cc.find("Canvas/bg/chessBoard/pieceBlue");
            const riData = rightBlock.getComponent("BoardGame2_ItemData");
            if (riData.jump != "") {
              rightBlock = this.jumpBlock(parseInt(riData.jump));
              let idx = parseInt(riData.jump);//this.getNextRightIdx();
              await this.pieceFindRightBlock(rightBlock, idx);
            }

            pieceRed["cantMove"] = true;
            pieceBlue["cantMove"] = true;
            this._status.letter = "";
            this.changeSide();
            this.updateStatus();
            return;
          }
          // console.log("SERVER_playerRight: " + JSON.stringify(item.data));
          // console.log("this._status = " + JSON.stringify(this._status));
          let rightBlock = this.getRightBlock();
          // console.log(rightBlock);
          let idx = this.getNextRightIdx();
          // console.log("targetIdx->" + idx);
          const pieceRed = cc.find("Canvas/bg/chessBoard/pieceRed");
          const pieceBlue = cc.find("Canvas/bg/chessBoard/pieceBlue");
          pieceRed["cantMove"] = false;
          pieceBlue["cantMove"] = false;
          await this.pieceFindRightBlock(rightBlock, idx);

          const riData = rightBlock.getComponent("BoardGame2_ItemData");
          if (riData.jump != "") {
            rightBlock = this.jumpBlock(parseInt(riData.jump));
            idx = parseInt(riData.jump);//this.getNextRightIdx();
            await this.pieceFindRightBlock(rightBlock, idx);
          }

          await this.playLocalAudio("正确");
          this.updateProgress(idx);
          pieceRed["cantMove"] = true;
          pieceBlue["cantMove"] = true;
          this._status.letter = "";
          this.changeSide();
          this.updateStatus();
        } else if (item.data.type == "SERVER_playerWrong") {
          console.log("SERVER_playerWrong: " + JSON.stringify(item.data));
          const node = cc.find(
            `Canvas/bg/chessBoard/piece${this._status.current}`
          );

          const playerMe = this.allPlayerList.find(
            (player) => player.uuid == this.playerId
          );
          if (playerMe.color == this._status.current) {
            await this.pieceGoBack(node);
          } else {
            this.rollPieceOnce(node);
          }

          node["cantMove"] = false;
          this._status.letter = "";
          this.changeSide();
          this.updateStatus();
        } else if (item.data.type == "SERVER_playerWin") {
          console.log("SERVER_playerWin: " + JSON.stringify(item.data));
          const node = cc.find(
            `Canvas/bg/chessBoard/piece${this._status.current}`
          );
          const playerMe = this.allPlayerList.find(
            (player) => player.uuid == this.playerId
          );
          const board = cc.find("Canvas/bg/chessBoard/boardItems");
          const idx = board.children.length;
          const rightBlock = board.children[idx - 1];

          await this.pieceFindRightBlock(rightBlock, idx);
          if (playerMe.color == this._status.current) {
            this.showWin();
            onHomeworkFinish({ isWin: true });
          } else {
            this.showLoss();
            onHomeworkFinish({ isWin: false });
          }
        }
      });
    });
  }

  showVoice(node: cc.Node) {
    return new Promise((resolve, reject) => {
      let voice = cc.find("Canvas/bg/voice");
      voice.active = true;

      let gray = voice.getChildByName("gray");
      let catBase = voice.getChildByName("catBase");
      let img = voice.getChildByName("img");
      let progress = voice.getChildByName("progress");
      let imgLight = voice.getChildByName("bg_light");
      let imgGood = voice.getChildByName("good");
      let imgTry = voice.getChildByName("try");

      progress.active = true;
      img.active = true;
      imgLight.active = false;
      imgGood.active = false;
      imgTry.active = false;
      catBase.active = true;

      //img需要clone对应的节点塞进去。
      img.removeAllChildren();
      let cloneNode = cc.instantiate(node);
      cloneNode.x = 0;
      cloneNode.y = 0;
      img.addChild(cloneNode);

      let progressBar = progress.getComponent(cc.ProgressBar)
      progressBar.progress = 1;
      let url = this.recordWaitCount == 0 ? this.data.recordWait : "";
      this.playAudioByUrl(url, () => {
        let cat = cc.find("cat", catBase);
        asyncPlayDragonBoneAnimation(cat, "record", 0);
        cc.tween(progressBar).delay(1).to(3, { progress: 0 }).call(() => {
        }).start();

        console.log('startTest->' + this._status.letter);
        courseware && courseware.startTest(this._status.letter); //开始录音
        setTimeout(async () => {
          if (!courseware) {
            let testData = {
              "dtLastResponse": "2021-09-17 13:36:26:109",
              "refText": "I haven't found anything out about him yet.",
              "recordId": "6144295213f0a2200000ed93",
              "eof": 1,
              "result": {
                "pronunciation": 25,
                "resource_version": "3.1.0",
                "fluency": 60,
                "rhythm": 90,
                "kernel_version": "5.2.4",
                "overall": 80,//25
                "integrity": 100,
                "duration": "6.779",
                "rear_tone": "fall",
                "speed": 96,
                "words": [
                  {
                    "phonemes": [
                      {
                        "phoneme": "w",
                        "pronunciation": 55,
                        "span": {
                          "end": 95,
                          "start": 88
                        }
                      },
                      {
                        "phoneme": "ɛ",
                        "pronunciation": 100,
                        "span": {
                          "end": 107,
                          "start": 95
                        }
                      },
                      {
                        "phoneme": "r",
                        "pronunciation": 99,
                        "span": {
                          "end": 123,
                          "start": 107
                        }
                      }
                    ],
                    "phonics": [
                      {
                        "overall": 85,
                        "phoneme": [
                          "w",
                          "ɛ",
                          "r"
                        ],
                        "spell": "Where"
                      }
                    ],
                    "scores": {
                      "overall": 80,
                      "pronunciation": 92
                    },
                    "span": {
                      "end": 123,
                      "start": 88
                    },
                    "word": "Where"
                  }, {
                    "phonemes": [
                      {
                        "phoneme": "w",
                        "pronunciation": 55,
                        "span": {
                          "end": 95,
                          "start": 88
                        }
                      },
                      {
                        "phoneme": "ɛ",
                        "pronunciation": 100,
                        "span": {
                          "end": 107,
                          "start": 95
                        }
                      },
                      {
                        "phoneme": "r",
                        "pronunciation": 99,
                        "span": {
                          "end": 123,
                          "start": 107
                        }
                      }
                    ],
                    "phonics": [
                      {
                        "overall": 85,
                        "phoneme": [
                          "w",
                          "ɛ",
                          "r"
                        ],
                        "spell": "Where"
                      }
                    ],
                    "scores": {
                      "overall": 10,
                      "pronunciation": 92
                    },
                    "span": {
                      "end": 123,
                      "start": 88
                    },
                    "word": "Where"
                  }
                ]
              },
              "tokenId": "6144295408558b08dd000001",
              "applicationId": "154838659000009e"
            }
            this.recordWaitCount++;
            if (this.recrodEnd(testData)) {
              this.playLocalAudio("正确");
              await this.showVoiceGood();
              return resolve(true)
            } else {
              this.playLocalAudio("错误弹回");
              await this.showVoiceTry();
              return resolve(false);
            }
          }
          // await pg.time.delay(5);
          courseware && courseware.stopTest(async (data) => {
            this.recordWaitCount++;
            data = JSON.parse(data);
            if (this.recrodEnd(data)) {
              this.playLocalAudio("正确");
              await this.showVoiceGood();
              return resolve(true)
            } else {
              this.playLocalAudio("错误弹回");
              await this.showVoiceTry();
              return resolve(false);
            }
          }); //结束录音
        }, 4000);
      })
    });
  }
  showVoiceGood() {
    return new Promise((resolve, reject) => {
      let voice = cc.find("Canvas/bg/voice");
      voice.active = true;
      let imgLight = voice.getChildByName("bg_light");
      let imgGood = voice.getChildByName("good");
      let imgTry = voice.getChildByName("try");
      imgLight.active = true;
      cc.Tween.stopAllByTarget(imgLight);
      cc.tween(imgLight)
        .by(3, { angle: 360 })
        .repeatForever()
        .start();
      imgGood.active = true;
      imgTry.active = false;
      setTimeout(() => {
        resolve('');
      }, 2000);
    });
  }
  showVoiceTry() {
    return new Promise((resolve, reject) => {
      let voice = cc.find("Canvas/bg/voice");
      voice.active = true;
      let imgLight = voice.getChildByName("bg_light");
      let imgGood = voice.getChildByName("good");
      let imgTry = voice.getChildByName("try");
      imgLight.active = true;
      cc.Tween.stopAllByTarget(imgLight);
      cc.tween(imgLight)
        .by(3, { angle: 360 })
        .repeatForever()
        .start();
      imgGood.active = false;
      imgTry.active = true;
      setTimeout(() => {
        resolve('');
      }, 2000);
    });
  }

  recrodEnd(data) {
    // return true;
    let score = data.result.overall;
    let isSuccess = this.checkWords(data);
    this.log("score->" + score);
    this.log("isSuccess->" + isSuccess);
    if (score >= 70 && isSuccess) {
      return true;
    } else {
      return false;
    }
  }

  private checkWords(data) {
    const sentences = data.result.sentences;
    if (!sentences) return true;
    for (let i = 0; i < sentences.length; i++) {
      const details = sentences[i].details;
      const isSuccess = details.some(item => item.overall <= 40);
      if (isSuccess) return false;
    }
    return true;
  }

  hideVoice() {
    let voice = cc.find("Canvas/bg/voice");
    voice.active = false;
  }



  showWin() {
    cc.find("Canvas/endBg").active = true;
    const bg = cc.find("Canvas/endBg/bg");
    cc.tween(bg).to(1, { opacity: 100 }).start();
    const loss = cc.find("Canvas/endBg/labelBg/labelLoss");
    loss.active = false;
    this.playLocalAudio("胜利");
  }
  showLoss() {
    cc.find("Canvas/endBg").active = true;
    const bg = cc.find("Canvas/endBg/bg");
    cc.tween(bg).to(1, { opacity: 100 }).start();
    const win = cc.find("Canvas/endBg/labelBg/labelWin");
    win.active = false;
    this.playLocalAudio("失败");
  }

  loadPlayerHeadImage() {
    const red = cc.find("Canvas/bg/Lifered/faceRed");
    const blue = cc.find("Canvas/bg/Lifeblue/faceBlue");
    this.allPlayerList.forEach((player) => {
      this.getSpriteFrimeByUrl(player.headUrl, (sf) => {
        if (player.color == "Red") {
          red.getComponent(cc.Sprite).spriteFrame = sf;
          red.width = 258;
          red.height = 258;
        } else {
          blue.getComponent(cc.Sprite).spriteFrame = sf;
          blue.width = 258;
          blue.height = 258;
        }
      });
    });
  }

  // async movePiece(letter, color) {
  //   const offsetX = { Red: -45, Blue: 45 };
  //   const offsetY = { Red: -90, Blue: -90 };
  //   const pieceNode = cc.find(`Canvas/bg/chessBoard/piece${color}`);
  //   const board = cc.find("Canvas/bg/chessBoard/boardItems");
  //   const startIdx = this._status[color];

  //   for (let i = startIdx + 1; i < board.children.length; i++) {
  //     const targetNode = board.children[i];
  //     const itemData = targetNode.getComponent("BoardGame2_ItemData");

  //     const prograssbar = cc.find(
  //       `Canvas/bg/Life${color.toLowerCase()}/life_${color.toLowerCase()}/mask/prograssbar`
  //     );
  //     const mask = cc.find(
  //       `Canvas/bg/Life${color.toLowerCase()}/life_${color.toLowerCase()}/mask`
  //     );
  //     const targetHeight = (i / board.children.length) * prograssbar.height;
  //     this.playLocalAudio("movePiece 进度条升高");
  //     cc.tween(mask)
  //       .to(1, { height: targetHeight }, { easing: "cubicInOut" })
  //       .start();

  //     await asyncTweenTo(
  //       pieceNode,
  //       1,
  //       {
  //         x: targetNode.x + offsetX[color],
  //         y: targetNode.y + offsetY[color],
  //       },
  //       { easing: "cubicInOut" }
  //     );

  //     if (itemData.letter.toLowerCase() == letter.toLowerCase()) {
  //       this._status[color] = i;

  //       return;
  //     }
  //   }
  //   this.finish();
  // }

  finish() {
    // onHomeworkFinish();
  }

  rollTheDice(num) {
    const dice = cc.find("Canvas/bg/chessBoard/diceBg/dice");
    if (dice["cantRoll"]) {
      return;
    }
    return new Promise((resolve, reject) => {
      const targetAngle = Math.ceil(dice.angle / 360 + 1) * 360;
      const time = (targetAngle - 360 - dice.angle) / 360;

      dice["cantRoll"] = true;

      cc.tween(dice)
        .by(3, { angle: 360 }, { easing: "cubicIn" })
        .to(time, { angle: targetAngle })
        .by(1, { angle: 360 })
        .by(1, { angle: 360 })
        .by(1, { angle: 360 })
        .by(1, { angle: 360 })
        .by((1 / 6) * num, { angle: 60 * num })
        .by(3, { angle: 360 }, { easing: "cubicOut" })
        .call(() => {
          dice["cantRoll"] = false;
          resolve(null);
        })
        .start();
      //TODO:调试加速
      // cc.tween(dice)
      //   .by(0.3, { angle: 360 }, { easing: "cubicIn" })
      //   .to(time, { angle: targetAngle })
      //   .by(0.1, { angle: 360 })
      //   .by(0.1, { angle: 360 })
      //   .by(0.1, { angle: 360 })
      //   .by(0.1, { angle: 360 })
      //   .by((1 / 6) * num, { angle: 60 * num })
      //   .by(0.3, { angle: 360 }, { easing: "cubicOut" })
      //   .call(() => {
      //     dice["cantRoll"] = false;
      //     resolve(null);
      //   })
      //   .start();
    });
  }

  playLocalAudio(audioName) {
    const audio = cc
      .find(`audioClips/${audioName}`)
      .getComponent(cc.AudioSource);
    return new Promise((resolve, reject) => {
      const id = cc.audioEngine.playEffect(audio.clip, false);
      cc.audioEngine.setFinishCallback(id, () => {
        resolve(id);
      });
    });
  }

  // 生命周期
  onDestroy() {
    this.networkHelper.onDestroy();
  }
}
