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

const { ccclass, property } = cc._decorator;
const RED = "red";
const BLUE = "blue";

// 所有消息列表
const MSG_TEST = "msg_test";
const MSG_SWITCHSIDE = "msg_switch_side";
const MSG_ROLLING = "msg_rolling";
const MSG_GO = "msg_go";
const MSG_TIMEOUT = "msg_timeout";
const MSG_FINISH = "msg_finish";
const MSG_PLAYER_TO_TREE = "msg_player_to_tree";
const MSG_PLAYER_TO_HOME = "msg_player_to_home";
const MSG_PROFIX_END = "__END__";
const DEBUG = false;
const TOTAL_SCORE = 42; // 总分 - 双方分数之和等于 TOTAL_SCORE
const AI_SUCCESS_RATE = 0.65; // ai评测成功率
const AUTO_GAME = false; // 自动游戏-调试使用

@ccclass
export default class SceneComponent extends MyCocosSceneComponent {
  @property(cc.Prefab)
  loadingLayerPrefab = null; // 等待其他小伙伴加入页面

  @property(cc.Prefab)
  playerOffLineLayerPrefab = null; // 其他人掉线页面

  @property(cc.Prefab)
  endLayerPrefab = null; // 结束页面

  server: GameServer;
  networkHelper: NetworkHelper;
  playerId; // 当前玩家ID
  isRoomOwner; // 是否为房主
  withAiPlayer=false; // 对手是否AI
  gameEnd = false;
  gameStaring = false;

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

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

    // 游戏加载
    this._audioResList.push({ url: this.data.gameLoadingAudio });
    // 游戏开始
    this._audioResList.push({ url: this.data.gameStartAudio });
    // 提示录音
    this._audioResList.push({ url: this.data.recordWait });
    this._audioResList.push({ url: this.data.waitingPiece });
    this._audioResList.push({ url: this.data.waitingTurn });
    this._audioResList.push({ url: this.data.waitingWheel });
  }

  addPreloadAnima() {}

  onLoadEnd() {
    // TODO 加载完成后的逻辑写在这里, 下面的代码仅供参考
    this.initData();
    this.initView();
    this.initListener();
    this.initEvents();

    // 测试停止游戏
    window.stopGame = () => {
      this.runEvent(MSG_TIMEOUT, {})
    }
  }

  // 初始化数据
  async initData() {
    this.networkHelper = new NetworkHelper();
    this.initNetworkListener();
    do {
      this.playerId = await this.networkHelper.init("l2_boardgame2_tree", 2);
      if (this.playerId === null) {
        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();
      // 设置AI玩家消息处理方法
      this.server.onAIEvents = this.onAiEvents.bind(this);
    }
    await this.initHeadImgAndName();
  }

  // 获取用户头像
  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,
    });
  }

  // 把卡片数据附加到节点上
  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;
    //     }
    //   }
    // });
  }

  initView() {
    // 初始化界面
    this.initLoadingLayer();
    this.initOfflineLayer();
    this.initPronunciationTestLayer();
    this.initCoolCat();
    this.initSeagull();
    this.initBox();
    this.initTurntable();
    this.initGemstone();
    this.initScore();
    this.initPlayerNode();
    this.initTreeNode();
  }

  // update (dt) {},

  initListener() {
    // 初始化时间监听
  }

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

  // 等待游戏开始加入
  loadingLayer;
  initLoadingLayer() {
    cc.log("[Function]initLoadingLayer");
    const loadingLayerBase = cc.find("Canvas/loadingLayerBase");
    const loadingLayerNode = cc.instantiate(this.loadingLayerPrefab);
    loadingLayerBase.addChild(loadingLayerNode);

    this.loadingLayer = loadingLayerNode.getComponent("LoadingLayer");
    this.loadingLayer.setMaxPlayerNumber(2);
    this.loadingLayer.onLoadFinished(() => {
      this.initSide();
      this.timerHandle = this.initTimer();
      this.initPlayerInfo();
      this.coolcatSpeak(this.data.gameStartAudio, "begin", ()=>{
        this.gameStaring = true;
      });
      // 自动游戏模式 - 调试使用
      if(AUTO_GAME) {
        this.turntable.stopBlink();
        const nextGem = this.getNextQuestionIndex();
        this.runEvent(MSG_ROLLING, {nextGem: nextGem});
      }
    });
    this.coolcatSpeak(this.data.gameLoadingAudio, "begin");
  }

  // 初始化掉线提示组件
  offlineLayer;
  initOfflineLayer() {
    cc.log("[Function]initOfflineLayer");
    const offlineLayerBase = cc.find("Canvas/offlineLayerBase");
    const offlineLayerNode = cc.instantiate(this.playerOffLineLayerPrefab);
    offlineLayerBase.addChild(offlineLayerNode);

    this.offlineLayer = offlineLayerNode.getComponent("PlayerOffLineLayer");
  }

  // 语音评测组件
  pronunciationTestLayer;
  initPronunciationTestLayer() {
    const loadingLayerBase = cc.find("Canvas/PronunciationTestLayer");
    this.pronunciationTestLayer = loadingLayerBase.getComponent("PronunciationTestLayer");
    this.pronunciationTestLayer.init("http://staging-teach.cdn.ireadabc.com/31952573236dd316a8ee1672d1614a1c.mp3", DEBUG?1:10)
  }

  redPlayerNode = null;
  bluePlayerNode = null;
  redPlayerHomeNode = null;
  bluePlayerHomeNode = null;
  redBagNode = null;
  blueBagNode = null;
  redPlayerDB = null;
  bluePlayerDB = null;
  redHeaderMask = null;
  blueHeaderMask = null;
  // 初始化玩家
  initPlayerNode() {
    this.redPlayerNode = cc.find("Canvas/playerLand/red/people");
    this.bluePlayerNode = cc.find("Canvas/playerLand/blue/people");
    this.redPlayerHomeNode = cc.find("Canvas/playerLand/red");
    this.bluePlayerHomeNode = cc.find("Canvas/playerLand/blue");
    this.redBagNode = cc.find("Canvas/playerLand/red/bag");
    this.blueBagNode = cc.find("Canvas/playerLand/blue/bag");
    this.redPlayerDB = cc.find("Canvas/playerLand/red/people/db");
    this.bluePlayerDB = cc.find("Canvas/playerLand/blue/people/db");
    this.redHeaderMask = cc.find("Canvas/playerLand/red/header/mask");
    this.blueHeaderMask = cc.find("Canvas/playerLand/blue/header/mask");
  }

  treeNode = null;
  // 初始化树木
  initTreeNode() {
    this.treeNode = cc.find("Canvas/center_map/tree/stand");
  }

  // 初始化酷猫
  coolCat = null;
  coolCatClick = null;
  coolCatAudioUrl = null;
  initCoolCat() {
    this.coolCat = cc.find("Canvas/coolcatLand/coolcat");
    this.coolCatClick = cc.find("Canvas/coolcatLand/click");
    this.coolCatAudioUrl = this.data.waitingWheel;
    this.coolCatClick.on(cc.Node.EventType.TOUCH_END, ()=>{
      if(this.gameStaring) {
        if(this.side == this.currentGameSide) {
          if(this.coolCatAudioUrl) {
            this.coolcatSpeak(this.coolCatAudioUrl, "right")
          }
        } else {
          this.coolcatSpeak(this.data.waitingTurn, "right")
        }
      }
    })
  }

  seagull = null;
  seagullMap = null;
  // 初始化海鸥
  initSeagull() {
    this.seagull = cc.find("Canvas/seagull");
    this.seagullMap = cc.find("Canvas/seagull/map");
  }

  // 海鸥带走
  seagullGo() {
    const pos = this.boxMap.convertToWorldSpaceAR(cc.v2(0, 0));
    const pos1 = worldPosToLocalPos(pos, this.seagull)
    return new Promise((resovle, reject)=>{
      cc.tween(this.seagull).to(2, {x: pos1.x, y: pos1.y, scale: 0.8}).call(()=>{
        this.boxMap.parent = this.seagullMap;
        asyncPlayDragonBoneAnimation(this.seagull, 'close', 0);
        cc.tween(this.seagull).to(2, {x: -2000, y: 2000, scale: 1}).call(()=>{
          resovle(true);
        }).start();
      }).start();
    }) 
  }

  boxMap = null;
  // 初始化宝箱
  initBox() {
    this.boxMap = cc.find("Canvas/center_map/boxGroup/map");
  }

  // 小人上树
  playerToTree(playerNode) {
    const wordPos = this.treeNode.convertToWorldSpaceAR(cc.v2(0, 0))
    // const pos2 = playerNode.convertToNodeSpaceAR(pos1)
    const pos = worldPosToLocalPos(wordPos, playerNode);
    let playerDB = null;
    if(playerNode.parent.name.indexOf('red') != -1) {
      playerDB = this.redPlayerDB;
    } else {
      playerDB = this.bluePlayerDB;
    }

    asyncPlayDragonBoneAnimation(playerDB, 'jump', -1);
    playerNode.scaleX = 1; // 右看
    return new Promise((resovle, reject) =>{
      cc.tween(playerNode).to(0.5, {x: pos.x, y: pos.y}).call(()=>{
        asyncPlayDragonBoneAnimation(playerDB, 'normal', -1);
        resovle(null);
      }).start();
    })
  } 

  // 小人到宝石
  playerToGem(playerNode, gemNode) {
    const wordPos = gemNode.convertToWorldSpaceAR(cc.v2(0, 0))
    const pos = worldPosToLocalPos(wordPos, playerNode);
    playerNode.scaleX = -1; // 左看

    let playerDB = null;
    if(playerNode.parent.name.indexOf('red') != -1) {
      playerDB = this.redPlayerDB;
    } else {
      playerDB = this.bluePlayerDB;
    }
    asyncPlayDragonBoneAnimation(playerDB, 'jump', -1);
    return new Promise((resovle, reject) =>{
      cc.tween(playerNode).to(0.5, {x: pos.x, y: pos.y}).call(()=>{
        gemNode.__node_text.active = false;
        asyncPlayDragonBoneAnimation(playerDB, 'squat', -1);
        resovle(null);
      }).start();
    })
  }

  // 小人回家
  playerToHome(playerNode, homeNode, gemNode) {
    playerNode.scaleX = 1; // 右看
    let playerDB = null;
    if(playerNode.parent.name.indexOf('red') != -1) {
      playerDB = this.redPlayerDB;
    } else {
      playerDB = this.bluePlayerDB;
    }
    
    asyncPlayDragonBoneAnimation(playerDB, 'jump', -1);
    return new Promise((resovle, reject) =>{
      cc.tween(playerNode).to(0.5, {x: 205, y: 23}).call(()=>{
        gemNode.__node_text.active = true;
        asyncPlayDragonBoneAnimation(playerDB, 'normal', -1);
        resovle(null);
      }).start();
    })
  }

  //小人带着宝石回家
  playerToHomeWithGem(playerNode, homeNode, gemIndex) {
    const gem = this.gemstonesAll[gemIndex];
    // const pos1 = localPosTolocalPos(playerNode, homeNode);
    const pos2 = gem.convertToWorldSpaceAR(cc.v2(0, 0));
    const pos3 = playerNode.convertToNodeSpaceAR(pos2);

    gem.x = pos3.x;
    gem.y = pos3.y;
    gem.parent = playerNode;
    gem.zIndex = -1;
    playerNode.scaleX = -1; // 左看

    let playerDB = null;
    if(playerNode.parent.name.indexOf('red') != -1) {
      playerDB = this.redPlayerDB;
    } else {
      playerDB = this.bluePlayerDB;
    }
    asyncPlayDragonBoneAnimation(playerDB, 'jump', -1);

    return new Promise((resovle, reject) =>{
      cc.tween(playerNode).to(0.5, {x: 205, y: 23}).call(()=>{
        asyncPlayDragonBoneAnimation(playerDB, 'normal', -1);
        resovle(null);
      }).start();
    })
  }

  // 将宝石移动进入宝箱
  moveGemToBag(gemNode, boxNode) {
    const wordPos = boxNode.convertToWorldSpaceAR(cc.v2(0, 0));
    const pos = worldPosToLocalPos(wordPos, gemNode);
    return new Promise((resovle, reject) =>{
      cc.tween(gemNode).to(0.5, {x: pos.x, y: pos.y, scale: 0}).call(()=>{
        if(this.currentGameSide == RED) {
          this.redPlayerNode.scaleX = 1; // 右看
        } else {
          this.bluePlayerNode.scaleX = 1; // 右看
        }
        gemNode.parent = boxNode;
        resovle(null);
      }).start();
    })
  }

  // 异步游戏核心事件控制
  allPlayerList;
  initNetworkListener() {
    this.networkHelper.on("playerJoin", (event) => {
      if (this.server) {
        this.server.onPlayerJoin({ data: { joinPlayerId: event.playerId } });
      }
      console.log("playerJoin");
    });
    this.networkHelper.on("playerLeave", (event) => {
      cc.log("playerLeave" + JSON.stringify(event));
      this.offlineLayer.show();
      this.networkHelper.leaveRoom();
    });
    this.networkHelper.on("playerOffLine", (event) => {
      cc.log("playerOffLine" + JSON.stringify(event));
      this.offlineLayer.show();
      this.networkHelper.leaveRoom();
    });
    this.networkHelper.on("gameStart", (event) => {
      console.log("游戏开始")
    });
    this.networkHelper.on("frameEvent", (event) => {
      // cc.log("Frame event");
      event.data.frame.items.forEach(async (item) => {
        if (this.server) {
          this.server.onFrameEvent(item.data);
        }

        if (item.data.type == "SERVER_allPlayerInfo") {
          cc.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 {
          // 遍历自定义消息
          for(let key in this.eventsMap) {
            // 找到对应的消息类型 并且发消息的人不是自己
            if(item.data.type == key && item.data.sender != this.playerId) {
              this.runServerEvent(key, item.data.param)
            }
          }
        }
      });
    });
  }

  timerCount = 300;
  timeLabel = null;
  timerHandle = null;
  // 初始化倒计时
  initTimer() {
    const timerHandle = () => {
      if(this.timerCount > 0) {
        this.timerCount --;
        this.timeLabel.string = this.timerCount + "";
      } else {
        // 时间到
        if(this.isRoomOwner) {
          // 房主发起时间到事件
          this.runEvent(MSG_TIMEOUT, {});
        }
        this.unschedule(timerHandle);
      }
    }
    this.timeLabel = cc.find("Canvas/timer/count").getComponent(cc.Label);
    this.schedule(timerHandle,1);
    return timerHandle;
  }

  // 停止计时器
  stopTimer() {
    if(this.timerHandle) {
      this.unschedule(this.timerHandle);
    }
  }

  scoreRed = 0;
  scoreBlue = 0;
  scoreRedComponent = null;
  scoreBlueComponent = null;
  scoreRedFinishComponent = null;
  scoreBlueFinishComponent = null;
  masterRedNode = null;
  masterBlueNode = null;

  redGems_5 = null;
  redGems_10 = null;
  redGems_15 = null;
  redGems_20 = null;
  redGems_25 = null;
  blueGems_5 = null;
  blueGems_10 = null;
  blueGems_15 = null;
  blueGems_20 = null;
  blueGems_25 = null;

  redFinishGems_5 = null;
  redFinishGems_10 = null;
  redFinishGems_15 = null;
  redFinishGems_20 = null;
  redFinishGems_25 = null;
  blueFinishGems_5 = null;
  blueFinishGems_10 = null;
  blueFinishGems_15 = null;
  blueFinishGems_20 = null;
  blueFinishGems_25 = null;
  // 初始化分数
  initScore() {
    this.scoreRedComponent = cc.find("Canvas/playerLand/red/bag/score").getComponent(cc.Label);
    this.scoreBlueComponent = cc.find("Canvas/playerLand/blue/bag/score").getComponent(cc.Label);
    this.scoreRedFinishComponent = cc.find("Canvas/finishLayer/red/bag/score").getComponent(cc.Label);
    this.scoreBlueFinishComponent = cc.find("Canvas/finishLayer/blue/bag/score").getComponent(cc.Label);
    this.masterRedNode = cc.find("Canvas/finishLayer/red/master");
    this.masterBlueNode = cc.find("Canvas/finishLayer/blue/master");

    this.redGems_5 = cc.find("Canvas/playerLand/red/gems/gem5");
    this.redGems_10 = cc.find("Canvas/playerLand/red/gems/gem10");
    this.redGems_15 = cc.find("Canvas/playerLand/red/gems/gem15");
    this.redGems_20 = cc.find("Canvas/playerLand/red/gems/gem20");
    this.redGems_25 = cc.find("Canvas/playerLand/red/gems/gem25");

    this.blueGems_5 = cc.find("Canvas/playerLand/blue/gems/gem5");
    this.blueGems_10 = cc.find("Canvas/playerLand/blue/gems/gem10");
    this.blueGems_15 = cc.find("Canvas/playerLand/blue/gems/gem15");
    this.blueGems_20 = cc.find("Canvas/playerLand/blue/gems/gem20");
    this.blueGems_25 = cc.find("Canvas/playerLand/blue/gems/gem25");

    this.redFinishGems_5 = cc.find("Canvas/finishLayer/red/gems/gem5");
    this.redFinishGems_10 = cc.find("Canvas/finishLayer/red/gems/gem10");
    this.redFinishGems_15 = cc.find("Canvas/finishLayer/red/gems/gem15");
    this.redFinishGems_20 = cc.find("Canvas/finishLayer/red/gems/gem20");
    this.redFinishGems_25 = cc.find("Canvas/finishLayer/red/gems/gem25");

    this.blueFinishGems_5 = cc.find("Canvas/finishLayer/blue/gems/gem5");
    this.blueFinishGems_10 = cc.find("Canvas/finishLayer/blue/gems/gem10");
    this.blueFinishGems_15 = cc.find("Canvas/finishLayer/blue/gems/gem15");
    this.blueFinishGems_20 = cc.find("Canvas/finishLayer/blue/gems/gem20");
    this.blueFinishGems_25 = cc.find("Canvas/finishLayer/blue/gems/gem25");

    this.redGems_5.active = false;
    this.redGems_10.active = false;
    this.redGems_15.active = false;
    this.redGems_20.active = false;
    this.redGems_25.active = false;
    this.blueGems_5.active = false;
    this.blueGems_10.active = false;
    this.blueGems_15.active = false;
    this.blueGems_20.active = false;
    this.blueGems_25.active = false;
    this.redFinishGems_5.active = false;
    this.redFinishGems_10.active = false;
    this.redFinishGems_15.active = false;
    this.redFinishGems_20.active = false;
    this.redFinishGems_25.active = false;
    this.blueFinishGems_5.active = false;
    this.blueFinishGems_10.active = false;
    this.blueFinishGems_15.active = false;
    this.blueFinishGems_20.active = false;
    this.blueFinishGems_25.active = false;

    this.scoreRed = 0;
    this.scoreBlue = 0;
    this.scoreRedComponent.string = this.scoreRed;
    this.scoreBlueComponent.string = this.scoreBlue;
    this.scoreRedFinishComponent.string = this.scoreRed;
    this.scoreBlueFinishComponent.string = this.scoreBlue;
  }

  // 加分
  addScore(side, score) {
    if(side == RED) {
      this.scoreRed+=score;
      this.scoreRedComponent.string = this.scoreRed;
      this.scoreRedFinishComponent.string = this.scoreRed;
    } else {
      this.scoreBlue+=score;
      this.scoreBlueComponent.string = this.scoreBlue;
      this.scoreBlueFinishComponent.string = this.scoreBlue;
    }

    if(this.scoreRed > this.scoreBlue) {
      this.masterRedNode.active = true;
      this.masterBlueNode.active = false;
    } else if(this.scoreRed < this.scoreBlue) {
      this.masterRedNode.active = false;
      this.masterBlueNode.active = true;
    } else {
      this.masterRedNode.active = false;
      this.masterBlueNode.active = false;
    }

    this.setRedScoreGem(this.scoreRed);
    this.setBlueScoreGem(this.scoreBlue);
  }

  // 根据分数显示头像框宝石数量 - 红
  setRedScoreGem(score) {
    if(score == 0) {
      this.redGems_5.active = false;
      this.redGems_10.active = false;
      this.redGems_15.active = false;
      this.redGems_20.active = false;
      this.redGems_25.active = false;
      
      this.redFinishGems_5.active = false;
      this.redFinishGems_10.active = false;
      this.redFinishGems_15.active = false;
      this.redFinishGems_20.active = false;
      this.redFinishGems_25.active = false;
    } else if(score <= 5) {
      this.redGems_5.active = true;
      this.redGems_10.active = false;
      this.redGems_15.active = false;
      this.redGems_20.active = false;
      this.redGems_25.active = false;
      
      this.redFinishGems_5.active = true;
      this.redFinishGems_10.active = false;
      this.redFinishGems_15.active = false;
      this.redFinishGems_20.active = false;
      this.redFinishGems_25.active = false;
    } else if(score <= 10) {
      this.redGems_5.active = true;
      this.redGems_10.active = true;
      this.redGems_15.active = false;
      this.redGems_20.active = false;
      this.redGems_25.active = false;
      
      this.redFinishGems_5.active = true;
      this.redFinishGems_10.active = true;
      this.redFinishGems_15.active = false;
      this.redFinishGems_20.active = false;
      this.redFinishGems_25.active = false;
    } else if(score <= 15) {
      this.redGems_5.active = true;
      this.redGems_10.active = true;
      this.redGems_15.active = true;
      this.redGems_20.active = false;
      this.redGems_25.active = false;
      
      this.redFinishGems_5.active = true;
      this.redFinishGems_10.active = true;
      this.redFinishGems_15.active = true;
      this.redFinishGems_20.active = false;
      this.redFinishGems_25.active = false;
    } else if(score <= 20) {
      this.redGems_5.active = true;
      this.redGems_10.active = true;
      this.redGems_15.active = true;
      this.redGems_20.active = true;
      this.redGems_25.active = false;
      
      this.redFinishGems_5.active = true;
      this.redFinishGems_10.active = true;
      this.redFinishGems_15.active = true;
      this.redFinishGems_20.active = true;
      this.redFinishGems_25.active = false;
    } else {
      this.redGems_5.active = true;
      this.redGems_10.active = true;
      this.redGems_15.active = true;
      this.redGems_20.active = true;
      this.redGems_25.active = true;
      
      this.redFinishGems_5.active = true;
      this.redFinishGems_10.active = true;
      this.redFinishGems_15.active = true;
      this.redFinishGems_20.active = true;
      this.redFinishGems_25.active = true;
    }
  }

  // 根据分数显示头像框宝石数量 - 蓝
  setBlueScoreGem(score) {
    if(score == 0) {
      this.blueGems_5.active = false;
      this.blueGems_10.active = false;
      this.blueGems_15.active = false;
      this.blueGems_20.active = false;
      this.blueGems_25.active = false;
      
      this.blueFinishGems_5.active = false;
      this.blueFinishGems_10.active = false;
      this.blueFinishGems_15.active = false;
      this.blueFinishGems_20.active = false;
      this.blueFinishGems_25.active = false;
    } else if(score <= 5) {
      this.blueGems_5.active = true;
      this.blueGems_10.active = false;
      this.blueGems_15.active = false;
      this.blueGems_20.active = false;
      this.blueGems_25.active = false;
      
      this.blueFinishGems_5.active = true;
      this.blueFinishGems_10.active = false;
      this.blueFinishGems_15.active = false;
      this.blueFinishGems_20.active = false;
      this.blueFinishGems_25.active = false;
    } else if(score <= 10) {
      this.blueGems_5.active = true;
      this.blueGems_10.active = true;
      this.blueGems_15.active = false;
      this.blueGems_20.active = false;
      this.blueGems_25.active = false;
      
      this.blueFinishGems_5.active = true;
      this.blueFinishGems_10.active = true;
      this.blueFinishGems_15.active = false;
      this.blueFinishGems_20.active = false;
      this.blueFinishGems_25.active = false;
    } else if(score <= 15) {
      this.blueGems_5.active = true;
      this.blueGems_10.active = true;
      this.blueGems_15.active = true;
      this.blueGems_20.active = false;
      this.blueGems_25.active = false;
      
      this.blueFinishGems_5.active = true;
      this.blueFinishGems_10.active = true;
      this.blueFinishGems_15.active = true;
      this.blueFinishGems_20.active = false;
      this.blueFinishGems_25.active = false;
    } else if(score <= 20) {
      this.blueGems_5.active = true;
      this.blueGems_10.active = true;
      this.blueGems_15.active = true;
      this.blueGems_20.active = true;
      this.blueGems_25.active = false;
      
      this.blueFinishGems_5.active = true;
      this.blueFinishGems_10.active = true;
      this.blueFinishGems_15.active = true;
      this.blueFinishGems_20.active = true;
      this.blueFinishGems_25.active = false;
    } else {
      this.blueGems_5.active = true;
      this.blueGems_10.active = true;
      this.blueGems_15.active = true;
      this.blueGems_20.active = true;
      this.blueGems_25.active = true;
      
      this.blueFinishGems_5.active = true;
      this.blueFinishGems_10.active = true;
      this.blueFinishGems_15.active = true;
      this.blueFinishGems_20.active = true;
      this.blueFinishGems_25.active = true;
    }
  }

  // 用户自定义事件
  eventsMap = {};
  registerEvent(name, callback, endCallback?) {
    if(this.eventsMap[name] != undefined) {
      cc.log("该事件已经注册过，将会覆盖原有注册")
    }
    this.eventsMap[name] = {
      fn: callback,
      pending: false,
      isRequireEnd: endCallback?true:false,
    }

    if(endCallback) {
      this.eventsMap[name + MSG_PROFIX_END] = {
        fn: endCallback,
        pending: false,
        isRequireEnd: false,
      }
    }
  }

  // 注册全局游戏事件，需要玩家之间同步执行的方法
  // 无论是自己方 还是对方，只需要调用即可，方法内处理消息发送和执行
  runEvent(eventName, param) {
    //  && eventName.indexOf(MSG_FINISH)==-1 && eventName.indexOf(MSG_TIMEOUT)==-1
    if(this.gameEnd && eventName != MSG_FINISH) {
      // 游戏结束，但会排除结束消息
      console.log(`收到${eventName} - 游戏已经结束`)
      return;
    }
    if(this.eventsMap[eventName] == undefined) {
      cc.log("该事件没有注册过");
      return;
    }
    this.eventsMap[eventName].fn(param, ()=>{
      this.eventsMap[eventName].pending = false;
      
    });
    this.eventsMap[eventName].pending = true;
    this.networkHelper.sendFrame({
      type: eventName,
      sender: this.playerId,
      param: param,
    });
  }

  // 执行服务器发来的消息广播 和runEvent不同的地方只是 这个方法不会再次转发消息
  runServerEvent(eventName, param) {
    if(this.gameEnd && eventName != MSG_FINISH) {
      // 游戏结束，但会排除结束消息
      console.log(`收到${eventName} - 游戏已经结束`)
      return;
    }
    if(this.eventsMap[eventName] == undefined) {
      cc.log("该事件没有注册过");
      return;
    }
    this.eventsMap[eventName].fn(param, (param)=>{
      this.eventsMap[eventName].pending = false;
      if(this.eventsMap[eventName].isRequireEnd) {
        this.networkHelper.sendFrame({
          type: eventName + MSG_PROFIX_END,
          sender: this.playerId,
          param: param
        });
      }
    });
    this.eventsMap[eventName].pending = true;
  }
  
  // 我方 或者 AI方 执行方法
  runFunctionMySide(runFunction) {
    if(this.side == this.currentGameSide) {
      runFunction && runFunction(false);
    } else if(this.side != this.currentGameSide && this.withAiPlayer) {
      runFunction && runFunction(true);
    }
  }

  // 初始化转盘
  turntable: null;
  initTurntable() {
    this.turntable = cc.find("Canvas/Turntable").getComponent("Turntable");
    this.turntable.initTurntable(DEBUG);
    cc.find("Canvas/Turntable").on("Rolling_Start", ()=>{
      // 游戏流程1: 玩家点击转盘
      if(!this.gameStaring) {
        return;
      }
      this.turntable.stopBlink();
      const nextGem = this.getNextQuestionIndex();
      this.runEvent(MSG_ROLLING, {nextGem: nextGem});
    })
  }

  // 初始化宝石
  gemstones = [[], [], []];
  gemstonesAll =[];
  initGemstone() {
    const gemstoneGroup = cc.find("Canvas/center_map/gemstone");
    gemstoneGroup.children.forEach((gem,index)=>{
      gem['__index'] = index;
      gem['__isDone'] = false;
      gem['__node_icon_text'] = cc.find("icon_text", gem);
      gem['__node_icon'] = cc.find("icon", gem);
      gem['__node_text'] = cc.find("text", gem);
      gem['__letter'] = gem.name.split("_")[0];
      gem['__score'] = Number(gem.name.split("_")[1]);

      if(gem['__score'] == 1) {
        gem['__arrIndex1'] = 0;
        this.gemstones[0].push(gem);
      } else if(gem['__score'] == 2) {
        gem['__arrIndex1'] = 1;
        this.gemstones[1].push(gem);
      } else if(gem['__score'] == 3) {
        gem['__arrIndex1'] = 2;
        this.gemstones[2].push(gem);
      }
      
      gem['__arrIndex2'] = index;
      gem['__node_icon_text'].active = false;
      this.gemstonesAll.push(gem);
    })
  }

  // 选边初始化
  side = RED; // 标记自己阵营颜色
  currentGameSide = RED; // 当前游戏轮次的颜色
  initSide() {
    if(this.isRoomOwner) {
      this.side = RED;
      // 初始化红色阵营 先手 开始闪烁
      this.turntable.blink();
      // 当前玩家上树
      this.runEvent(MSG_PLAYER_TO_TREE,{});
    } else {
      this.side = BLUE;
      // 蓝色阵营 后手 禁止点击
      this.turntable.disable()
    }

    if(this.currentGameSide == RED) {
      this.redHeaderMask.active = false;
      this.blueHeaderMask.active = true;
    } else {
      this.redHeaderMask.active = true;
      this.blueHeaderMask.active = false;
    }
  }

  // 注册自定义消息事件
  initEvents() {
    // 测试消息
    this.registerEvent(MSG_TEST, (param, next)=>{
      console.log("测试消息")
      next();
    })

    // 换边
    this.registerEvent(MSG_SWITCHSIDE, (param, next)=>{
      this.currentGameSide = param.side;
      this.coolCatAudioUrl = this.data.waitingWheel;
      this.handleSwitchSide();
      next();
    })

    // 玩家上树
    this.registerEvent(MSG_PLAYER_TO_TREE, (param, next)=>{
      if(this.currentGameSide == RED) {
        this.playerToTree(this.redPlayerNode)
      } else {
        this.playerToTree(this.bluePlayerNode)
      }
    })

    // 玩家回家
    this.registerEvent(MSG_PLAYER_TO_HOME, (param, next) => {
      if(param.success) {
        if(this.currentGameSide == RED) {
          this.playerToHomeWithGem(this.redPlayerNode, this.redPlayerHomeNode, param.gemIndex).then(()=>{
            this.moveGemToBag(this.gemstonesAll[param.gemIndex], this.redBagNode).then(()=>{
              this.addScore(RED, this.gemstonesAll[param.gemIndex].__score);
              this.setGemstoneDoneByIndex(param.gemIndex);
              next()
            })
          })
        } else {
          this.playerToHomeWithGem(this.bluePlayerNode, this.bluePlayerHomeNode, param.gemIndex).then(()=>{
            this.moveGemToBag(this.gemstonesAll[param.gemIndex], this.blueBagNode).then(()=>{
              this.addScore(BLUE, this.gemstonesAll[param.gemIndex].__score);
              this.setGemstoneDoneByIndex(param.gemIndex);
              next()
            })
          })
        }
      } else {
        if(this.currentGameSide == RED) {
          this.playerToHome(this.redPlayerNode, this.redPlayerHomeNode, this.gemstonesAll[param.gemIndex]).then(()=>{
            next()
          })
        } else {
          this.playerToHome(this.bluePlayerNode, this.bluePlayerHomeNode, this.gemstonesAll[param.gemIndex]).then(()=>{
            next()
          })
        }
      }
     
    }, ()=>{
      this.runFunctionMySide(()=>{
        if((this.scoreBlue + this.scoreRed) >= TOTAL_SCORE) {
          this.runEvent(MSG_FINISH, {});
        } else {
          if(this.currentGameSide == RED) {
            this.currentGameSide = BLUE;
          } else {
            this.currentGameSide = RED;
          }
          let side = this.currentGameSide;
          this.runEvent(MSG_SWITCHSIDE, {side});
        }
      })
    })

    // 转盘
    this.registerEvent(MSG_ROLLING, (param, next)=>{
      // console.log("转盘结果：", param.nextGem)
      cc.audioEngine.stopAll();
      this.coolCatAudioUrl = this.data.waitingPiece;
      this.turntable.stopBlink();
      this.turntable.rollNum(param.nextGem.score).then(()=>{
        // 异步操作执行完成后调用
        next(param);
      });
    }, (param)=>{
      // 游戏流程2: 走棋
      this.runEvent(MSG_GO, {index: param.nextGem.gemIndex});
    })

    // 走棋
    this.registerEvent(MSG_GO, (param, next)=>{
      if(this.currentGameSide == RED) {
        this.playerToGem(this.redPlayerNode, this.gemstonesAll[param.index]).then(()=>{
          next(param);
        });
      } else {
        this.playerToGem(this.bluePlayerNode, this.gemstonesAll[param.index]).then(()=>{
          next(param);
        });
      }
    }, (param)=>{
      // 游戏流程3: 测评 - 对手不会出现测评界面
      this.runFunctionMySide((isAi)=>{
        console.log("语音评测开始", isAi);
        if(isAi) {
          setTimeout(() => {
            console.log("语音评测结束")
            if(Math.random() > AI_SUCCESS_RATE) {
              console.log("评测失败，后退")
              // 后退
              this.runEvent(MSG_PLAYER_TO_HOME, {success: false, gemIndex: param.index});
            } else {
              console.log("评测成功")
              // 玩家回家
              this.runEvent(MSG_PLAYER_TO_HOME, {success: true,  gemIndex: param.index});
            }
          }, DEBUG?10:2000);
        } else {
          this.coolCat.active = false;
          let testNodeShow = cc.instantiate(this.gemstonesAll[param.index].__node_icon_text);
          testNodeShow.active = true;
          this.pronunciationTestLayer.showVoice(testNodeShow, this.gemstonesAll[param.index].__letter).then(res=>{
            this.coolCat.active = true;
            this.runEvent(MSG_PLAYER_TO_HOME, {success: res, gemIndex: param.index});
          })
        }
      })
    })

    // 时间到
    this.registerEvent(MSG_TIMEOUT, async (param, next) => {
      // console.log("时间到")
      this.turntable.disable();
      this.turntable.stopBlink();
      this.pronunciationTestLayer.stopTesting();
      this.stopTimer();
      this.gameEnd = true;
      await this.seagullGo();
      this.runEvent(MSG_FINISH, {})
    },)

    // 结束
    this.registerEvent(MSG_FINISH, (param, next) => {
      console.log("游戏结束")
      this.stopTimer();
      this.redPlayerHomeNode.active = false;
      this.bluePlayerHomeNode.active = false;
      cc.find("Canvas/finishLayer").active = true;
    })
  }

  async onAiEvents(event) {
    // 当有AI玩家的时候 需要处理这部分逻辑
    switch(event.type) {
      case MSG_ROLLING:
        this,this.scheduleOnce(()=>{
          this.eventsMap[MSG_ROLLING + MSG_PROFIX_END].fn(event.param);
        }, DEBUG?2:5.5)
        
        break;
      case MSG_GO:
        this,this.scheduleOnce(()=>{
          this.eventsMap[MSG_GO + MSG_PROFIX_END].fn(event.param);
        }, 1)
        
        break;
      case MSG_TIMEOUT:
        this,this.scheduleOnce(()=>{
          if(this.eventsMap[MSG_TIMEOUT + MSG_PROFIX_END] && this.eventsMap[MSG_TIMEOUT + MSG_PROFIX_END].fn) {
            this.eventsMap[MSG_TIMEOUT + MSG_PROFIX_END].fn(event.param);
          }
        }, 1)
        
        break;
      case MSG_PLAYER_TO_HOME:
        this,this.scheduleOnce(()=>{
          this.eventsMap[MSG_PLAYER_TO_HOME + MSG_PROFIX_END].fn(event.param);
        }, 1)
        
        break;
      case MSG_SWITCHSIDE:
        if(this.side != this.currentGameSide) {
          this.runEvent(MSG_PLAYER_TO_TREE,{});
          await asyncDelay(1)
          const nextGem = this.getNextQuestionIndex();
          this.runEvent(MSG_ROLLING, {nextGem: nextGem});
        }
        break;
    } 
  }

  // 获取下一道题的索引
  getNextQuestionIndex() {
    let nums = []

    // 根据当前宝石数量进行分组 - 每次从当前剩余宝石中随机出来 __isDone = true 表示当前宝石已经被拿走
    let gem1 = [];
    this.gemstones[0].forEach(gem=>{
      if(!gem.__isDone) {
        gem1.push(gem);
      }
    })
    if(gem1.length > 0) {
      nums.push(0)
    }

    let gem2 = [];
    this.gemstones[1].forEach(gem=>{
      if(!gem.__isDone) {
        gem2.push(gem);
      }
    })
    if(gem2.length > 0) {
      nums.push(1)
    }

    let gem3 = [];
    this.gemstones[2].forEach(gem=>{
      if(!gem.__isDone) {
        gem3.push(gem);
      }
    })
    if(gem3.length > 0) {
      nums.push(2)
    }

    // 随机出分值
    let num = nums[Math.floor((Math.random() * nums.length * 10) / 10)];
    // 从对应分值组中 找到一个宝石
    let gIndex =  -1;
    let index = -1;
    switch(num) {
      case 0: gIndex = Math.floor((Math.random() * gem1.length * 10) / 10); index = gem1[gIndex].__index; break;
      case 1: gIndex = Math.floor((Math.random() * gem2.length * 10) / 10); index = gem2[gIndex].__index; break;
      case 2: gIndex = Math.floor((Math.random() * gem3.length * 10) / 10); index = gem3[gIndex].__index; break;
      default: console.log(TOTAL_SCORE); gIndex = Math.floor((Math.random() * gem1.length * 10) / 10); index = gem1[gIndex].__index; break;
    }
    return {
      score: num,
      gemIndex: index
    };
  }

  // 将宝石设置为已经完成
  setGemstoneDoneByIndex(gemIndex) {
    const gem = this.gemstonesAll[gemIndex];
    const arrIndex1 = gem.__arrIndex1;
    const arrIndex2 = gem.__arrIndex2;
    gem.__isDone = true;
  }

  // 初始化用户信息 头像 名字
  initPlayerInfo() {
    const red = cc.find("Canvas/playerLand/red/header/image");
    const blue = cc.find("Canvas/playerLand/blue/header/image");
    const redFinish = cc.find("Canvas/finishLayer/red/header/image");
    const blueFinish = cc.find("Canvas/finishLayer/blue/header/image");
    const redName = cc.find("Canvas/playerLand/red/name/label").getComponent(cc.Label);
    const blueName = cc.find("Canvas/playerLand/blue/name/label").getComponent(cc.Label);
    const redNameFinish = cc.find("Canvas/finishLayer/red/name/label").getComponent(cc.Label);
    const blueNameFinish = cc.find("Canvas/finishLayer/blue/name/label").getComponent(cc.Label);
    this.allPlayerList.forEach((player) => {
      if(player.uuid.indexOf("ai_") != -1) {
        this.withAiPlayer = true;
      }
      this.getSpriteFrimeByUrl(player.headUrl, (sf) => {
        if (player.color == "Red") {
          red.getComponent(cc.Sprite).spriteFrame = sf;
          red.width = 140;
          red.height = 140;
          redName.string = player.name;
          redFinish.getComponent(cc.Sprite).spriteFrame = sf;
          redFinish.width = 140;
          redFinish.height = 140;
          redNameFinish.string = player.name;
        } else {
          blue.getComponent(cc.Sprite).spriteFrame = sf;
          blue.width = 140;
          blue.height = 140;
          blueName.string = player.name;
          blueFinish.getComponent(cc.Sprite).spriteFrame = sf;
          blueFinish.width = 140;
          blueFinish.height = 140;
          blueNameFinish.string = player.name;
        }
      });
    });
  }

  // 处理换边
  async handleSwitchSide() {
    if(this.side == this.currentGameSide) {
      this.turntable.enable();
      this.turntable.blink();
      // 当前玩家上树
      this.runEvent(MSG_PLAYER_TO_TREE,{});
      if(AUTO_GAME) {
        await asyncDelay(1);
        this.turntable.stopBlink();
        const nextGem = this.getNextQuestionIndex();
        this.runEvent(MSG_ROLLING, {nextGem: nextGem});
      }
    } else {
      this.turntable.disable();
      this.turntable.stopBlink();
    }

    if(this.currentGameSide == RED) {
      this.redHeaderMask.active = false;
      this.blueHeaderMask.active = true;
    } else {
      this.redHeaderMask.active = true;
      this.blueHeaderMask.active = false;
    }

    // 重置转盘
    this.turntable.reset();
  }

  // 酷猫说话
  audioID = null;
  coolcatSpeak(url, aniName = "normal", callback?) {
    if(url) {
      console.log(aniName)
      asyncPlayDragonBoneAnimation(this.coolCat, aniName, 0);
      if(this.audioID) {
        cc.audioEngine.stop(this.audioID);
      }
      this.playAudioByUrl(url, ()=>{
        this.audioID=null;
        if(callback) {
          callback();
        }
      }).then(id=>{
        this.audioID = id;
        asyncPlayDragonBoneAnimation(this.coolCat, "normal", 0);
      })
    }
  }
}
