<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import Container from "@/components/Container.vue";
import PlayerSeats from "@/components/PlayerSeats.vue";
import Guide from "@/components/Guide.vue";
import Timer from "@/components/Timer.vue";
import SButton from "@/components/SButton.vue";
import BowTarget from "@/components/BowTarget.vue";
import BattleHeader from "@/components/BattleHeader.vue";
import BattleFooter from "@/components/BattleFooter.vue";
import BowPower from "@/components/BowPower.vue";
import ShootProgress from "@/components/ShootProgress.vue";
import PlayersRow from "@/components/PlayersRow.vue";
import SModal from "@/components/SModal.vue";
import ScreenHint from "@/components/ScreenHint.vue";
import RoundEndTip from "@/components/RoundEndTip.vue";
import TestDistance from "@/components/TestDistance.vue";
import { getRoomAPI, destroyRoomAPI, exitRoomAPI, startRoomAPI } from "@/apis";
import { MESSAGETYPES, roundsName, getMessageTypeName } from "@/constants";
import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
const { user } = storeToRefs(store);
const step = ref(1);
const seq = ref(0);
const timerSeq = ref(0);
const battleId = ref("");
const room = ref({});
const roomNumber = ref("");
const owner = ref({});
const opponent = ref({});
const redTeam = ref([]);
const blueTeam = ref([]);
const currentShooterId = ref(0);
const players = ref([]);
const currentRound = ref(1);
const totalRounds = ref(0);
const start = ref(false);
const startCount = ref(false);
const power = ref(0);
const scores = ref([]);
const blueScores = ref([]);
const tips = ref("即将开始...");
const roundResults = ref([]);
const redPoints = ref(0);
const bluePoints = ref(0);
const currentRedPoint = ref(0);
const currentBluePoint = ref(0);
const showRoundTip = ref(false);
const playersScores = ref({});
const showModal = ref(false);
const halfTimeTip = ref(false);
const isFinalShoot = ref(false);
const total = ref(90);

onLoad(async (options) => {
  if (options.battleId) {
    const battleInfo = uni.getStorageSync(`battle-${options.battleId}`);
    // console.log("----battleInfo", battleInfo);
    if (battleInfo) {
      battleId.value = battleInfo.id;
      start.value = true;
      redTeam.value = battleInfo.redTeam;
      blueTeam.value = battleInfo.blueTeam;
      currentRound.value = battleInfo.currentRound;
      bluePoints.value = battleInfo.blueScore;
      redPoints.value = battleInfo.redScore;
      totalRounds.value = battleInfo.maxRound;
      roundResults.value = battleInfo.roundResults;
      currentShooterId.value = battleInfo.firePlayerIndex;
      const remain = Date.now() / 1000 - battleInfo.fireTime;
      if (remain > 0 && remain < 15) {
        // 等渲染好再通知
        setTimeout(() => {
          uni.$emit("update-ramain", remain);
        }, 300);
      }
    }
  }
  if (options.roomNumber) {
    roomNumber.value = options.roomNumber;
    const result = await getRoomAPI(options.roomNumber);
    room.value = result;
    result.members.some((m) => {
      if (m.userInfo.id === result.creator) {
        owner.value = {
          id: m.userInfo.id,
          name: m.userInfo.name,
          avatar: m.userInfo.avatar,
        };
        return true;
      }
      return false;
    });
    if (result.battleType === 1) {
      total.value = 15;
      if (user.value.id !== owner.value.id) {
        opponent.value = {
          id: user.value.id,
          name: user.value.nickName,
          avatar: user.value.avatar,
        };
      } else if (result.members.length > 1) {
        result.members.some((m) => {
          if (m.userInfo.id !== owner.value.id) {
            opponent.value = {
              id: m.userInfo.id,
              name: m.userInfo.name,
              avatar: m.userInfo.avatar,
            };
            return true;
          }
          return false;
        });
      }
    } else if (result.battleType === 2) {
      result.members.forEach((m) => {
        players.value.push(m.userInfo);
      });
    }
  }
});
const startGame = async () => {
  const result = await startRoomAPI(room.value.number);
  timerSeq.value += 1;
  step.value = 2;
};

async function onReceiveMessage(messages = []) {
  messages.forEach((msg) => {
    if (
      msg.roomNumber === roomNumber.value ||
      (battleId.value && msg.id === battleId.value) ||
      msg.constructor === MESSAGETYPES.WaitForAllReady
    ) {
      console.log("收到消息：", getMessageTypeName(msg.constructor), msg);
    }
    if (msg.constructor === MESSAGETYPES.WaitForAllReady) {
      // 这里会掉多次;
      timerSeq.value += 1;
      battleId.value = msg.id;
      if (room.value.battleType === 1) {
        redTeam.value = msg.groupUserStatus.redTeam;
        blueTeam.value = msg.groupUserStatus.blueTeam;
      }
      step.value = 2;
    }
    if (msg.roomNumber === roomNumber.value) {
      if (msg.constructor === MESSAGETYPES.UserEnterRoom) {
        if (room.value.battleType === 1) {
          if (msg.userId === room.value.creator) {
            owner.value = {
              id: msg.userId,
              name: msg.name,
              avatar: msg.avatar,
            };
          } else {
            opponent.value = {
              id: msg.userId,
              name: msg.name,
              avatar: msg.avatar,
            };
          }
        }
        if (room.value.battleType === 2) {
          players.value.push({
            id: msg.userId,
            name: msg.name,
            avatar: msg.avatar,
          });
        }
      }
      if (!start.value && msg.constructor === MESSAGETYPES.UserExitRoom) {
        if (room.value.battleType === 1) {
          if (msg.userId === room.value.creator) {
            owner.value = {
              id: "",
            };
          } else {
            opponent.value = {
              id: "",
            };
          }
        }
        if (room.value.battleType === 2) {
          players.value = players.value.filter((p) => p.id !== msg.userId);
        }
      }
      if (msg.constructor === MESSAGETYPES.RoomDestroy && !battleId.value) {
        uni.showToast({
          title: "房间已解散",
          icon: "none",
        });
        roomNumber.value = "";
        setTimeout(() => {
          uni.navigateBack();
        }, 1000);
      }
    }
    if (msg.id === battleId.value) {
      if (msg.constructor === MESSAGETYPES.AllReady) {
        start.value = true;
        timerSeq.value = 0;
        scores.value = [];
        totalRounds.value = msg.groupUserStatus.config.maxRounds;
        step.value = 3;
        if (room.value.battleType === 2) {
          tips.value = "请在90秒内射完12支箭";
          seq.value += 1;
        }
      }
      if (msg.constructor === MESSAGETYPES.MeleeAllReady) {
        start.value = true;
        startCount.value = true;
        seq.value += 1;
        timerSeq.value = 0;
        tips.value = "请连续射出6支箭";
        scores.value = [];
      }
      if (msg.constructor === MESSAGETYPES.ToSomeoneShoot) {
        if (room.value.battleType === 1) {
          if (currentShooterId.value !== msg.userId) {
            scores.value = [];
            blueScores.value = [];
            seq.value += 1;
            currentShooterId.value = msg.userId;
            if (redTeam.value[0].id === currentShooterId.value) {
              tips.value = "请红队射箭-";
            } else {
              tips.value = "请蓝队射箭-";
            }
            if (isFinalShoot.value) {
              tips.value += "决金箭";
            } else {
              tips.value += `第${roundsName[currentRound.value]}轮`;
            }
          }
        }
      }
      if (msg.constructor === MESSAGETYPES.ShootResult) {
        if (room.value.battleType === 1) {
          const isRed = redTeam.value.find((item) => item.id === msg.userId);
          if (isRed) {
            scores.value = [msg.target];
          } else {
            blueScores.value = [msg.target];
          }
        }
        if (room.value.battleType === 2) {
          scores.value.push(msg.target);
          power.value = msg.target.battery;
        }
        if (playersScores.value[msg.userId])
          playersScores.value[msg.userId].push(msg.target);
      }
      if (msg.constructor === MESSAGETYPES.CurrentRoundEnded) {
        if (room.value.battleType === 1) {
          const result = msg.preRoundResult;
          scores.value = [];
          blueScores.value = [];
          currentShooterId.value = 0;
          currentBluePoint.value = result.blueScore;
          currentRedPoint.value = result.redScore;
          bluePoints.value += result.blueScore;
          redPoints.value += result.redScore;
          roundResults.value = result.roundResults;
          currentRound.value = result.currentRound + 1;
          if (result.currentRound < 5) showRoundTip.value = true;
        }
      }
      if (msg.constructor === MESSAGETYPES.FinalShoot) {
        isFinalShoot.value = true;
        showRoundTip.value = true;
      }
      if (msg.constructor === MESSAGETYPES.HalfTimeOver) {
        startCount.value = false;
        halfTimeTip.value = true;
        tips.value = "准备下半场";
      }
      if (msg.constructor === MESSAGETYPES.MatchOver) {
        uni.redirectTo({
          url: `/pages/battle-result?battleId=${msg.id}`,
        });
      }
    }
  });
}

const destroyRoom = async () => {
  if (roomNumber.value) await destroyRoomAPI(roomNumber.value);
};

const exitRoom = async () => {
  uni.navigateBack();
};

onMounted(() => {
  uni.$on("socket-inbox", onReceiveMessage);
});

onUnmounted(() => {
  uni.$off("socket-inbox", onReceiveMessage);
  if (owner.value.id !== user.value.id && !battleId.value) {
    exitRoomAPI(roomNumber.value);
  }
});
</script>

<template>
  <Container
    title="对战"
    :onBack="() => (showModal = true)"
    :bgType="battleId ? 1 : 0"
  >
    <view class="standby-phase" v-if="step === 1">
      <Guide>
        <view :style="{ display: 'flex', flexDirection: 'column' }">
          <text :style="{ color: '#fed847' }">人都到齐了吗？</text>
          <text>天赋异禀的弓箭手们，比赛即将开始！</text>
        </view>
      </Guide>
      <view v-if="room.battleType === 1" class="team-mode">
        <image src="../static/1v1-bg.png" mode="widthFix" />
        <view>
          <view class="player" :style="{ transform: 'translateY(-60px)' }">
            <image :src="owner.avatar" mode="widthFix" />
            <text>{{ owner.name }}</text>
          </view>
          <image src="../static/versus.png" mode="widthFix" />
          <block v-if="opponent.id">
            <view class="player" :style="{ transform: 'translateY(60px)' }">
              <image :src="opponent.avatar" mode="widthFix" />
              <text v-if="opponent.name">{{ opponent.name }}</text>
            </view>
          </block>
          <block v-else>
            <view class="no-player">
              <image src="../static/question-mark.png" mode="widthFix" />
            </view>
          </block>
        </view>
      </view>
      <PlayerSeats
        v-if="room.battleType === 2"
        :total="room.count || 10"
        :players="players"
      />
      <view>
        <SButton
          v-if="user.id === owner.id && room.battleType === 1"
          :disabled="!opponent.id"
          :onClick="startGame"
          >进入对战</SButton
        >
        <SButton
          v-if="user.id === owner.id && room.battleType === 2"
          :disabled="players.length < 2"
          :onClick="startGame"
          >进入大乱斗</SButton
        >
        <SButton v-if="user.id !== owner.id" disabled>等待房主开启对战</SButton>
        <text class="tips">创建者点击下一步，所有人即可进入游戏。</text>
      </view>
    </view>
    <view v-if="step === 2" :style="{ width: '100%' }">
      <BattleHeader
        :blueTeam="blueTeam"
        :redTeam="redTeam"
        :players="players"
      />
      <TestDistance :guide="false" />
    </view>
    <view v-if="step === 3">
      <ShootProgress
        :tips="tips"
        :seq="seq"
        :start="start && startCount"
        :total="total"
      />
      <PlayersRow
        v-if="room.battleType === 1"
        :blueTeam="blueTeam"
        :redTeam="redTeam"
        :currentShooterId="currentShooterId"
      />
      <BowTarget
        :mode="room.battleType ? 'team' : 'solo'"
        :showE="start && user.id === currentShooterId"
        :power="start ? power : 0"
        :currentRound="currentRound"
        :totalRound="totalRounds"
        :scores="scores"
        :blueScores="blueScores"
      />
      <BattleFooter
        v-if="room.battleType === 1"
        :roundResults="roundResults"
        :redPoints="redPoints"
        :bluePoints="bluePoints"
      />
      <PlayerScore
        v-if="room.battleType === 2"
        v-for="(player, index) in players"
        :key="index"
        :name="player.name"
        :avatar="player.avatar"
        :scores="playersScores[player.id] || []"
        :done="
          playersScores[player.id] && playersScores[player.id].length === 12
        "
      />
    </view>
    <Timer :seq="timerSeq" />
    <ScreenHint :show="showRoundTip" :onClose="() => (showRoundTip = false)">
      <RoundEndTip
        :isFinal="isFinalShoot"
        :round="currentRound - 1"
        :bluePoint="currentBluePoint"
        :redPoint="currentRedPoint"
        :roundData="roundResults[roundResults.length - 1]"
        :onAutoClose="() => (showRoundTip = false)"
      />
    </ScreenHint>
    <ScreenHint
      :show="halfTimeTip"
      mode="small"
      :onClose="() => (halfTimeTip = false)"
    >
      <view class="half-time-tip">
        <text>上半场结束，休息一下吧:）</text>
        <text>20秒后开始下半场</text>
      </view>
    </ScreenHint>
    <SModal :show="showModal" :onClose="() => (showModal = false)">
      <view class="btns">
        <block v-if="!battleId">
          <SButton :onClick="exitRoom" width="200px" :rounded="20">
            暂时离开
          </SButton>
          <block v-if="owner.id === user.id">
            <view :style="{ height: '20px' }"></view>
            <SButton :onClick="destroyRoom" width="200px" :rounded="20">
              解散房间
            </SButton>
          </block>
        </block>
        <block v-else>
          <SButton :onClick="exitRoom" width="200px" :rounded="20">
            退出比赛
          </SButton>
        </block>
      </view>
    </SModal>
  </Container>
</template>

<style scoped>
.standby-phase {
  width: 100%;
  height: calc(100% - 40px);
  overflow-x: hidden;
}
.tips {
  color: #fff9;
  width: 100%;
  text-align: center;
  display: block;
  margin-top: 10px;
  font-size: 12px;
}
.player-unknow {
  width: 40px;
  height: 40px;
  margin: 0 10px;
  border: 1px solid #fff3;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #69686866;
}
.player-unknow > image {
  width: 40%;
}
.team-mode {
  width: calc(100vw - 30px);
  height: 107vw;
  margin: 15px;
}
.team-mode > image:first-child {
  position: absolute;
  width: calc(100vw - 30px);
  z-index: -1;
}
.team-mode > view {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 95%;
}
.player {
  width: 70px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  transform: translateY(-60px);
  color: #fff9;
  font-size: 14px;
}
.player > image {
  width: 70px;
  height: 70px;
  border-radius: 50%;
  background-color: #ccc;
  margin-bottom: 5px;
}
.player > text {
  width: 100px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: center;
}
.team-mode > view > image:nth-child(2) {
  width: 120px;
}
.no-player {
  width: 70px;
  height: 70px;
  border-radius: 50%;
  background-color: #ccc;
  display: flex;
  justify-content: center;
  align-items: center;
  transform: translateY(60px);
}
.no-player > image {
  width: 20px;
  margin-right: 2px;
}
.btns {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
</style>
