<template>
  <div id="outBlock">
    <div id="outBlock2">
      <nav class="navbar navbar-expand navbar-dark bg-dark d-sm-block p-0">
        <div class="container-fluid px-0">
          <div class="collapse navbar-collapse">
            <ul class="navbar-nav me-auto mx-auto">
              <li class="nav-item">테스트</li>
              <li class="nav-item">테스트</li>
              <li class="nav-item">테스트</li>
            </ul>
          </div>
        </div>
      </nav>
      <!-- eslint-disable-next-line vue/max-attributes-per-line -->
      <BContainer v-if="asyncReady" id="container" :position="'position-relative'" :toast="{ root: true }" class="bg0">
        <main>
          <div class="commonToolbar">툴바?</div>
          <div class="gameInfo">시나리오</div>
          <div class="gameInfo">토너먼트/설문</div>
          <div class="gameInfo2">접속중인</div>
          <div class="nationNotice">국방</div>
          <div>접속자</div>
          <div class="d-grid"><BButton @click="tryRefresh">갱신</BButton></div>
          <!-- TODO: 운영자 툴바는 어디에?-->
          <div class="mapView">지도</div>
          <div class="reservedCommandZone">예턴</div>
          <div class="cityInfo">도시 정보</div>
          <div class="nationInfo">국가 정보</div>
          <div class="generalInfo">장수 정보</div>
          <div class="generalCommandToolbar">국가 툴바</div>
          <div class="actionMiniPlate">갱신/로비 버튼</div>
          <div class="PublicRecord">
            <div class="title">장수 동향</div>
            <template v-for="[idx, rawText] of globalRecords.toArray()" :key="idx">
              <!-- eslint-disable-next-line vue/no-v-html -->
              <div :v-data-idx="idx" v-html="formatLog(rawText)" />
            </template>
          </div>
          <div class="GeneralLog">
            <div class="title">개인 기록</div>
            <template v-for="[idx, rawText] of generalRecords.toArray()" :key="idx">
              <!-- eslint-disable-next-line vue/no-v-html -->
              <div :v-data-idx="idx" v-html="formatLog(rawText)" />
            </template>
          </div>
          <div class="WorldHistory">
            <div class="title">중원 정세</div>
            <template v-for="[idx, rawText] of worldHistory.toArray()" :key="idx">
              <!-- eslint-disable-next-line vue/no-v-html -->
              <div :v-data-idx="idx" v-html="formatLog(rawText)" />
            </template>
          </div>
          <div class="commonToolbar">툴바?</div>
          <div class="MessageInputForm">메시지 입력</div>
          <div class="PublicTalk">전체 메시지</div>
          <div class="NationalTalk">국가 메시지</div>
          <div class="PrivateTalk">개인 메시지</div>
          <div class="DiplomacyTalk">외교 메시지</div>
          <div class="commonToolbar">툴바?</div>
        </main>
      </BContainer>
      <div v-else>서버 갱신 중입니다.</div>
    </div>
    <nav id="mobileBottomBar">
      <BButton>하단 바</BButton>
      <BButton>하단 바2</BButton>
    </nav>
  </div>
</template>
<script lang="ts">
declare const staticValues: {
  serverName: string;
  serverNick: string;
  serverID: string;
  mapName: string;
  unitSet: string;
};
</script>
<script lang="ts" setup>
import { BContainer, BButton, useToast } from "bootstrap-vue-3";
import { isString } from "lodash";
import { provide, ref, watch } from "vue";
import { GameConstStore, getGameConstStore } from "./GameConstStore";
import { SammoAPI, type InvalidResponse } from "./SammoAPI";
import { parseTime } from "./util/parseTime";
import { unwrap } from "./util/unwrap";
import Denque from "denque";
import { formatLog } from "@/utilGame/formatLog";
import type { ExecuteResponse } from "./defs/API/Global";
import { delay } from "./util/delay";

const { serverName, serverNick, serverID } = staticValues;

const asyncReady = ref(false);
const gameConstStore = ref<GameConstStore>();

const toasts = unwrap(useToast());

provide("gameConstStore", gameConstStore);

const lastExecuted = ref<Date>(parseTime("2022-08-15 00:00:00"));
const serverLocked = ref(true);
const refreshCounter = ref(0);

const storeP = getGameConstStore().then((store) => {
  gameConstStore.value = store;
});

let responseLock = false;

async function tryRefresh() {
  if (responseLock) {
    return;
  }
  try {
    responseLock = true;
    const responseP = SammoAPI.Global.ExecuteEngine({ serverID }, true).then(
      (response) => {
        if (response.result) {
          lastExecuted.value = parseTime(response.lastExecuted);
          serverLocked.value = response.locked;
        }
        return response;
      }
    );

    //TODO: 갱신 알림 띄우기
    const response = await Promise.race([delay(3000), responseP]);
    responseLock = false;

    if(response === undefined){
      //timeout이지만 일단 갱신한다.
      refreshCounter.value += 1;
      return;
    }

    if (!response.result) {
      if (response.reqRefresh) {
        alert(`갱신이 필요합니다: ${response.reason}`);
        window.location.reload();
        return;
      }

      console.error(response.reason);
      if (!asyncReady.value) {
        throw response.reason;
      }
      toasts.danger({
        title: "갱신 실패",
        body: response.reason,
      });
      return;
    }

    refreshCounter.value += 1;

    //TODO: 서버와 클라이언트 버전이 다르다면 갱신 필요
  } catch (e) {
    responseLock = false;
    //매우 심각한 버그
    console.error(e);
    alert(`서버 갱신 실패: ${e}`);
    throw e;
  }
}

void Promise.all([storeP, tryRefresh()]).then(() => {
  asyncReady.value = true;
});

const lastGeneralRecordID = ref(0);
const lastWorldHistoryID = ref(0);

const generalRecords = ref(new Denque<[number, string]>());
const globalRecords = ref(new Denque<[number, string]>());
const worldHistory = ref(new Denque<[number, string]>());

let recordLock = false;

watch(refreshCounter, async () => {
  if(recordLock){
    return;
  }
  try {
    recordLock = true;
    const response = await SammoAPI.Global.GetRecentRecord({
      lastGeneralRecordID: lastGeneralRecordID.value,
      lastWorldHistoryID: lastWorldHistoryID.value,
    });
    recordLock = false;

    if (response.flushGeneral) {
      generalRecords.value = new Denque<[number, string]>();
    }
    if (response.flushGlobal) {
      globalRecords.value = new Denque<[number, string]>();
    }
    if (response.flushHistory) {
      worldHistory.value = new Denque<[number, string]>();
    }

    if (response.general.length) {
      lastGeneralRecordID.value = Math.max(lastGeneralRecordID.value, response.general[0][0]);
    }
    if (response.global.length) {
      lastGeneralRecordID.value = Math.max(lastGeneralRecordID.value, response.global[0][0]);
    }
    if (response.history.length) {
      lastWorldHistoryID.value = Math.max(lastWorldHistoryID.value, response.history[0][0]);
    }

    while (response.general.length) {
      const [id, record] = unwrap(response.general.pop());
      if (!generalRecords.value.isEmpty() && id <= unwrap(generalRecords.value.get(0))[0]) {
        continue;
      }
      if(generalRecords.value.length >= 15) {
        generalRecords.value.pop();
      }
      generalRecords.value.unshift([id, record]);

    }

    while (response.global.length) {
      const [id, record] = unwrap(response.global.pop());
      if (!globalRecords.value.isEmpty() && id <= unwrap(globalRecords.value.get(0))[0]) {
        continue;
      }
      if(globalRecords.value.length >= 15) {
        globalRecords.value.pop();
      }
      globalRecords.value.unshift([id, record]);
    }

    while (response.history.length) {
      const [id, record] = unwrap(response.history.pop());
      if (!worldHistory.value.isEmpty() && id <= unwrap(worldHistory.value.get(0))[0]) {
        continue;
      }
      if(worldHistory.value.length >= 15) {
        worldHistory.value.pop();
      }
      worldHistory.value.unshift([id, record]);
    }
  } catch (e) {
    recordLock = false;
    console.error(e);
    toasts.danger({
      title: "최근 기록 갱신 실패",
      body: `${e}`,
    });
  }
});
</script>
<style lang="scss" scoped>
@import "@scss/common/break_500px.scss";

#mobileBottomBar {
  display: none;
}

#outBlock {
  display: flex;
  flex-flow: column;
  justify-content: space-between;
}

@include media-500px {
  #outBlock {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;

    #mobileBottomBar {
      display: block;
    }
  }

  #outBlock2 {
    flex-grow: 1;
    overflow-y: scroll;
  }

  #container {
    width: 500px;

    > main > div {
      min-height: 100px;
      /* 테스트 */
    }
  }
}

@include media-1000px {
  #container {
    width: 1000px;
  }
}
</style>
