<template>
  <Progress
    v-show="routerStatus.isLoad"
    class="router-progress"
    :size="6"
  />

  <div class="modals-container" />

  <main class="layout">
    <div class="left-menu">
      <RouterLink
        to="/"
        :class='$route.path === "/"
          ? "isActive"
          : ""'
        title="ホーム"
      >
        <img :src='"icon" in serverInfo
          ? serverInfo.icon
          : "/assets/lynqchat.svg"'
        />
      </RouterLink>

      <RouterLink
        v-for="community of communitys"
        :to="`/community/${community.id}`"
        :class='$route.path.startsWith(`/community/${community.id}`)
          ? "isActive"
          : ""'
        :title="community.name"
      >
        <img
          v-if="community.icon"
          :src="community.icon"
        />
        <Icon
          v-else
          icon="material-symbols:groups-rounded"
        />
      </RouterLink>
    </div>

    <div class="content-main">
      <div class="content-header">
        {{
          title
            ?? (serverInfo.success
              ? serverInfo.name
              : null)
            ?? "LynqChat"
        }}
      </div>

      <div
        class="route-main"
        :class='isFullRoute
          ? "full-route"
          : ""'
      >
        <RouterView />
      </div>
    </div>
  </main>
</template>

<style scoped>
main.layout {
  display: flex;
  width: 100dvw;
  height: 100dvh;
  padding: 0.5rem;
  gap: 0.5rem;
  box-sizing: border-box;
}

.left-menu {
  display: flex;
  flex-shrink: 0;
  flex-direction: column;
  padding: 0.5rem 0;
  height: 100%;
  overflow: scroll;
  gap: 0.5rem;
  box-sizing: border-box;
  user-select: none;
  -webkit-user-select: none;
}

.left-menu a {
  display: block;
  position: relative;
  z-index: 0;
  border-radius: 0.5rem;
  width: 3rem;
  height: 3rem;
  padding: 0.5rem;
  transition: background-color 200ms ease-out;
}

.left-menu a * {
  font-size: 3rem;
  padding: 0.25rem;
  border-radius: 0.5rem;
  width: 3rem;
  height: 3rem;
  color: var(--text-color);
  display: block;
  overflow: hidden;
  object-fit: contain;
  box-sizing: border-box;
}

.left-menu a::before {
  content: "";
  display: block;
  position: absolute;
  top: 50%;
  left: 0.3rem;
  transform: translateY(-50%);
  width: 0.25rem;
  height: 70%;
  border-radius: 0.5rem;
  background-color: transparent;
  transition: all 200ms ease-out;
}

.left-menu a.isActive::before {
  background-color: var(--text-color);
}

.left-menu a:hover,
.left-menu a.isActive {
  background-color: var(--border-color);
}

.content-main {
  border: 1px solid var(--border-color);
  background-color: var(--route-bg-color);
  border-radius: 0.5rem;
  overflow: hidden;
  flex-grow: 1;
}

.content-header {
  padding: 1rem 1.25rem;
  font-size: 1.3rem;
  font-weight: bold;
  border-bottom-left-radius: 0.5rem;
  border-bottom-right-radius: 0.5rem;
  border-bottom: 1px solid var(--border-color);
  box-shadow: 0px 1px 10px var(--border-color);
  user-select: none;
  -webkit-user-select: none;
}

.route-main {
  display: flex;
  flex-direction: column;
  padding: 1.25rem;
  padding-bottom: 0;
  overflow: scroll;
  height: 100%;
}

.content-main .route-main.full-route {
  padding: 0;
  overflow: hidden;
}

.router-progress {
  position: fixed;
  inset: 0.5rem 0.5rem 0 auto;
  z-index: 9999;
}

.modals-container {
  z-index: 9998;
  position: relative;
}

@media (max-width: 40rem) {
  .layout {
    padding: 0 !important;
  }

  .left-menu {
    display: none;
  }

  .content-main {
    border: none;
    border-radius: 0;
  }
}
</style>

<script lang="ts" setup>
import { RouterView, RouterLink, useRouter, useRoute } from "vue-router";
import routerStatus, { title } from "@/lib/router";
import { Icon } from "@iconify/vue";
import Progress from "@/components/Progress.vue";
import { communitys, serverInfo } from "@/lib/account";
import { computed, onBeforeUnmount, onMounted, watch } from "vue";
import { createModal } from "@/lib/modal";
import ErrorModal from "@/components/Modal/Error.vue";

const router = useRouter();
const route = useRoute();

const isFullRoute = computed(() => route.meta.isFullRoute === true);

watch(route, (to, from) => {
  if (
    to.matched[0]?.path === from.matched[0]?.path &&
    from.meta.canReloadTitle === false
  ) {
    routerStatus.isLoad = false;
    return false;
  }
  
  if (typeof route.meta.title === "string")
    title.value = route.meta.title;
});

if (!serverInfo.value.success) {
  throw new Error("サーバー情報の取得に失敗しました。");
}

if (!serverInfo.value.isInitialized) {
  router.replace("/setup/initialization");
}

if (!serverInfo.value.isFirstAdminExists) {
  router.replace("/setup/create-admin");
}

function handleError(event: ErrorEvent | PromiseRejectionEvent) {
  let content = event instanceof PromiseRejectionEvent
    ? event.reason
    : event;

  if (content instanceof Error) {
    content = content.message;
  }

  createModal({
    component: ErrorModal,
    props: {
      error: content ?? "不明なエラー",
      canClose: false,
    },
  });
}

onMounted(async () => {
  window.addEventListener("error", handleError);
  window.addEventListener("unhandledrejection", handleError);

  if ("serviceWorker" in navigator) {
    const swFile = import.meta.env.MODE === "production"
      ? "/sw.js"
      : "/dev-sw.js?dev-sw";
    
    navigator.serviceWorker.register(swFile, {
      type: import.meta.env.MODE === "production"
        ? "classic"
        : "module",
      scope: "/",
    });
  }
});

onBeforeUnmount(() => {
  window.removeEventListener("error", handleError);
  window.removeEventListener("unhandledrejection", handleError);
});
</script>