<template>
  <div class="game">
    <Header @confirmExit="getExit" :showTool="false" closeClass="close2"></Header>
    <div class="menu" v-if="projectList.length" :class="projectList.length <= 12 ? 'menu1' : 'menu2'"
      :key="projectList.length">
      <swiper :slides-per-view="6" :modules="[Grid]" :grid="{
        fill: projectList.length <= 12 ? 'row' : 'column',
        rows: 2,
      }" :space-between="20" :slides-per-group="12">
        <swiper-slide v-for="(item, index) in projectList" :key="item.project_uid" @click="getJump(item)">
          <div class="li">
            <div>
              <div class="pic"><img :src="'static/images/game/' + item.exam_name + '.png'" /></div>
              <div class="name">
                {{ item.exam_name_cn }}
              </div>
            </div>
          </div>
        </swiper-slide>
      </swiper>
    </div>
    <Transition :enter-active-class="proxy?.animate.rankingWindow.enter"
      :leave-active-class="proxy?.animate.rankingWindow.leave">
      <div class="gameWindow" v-if="start">
        <!---人体姿态识别-->
        <div class="columns" v-if="currentGame == 'bodyposecontroller'">
          <template v-if="currentGameArea.length == 2">
            <div class="item left">
              <HumanBody ref="humanBodyLeftRef" type="left" :currentGameArea="currentGameArea[0]"
                :areaStateList="areaStateList"></HumanBody>
            </div>
            <div class="item right">
              <HumanBody ref="humanBodyRightRef" type="right" :currentGameArea="currentGameArea[1]"
                :areaStateList="areaStateList"></HumanBody>
            </div>
          </template>
          <template v-else>
            <HumanBody ref="humanBodyLeftRef" type="left" :currentGameArea="currentGameArea[0]"
              :areaStateList="areaStateList"></HumanBody>
          </template>
        </div>
        <!---篮球投篮-->
        <div class="columns" v-if="currentGame == 'game_basketball'">
          <div class="item left">
            <Basketball ref="basketballLeftRef" type="left" @confirmExit="getExitGame"
              :currentGameArea="currentGameArea[0]" :areaStateList="areaStateList"></Basketball>
          </div>
          <div class="item right">
            <Basketball ref="basketballRightRef" type="right" @confirmExit="getExitGame"
              :currentGameArea="currentGameArea[1]" :areaStateList="areaStateList"></Basketball>
          </div>
        </div>
        <!---足球带球-->
        <div class="columns" v-if="currentGame == 'game_football'">
          <div class="item left">
            <Football ref="footballLeftRef" type="left" @confirmExit="getExitGame" :currentGameArea="currentGameArea[0]"
              :areaStateList="areaStateList">
            </Football>
          </div>
          <div class="item right">
            <Football ref="footballRightRef" type="right" @confirmExit="getExitGame"
              :currentGameArea="currentGameArea[1]" :areaStateList="areaStateList">
            </Football>
          </div>
        </div>
        <!---切水果-->
        <div class="columns" v-if="currentGame == 'game_fruit'">
          <Fruit ref="fruitRef" @confirmExit="getExitGame" :currentGameArea="currentGameArea[0]"
            :areaStateList="areaStateList">
          </Fruit>
        </div>
      </div>
    </Transition>
    <div class="continueGame" v-if="resumeGame">举手继续游戏</div>
    <div class="resumeGame" v-if="resumeGame" @click="getResumeGame">继续游戏</div>
    <div class="close close1" v-if="start" @click="getExitGame"></div>
    <ActionConfirmWindow ref="actionConfirmRef" @confirmExit="getExitGame({ type: 1 })" @confirmStart="getStartGame"
      @setMusic="setMusic">
    </ActionConfirmWindow>
    <div class="time" v-if="timerNum > 0">
      <div>{{ timerNum }}</div>
    </div>
    <div class="close close2" @click="getExit"></div>
  </div>
</template>

<script setup name="GameIndex" lang="ts">
import useAppStore from '@/store/modules/app';
import { clearInterval, clearTimeout, setInterval, setTimeout } from 'worker-timers';
import { initSpeech, speckText, playMusic, controlMusic, speckCancel, chineseNumber } from '@/utils/speech';
import { Swiper, SwiperSlide } from 'swiper/vue';
import { Grid } from 'swiper/modules';
import 'swiper/css';
import 'swiper/css/grid';
import { useWebSocket } from '@/utils/bodyposeWs';

import HumanBody from "./components/humanBody.vue";
import Basketball from "./components/basketball.vue";
import Football from "./components/football.vue";
import Fruit from "./components/fruit.vue";
const router = useRouter();
const { proxy } = getCurrentInstance() as any;
const humanBodyLeftRef = ref();
const humanBodyRightRef = ref();
const basketballLeftRef = ref();
const basketballRightRef = ref();
const footballLeftRef = ref();
const footballRightRef = ref();
const fruitRef = ref();
const actionConfirmRef = ref();

const { bodyposeWs, startDevice, checkBodypose, openBodypose, terminateBodypose, suspendBodypose, resumeBodypose, getBodyposeState, closeWS } = useWebSocket();

const data = reactive<any>({
  projectList: [],//项目列表
  wsState: false,//WS状态
  bodyposeState: false,//姿态识别窗口状态
  deviceInfo: {},//设备信息
  currentGame: "",//当前游戏
  currentGameArea: [],//当前游戏区
  start: false,//是否开始游戏
  areaStateList: [],//各游戏就绪状态
  resumeGame: false,//游戏结束显示继续游戏
  timer: null,
  timerNum: null,
  music: { id: null, list: [] }
});
const { projectList, wsState, bodyposeState, deviceInfo, currentGame, currentGameArea, start, areaStateList, resumeGame, timer, timerNum, music } = toRefs(data);

/**
 * 监听数据变化
 */
watch(
  () => areaStateList.value,
  (newData, oldData) => {
    console.log("areaStateList.value", areaStateList.value)
    //如果当前都是结束了就再重新弹窗
    let state = newData.every((item: any) => {
      return item.gameover;
    })
    if (state) {
      speckCancel();
      // start.value = false;
      // actionConfirmRef.value.getOpen(currentGame.value, currentGameArea.value);
      resumeGame.value = true;
      speckText("举手继续游戏");
    }
  },
  { deep: true }
);

/**
 * 初始化
 */
const getInit = async () => {
  console.log("触发姿态识别")
  let deviceid = localStorage.getItem('deviceid') || '';
  if (!deviceid) {
    proxy?.$modal.msgError(`请重新登录绑定设备号后使用`);
    getExit();
    return false;
  }
  bodyposeState.value = true;
  if (wsState.value) {
    proxy?.$modal.msgWarning(`操作过快，请稍后重试`);
    setTimeout(() => {
      bodyposeState.value = false;
    }, 1000)
    return false;
  }
  bodyposeWs((e: any) => {
    if (e?.wksid) {
      wsState.value = true;
      //获取设备信息
      startDevice({ deviceid: deviceid });
      console.log("获取设备信息")
    }
    if (e?.type == 'fe_device_init_result') {
      //接收设备信息并发送请求
      if (e?.device_info) {
        deviceInfo.value = e.device_info;
        let list = deviceInfo.value.project_list.filter((item: any) => {
          return ['bodyposecontroller', 'game_basketball', 'game_football', 'game_fruit'].includes(item.exam_name)
        })
        projectList.value = list;
      } else {
        proxy?.$modal.msgError(`设备信息缺失，请重新登录绑定设备号后使用`);
      }
    }
    if (e?.cmd == 'check_bodyposecontroller_available') {
      let area = e.ctrl_name.replace('bodyposecontroller_', '');
      if (e?.code == 0) {
        getBodyposeState(area);
      }
    }
    if (e?.cmd == 'get_bodyposecontroller_state') {
      let area = e.ctrl_name.replace('bodyposecontroller_', '');
      //state说明: 0：关闭，3：空闲，36：工作中
      if ([3, 36].includes(e.state)) {
        terminateBodypose(area);
      } else {
        openBodypose(area);
      }
    }
    if (e?.type == 'bodyposecontroller_result') {
      //可信度低于0.1不要
      let arr = e.data.result.keypoints;
      let result = [];
      for (let i = 0; i < arr.length; i += 3) {
        result.push(arr[i + 2]);
      }
      // console.log("result", result)
      let ok = result.every((item) => {
        return item >= 0.1
      })
      if (!ok) {
        return false;
      }
      //传给预备窗口
      if (!start.value) {
        actionConfirmRef.value.getInit(e);
        return false;
      }
      if (!currentGame.value) {
        return false;
      }
      //举手继续游戏
      if (resumeGame.value) {
        let myArr = e.data.result.keypoints;
        let result = [];
        for (let i = 0; i < myArr.length; i += 3) {
          result.push(myArr.slice(i, i + 2));
        }
        let leftA = result[6][1];//右肩Y
        let rightA = result[5][1];//左肩Y
        let leftB = result[8][1];//右肘Y
        let rightB = result[7][1];//左肘Y
        let bizi = result[0][1];//鼻子Y
        if (leftB < leftA || rightB < rightA || leftB < bizi || rightB < bizi) {
          getResumeGame();
        }
      }
      let area = e.ctrl_name.replace('bodyposecontroller_', '');
      //传给游戏窗口
      if (currentGame.value == 'bodyposecontroller') {
        if (currentGameArea.value.length == 2) {
          if (area == currentGameArea.value[0]) {
            humanBodyLeftRef.value.getInit(e);
          }
          if (area == currentGameArea.value[1]) {
            humanBodyRightRef.value.getInit(e);
          }
        } else {
          if (area == currentGameArea.value[0]) {
            humanBodyLeftRef.value.getInit(e);
          }
        }
      }
      if (currentGame.value == 'game_basketball') {
        if (area == currentGameArea.value[0]) {
          basketballLeftRef.value.getInit(e);
        }
        if (area == currentGameArea.value[1]) {
          basketballRightRef.value.getInit(e);
        }
      }
      if (currentGame.value == 'game_football') {
        if (area == currentGameArea.value[0]) {
          footballLeftRef.value.getInit(e);
        }
        if (area == currentGameArea.value[1]) {
          footballRightRef.value.getInit(e);
        }
      }
      if (currentGame.value == 'game_fruit') {
        fruitRef.value.getInit(e);
      }
    }
    if (e?.cmd == 'terminate_bodyposecontroller') {
    }
    if (e?.type == 'disconnect') {
      getExit();
    }
  });
};

//打开窗口
const getJump = (data: any) => {
  console.log("222", data)
  if (data.exam_name == 'test') {
    router.push({ path: '/game/test' });
  } else {
    //相同项目切换音乐保留上一次记录
    if (music.value.id) {
      actionConfirmRef.value.setMusic(music.value.id);
    } else {
      music.value.id = data.music_id;
      actionConfirmRef.value.setMusic(music.value.id);
    }
    currentGame.value = data.exam_name;
    currentGameArea.value = data.area_test_id?.split(",") || [];
    actionConfirmRef.value.getOpen(currentGame.value, currentGameArea.value);
    currentGameArea.value.forEach((item: any) => {
      checkBodypose(item);
    })
  }
};

/**
 * 退出
 */
const getExit = () => {
  speckCancel();
  // router.go(-1);
  router.push({ path: '/home' });
};

/**
 * 退出游戏
 */
const getExitGame = (data: any) => {
  if (data.type == 1) {
    //浮窗退出
    console.log("currentGameArea.value", currentGameArea.value)
    currentGameArea.value.forEach((item: any) => {
      terminateBodypose(item);
    })
    currentGame.value = "";
    start.value = false;
    resumeGame.value = false;
    timerNum.value = 0;
    clearInterval(timer.value);
    timer.value = null;
    speckCancel();
  } else if (data.type == 2) {
    //游戏结束显示下一场
    let myIndex = areaStateList.value.findIndex((item: any) => {
      return item.area == data.area;
    })
    if (myIndex != undefined) {
      areaStateList.value[myIndex].gameover = true;
    }
  } else {
    //游戏中退出
    proxy?.$modal.confirm("确定退出吗？").then(() => {
      currentGameArea.value.forEach((item: any) => {
        terminateBodypose(item);
      })
      currentGame.value = "";
      start.value = false;
      resumeGame.value = false;
      timerNum.value = 0;
      clearInterval(timer.value);
      timer.value = null;
      speckCancel();
    }).finally(() => {
    });
  }
};

/**
 * 开始游戏
 */
const getStartGame = (data: any) => {
  areaStateList.value = data;
  start.value = true;
  resumeGame.value = false;
  getPlayMusic();
};

/**
 * 继续游戏
 */
const getResumeGame = () => {
  if (timer.value) {
    clearInterval(timer.value);
    timer.value = null;
  }
  resumeGame.value = false;
  timerNum.value = 5;
  speckText(timerNum.value);
  timer.value = setInterval(() => {
    timerNum.value--;
    speckText(timerNum.value);
    if (timerNum.value == 0) {
      areaStateList.value.forEach((item: any, index: number) => {
        areaStateList.value[index].gameover = false;
      })
      clearInterval(timer.value);
      timer.value = null;
      if (currentGame.value == 'game_basketball') {
        basketballLeftRef.value.getResumeGame();
        basketballRightRef.value.getResumeGame();
      }
      if (currentGame.value == 'game_football') {
        footballLeftRef.value.getResumeGame();
        footballRightRef.value.getResumeGame();
      }
      if (currentGame.value == 'game_fruit') {
        fruitRef.value.getResumeGame();
      }
      getPlayMusic();
    }
  }, 1000)
};


/**
 * 播放音乐
 */
const getPlayMusic = async () => {
  if (music.value.id) {
    let obj = music.value.list.find((item: any) => {
      return item.id == music.value.id;
    });
    if (obj != undefined) {
      playMusic(obj.url, true);
    }
  }
};

/**
 * 获取音乐
 */
const getMusic = async () => {
  const list: any = useAppStore().getMusic();
  if (list.length) {
    music.value.list = list;
  } else {
    await proxy?.$http.train.musicList().then((res: any) => {
      if (res.data.length > 0) {
        let myList: any = res.data;
        music.value.list = myList;
        useAppStore().setMusic(myList);
      }
    });
  }
};

/**
 * 弹窗设置的音乐返回上层
 */
const setMusic = async (data: any) => {
  //console.log("data",data)
  music.value.id = data;
};

onBeforeMount(async () => {
  //初始化语音
  initSpeech();
  //初始化WS
  getInit();
  //音乐
  getMusic();
});

onMounted(() => {
});

onBeforeUnmount(() => {
  speckCancel();
  closeWS();
});
</script>

<style lang="scss" scoped>
$topPadding: 5.19rem;
$waiPadding: 6.51rem;

.menu {
  width: calc(100% - ($waiPadding * 2));
  height: 72vh;
  padding-top: 10rem;
  margin: 0 auto;
  display: flex;

  .li {
    // width: calc((100% / 6) - 1rem + (1rem/6));
    // margin-right: 1rem;
    // margin-bottom: 1rem;
    width: 100%;
    height: calc((72vh / 2) - 20px);
    padding: 2.2vh 0;
    border-radius: 1.6rem;
    box-sizing: border-box;
    box-shadow: inset 0px 1px 0px 2px rgba(255, 255, 255, 0.9046), inset 0px 3px 6px 0px rgba(0, 0, 0, 0.0851);
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;

    .pic {
      width: 11.36vw;
      height: 11.36vw;
      border-radius: 50%;
      background: radial-gradient(78% 78% at 53% 50%, #07121a 0%, #2a4256 49%, #5180a9 100%);
      box-shadow: 0px 0px 2px 2px #ffffff;
      margin-bottom: 2.5vh;
      overflow: hidden;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;

      img {
        max-width: 88%;
        max-height: 88%;
        transition: all 1s;
      }
    }

    .name {
      width: 100%;
      font-size: 2.1rem;
      color: #1a293a;
      text-align: center;
    }

    &:hover {
      img {
        transform: translateY(-0.5vw);
      }
    }
  }

  .swiper-slide {
    border-radius: 1.6rem;
    overflow: hidden;
  }
}

.menu1 {
  align-items: center;

  .swiper-slide {
    margin-bottom: 20px;

    .li {
      background: radial-gradient(96% 96% at 2% 32%, #ffffff 0%, #fcfdfd 54%, #e1e4e7 100%);
    }

    &:nth-child(2),
    &:nth-child(4),
    &:nth-child(6),
    &:nth-child(7),
    &:nth-child(9),
    &:nth-child(11) {
      .li {
        background: radial-gradient(167% 126% at 97% 6%, #35ffc6 0%, #00ffe8 100%);
      }
    }
  }
}

.menu2 {
  display: flex;

  .swiper-slide {

    &:nth-child(1),
    &:nth-child(4),
    &:nth-child(5),
    &:nth-child(8),
    &:nth-child(9),
    &:nth-child(12),
    &:nth-child(13),
    &:nth-child(16),
    &:nth-child(17),
    &:nth-child(20),
    &:nth-child(21),
    &:nth-child(24),
    &:nth-child(25),
    &:nth-child(28),
    &:nth-child(29),
    &:nth-child(32),
    &:nth-child(33),
    &:nth-child(36),
    &:nth-child(37),
    &:nth-child(40),
    &:nth-child(41),
    &:nth-child(44) {
      .li {
        background: radial-gradient(96% 96% at 2% 32%, #ffffff 0%, #fcfdfd 54%, #e1e4e7 100%);
      }
    }

    &:nth-child(2),
    &:nth-child(3),
    &:nth-child(6),
    &:nth-child(7),
    &:nth-child(10),
    &:nth-child(11),
    &:nth-child(14),
    &:nth-child(15),
    &:nth-child(18),
    &:nth-child(19),
    &:nth-child(22),
    &:nth-child(23),
    &:nth-child(26),
    &:nth-child(27),
    &:nth-child(30),
    &:nth-child(31),
    &:nth-child(34),
    &:nth-child(35),
    &:nth-child(38),
    &:nth-child(39),
    &:nth-child(42),
    &:nth-child(43) {
      .li {
        background: radial-gradient(167% 126% at 97% 6%, #35ffc6 0%, #00ffe8 100%);
      }
    }
  }
}

.gameWindow {
  width: 100vw;
  height: 100vh;
  position: absolute;
  z-index: 990;
  left: 0;
  top: 0;
  display: flex;

  .columns {
    display: flex;
    flex-wrap: wrap;
    width: 100%;

    .item {
      flex: 1;
      display: flex;
      box-sizing: border-box;
      width: 50%;
    }

    .left {
      border-right: 10px solid #07121a;
    }

    .right {
      border-left: 10px solid #07121a;
    }
  }

}

.close1 {
  z-index: 991;
  position: fixed;
  bottom: 35px;
  left: 50%;
  margin-left: -1.6rem;
}

.resumeGame {
  width: 10rem;
  height: 3.2rem;
  line-height: 3.2rem;
  font-size: 1.8rem;
  color: #1a293a;
  text-align: center;
  z-index: 991;
  position: fixed;
  bottom: calc(35px + 3.2rem + 25px);
  left: 50%;
  margin-left: -5rem;
  cursor: pointer;
  border-radius: 8px;
  background: radial-gradient(159% 126% at 5% 93%, #8effa9 0%, #07ffe7 100%);
  box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.1874), inset 0px 1px 0px 1px rgba(255, 255, 255, 0.3);

  &:hover {
    background: #8effa9;
  }
}

.continueGame {
  z-index: 991;
  position: fixed;
  width: 100%;
  left: 0;
  text-align: center;
  font-size: 3.5em;
  top: 40%;
  color: #ffffff;
}

.time {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  color: #ffffff;
  font-size: 7rem;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 998;
}

::v-deep(.menu) {
  .swiper-horizontal {
    width: 100%;
  }
}

.close2 {
  position: absolute;
  // right: calc($waiPadding - 3.2rem);
  left: auto;
  right: calc($waiPadding - 3.2rem);
  top: auto;
  bottom: calc($topPadding / 2 - 3.2rem / 4);
}

@media screen and (max-width: 1450px) {
  .menu {
    .li {
      .name {
        font-size: 1.6rem;
      }

      .pic {
        width: 10vw;
        height: 10vw;
      }
    }
  }
}
</style>
