<script setup lang="ts">
import { useWindowSize } from "@vueuse/core";
import gsap from "gsap";
import { LazyLagModal } from "#components";

const { isReady } = useAssets();

const app = useAppStore();

const overlay = useOverlay();
const lagModal = overlay.create(LazyLagModal);

watch(
  () => app.lagDetected,
  (detected) => {
    if (detected) lagModal.open();
  },
);

const topScreen = useTemplateRef("topScreen");
const bottomScreen = useTemplateRef("bottomScreen");

const topScreenCanvas = computed(() => topScreen.value?.canvas ?? null);
const bottomScreenCanvas = computed(() => bottomScreen.value?.canvas ?? null);

const isTouchDevice = () =>
  "ontouchstart" in window || navigator.maxTouchPoints > 0;

const windowSize = useWindowSize();

const isLargeEnough = computed(
  () => windowSize.width.value / windowSize.height.value > 614 / 667,
);

watch([windowSize.width, windowSize.height], ([width, height]) => {
  if (width / height > 614 / 667) {
    if (app.booted) app.allowHints();
  } else {
    app.disallowHints();
  }
}, { immediate: true });

const helpButton = useTemplateRef("helpButton");
let helpAnimation: gsap.core.Timeline | null = null;

const showHelpLabels = async (yoyo = false) => {
  if (!app.hintsAllowed) return;

  helpAnimation?.kill();
  app.hintsVisible = true;

  await nextTick();

  helpAnimation = gsap
    .timeline({
      onComplete: () => {
        helpAnimation = null;
      },
    })
    .fromTo(
      helpButton.value,
      { color: "#666666", opacity: 0.5 },
      { color: "#ffffff", opacity: 1, duration: 0.2, ease: "power1.out" },
    )
    .to(helpButton.value, {
      color: "#666666",
      opacity: 0.5,
      duration: 0.2,
      ease: "power1.in",
      delay: 3,
    })
    .call(() => {
      app.hintsVisible = false;
    });

  if (yoyo) {
    helpAnimation.to(helpButton.value, {
      color: "#ffffff",
      opacity: 1,
      duration: 0.3,
      repeat: 5,
      yoyo: true,
      delay: 0.3,
    });
  }
};

const hideHelpLabels = () => {
  if (!app.hintsVisible) return;

  helpAnimation?.kill();
  helpAnimation = null;

  app.hintsVisible = false;

  gsap.to(helpButton.value, {
    color: "#666666",
    opacity: 0.5,
    duration: 0.2,
    ease: "power1.in",
  });
};

watch(
  () => app.hintsAllowed,
  (allowed) => {
    if (!allowed) hideHelpLabels();
  },
);

onMounted(async () => {
  if (isTouchDevice()) {
    const landscape = window.matchMedia("(orientation: landscape)");

    const onOrientationChange = (e: MediaQueryListEvent | MediaQueryList) => {
      if (e.matches && !document.fullscreenElement) {
        document.documentElement.requestFullscreen().catch(() => {});
      }
    };

    landscape.addEventListener("change", onOrientationChange);

    onUnmounted(() => {
      landscape.removeEventListener("change", onOrientationChange);
    });
  }

  const scaleX = (window.innerWidth - 40) / 235;
  const scaleY = (window.innerHeight - 40) / 431;
  const scale = Math.min(scaleX, scaleY);

  if (app.settings.renderingMode === "2d" && scale < 1) return;

  if (!app.booted) {
    watch(
      () => app.hintsAllowed,
      async (allowed) => {
        if (allowed) await showHelpLabels(true);
      },
      { once: true },
    );
  }
});

useKeyDown(async ({ key, repeated }) => {
  if (!repeated && key.toLocaleLowerCase() === "h") {
    if (app.hintsVisible) {
      hideHelpLabels();
    } else {
      await showHelpLabels();
    }
  }
});
</script>

<template>
  <LoadingScreen v-if="!isReady || !app.userHasInteracted" />
  <div v-else>
    <TresCanvas
      v-if="app.settings.renderingMode === '3d'"
      window-size
      clear-color="#181818"
    >
      <TresPerspectiveCamera :args="[45, 1, 0.001, 1000]" />

      <TresAmbientLight />
      <TresDirectionalLight />

      <NDS3D
        v-if="topScreenCanvas && bottomScreenCanvas"
        :top-screen-canvas="topScreenCanvas"
        :bottom-screen-canvas="bottomScreenCanvas"
      />
    </TresCanvas>

    <NDS2D
      :style="{
        visibility: app.settings.renderingMode === '3d' ? 'hidden' : 'visible',
      }"
    >
      <template #topScreen>
        <Screen ref="topScreen">
          <IntroTopScreen v-if="!app.booted" />
          <HomeTopScreen v-else-if="app.screen === 'home'" />
          <ContactTopScreen v-else-if="app.screen === 'contact'" />
          <ProjectsTopScreen v-else-if="app.screen === 'projects'" />
          <SettingsTopScreen v-else-if="app.screen === 'settings'" />
          <GalleryTopScreen v-else-if="app.screen === 'gallery'" />
          <AchievementsTopScreen v-else-if="app.screen === 'achievements'" />
          <CreditsTopScreen v-else-if="app.screen === 'credits'" />

          <AchievementsNotification />
          <CommonConfetti screen="top" />
        </Screen>
      </template>
      <template #bottomScreen>
        <Screen ref="bottomScreen">
          <IntroBottomScreen v-if="!app.booted" />
          <HomeBottomScreen v-else-if="app.screen === 'home'" />
          <ContactBottomScreen v-else-if="app.screen === 'contact'" />
          <ProjectsBottomScreen v-else-if="app.screen === 'projects'" />
          <SettingsBottomScreen v-else-if="app.screen === 'settings'" />
          <GalleryBottomScreen v-else-if="app.screen === 'gallery'" />
          <AchievementsBottomScreen v-else-if="app.screen === 'achievements'" />
          <CreditsBottomScreen v-else-if="app.screen === 'credits'" />

          <CommonConfetti screen="bottom" />
        </Screen>
      </template>
    </NDS2D>

    <button
      v-if="app.hintsAllowed"
      ref="helpButton"
      class="help-btn"
      @click="app.hintsVisible ? hideHelpLabels() : showHelpLabels()"
    >
      ?
    </button>

    <Controls />
  </div>
</template>

<style scoped>
.help-btn {
  position: fixed;
  bottom: 16px;
  left: 16px;
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  color: #666;
  font-size: 18px;
  cursor: pointer;
  opacity: 0.5;
  transition: opacity 0.2s;
  user-select: none;
  z-index: 100;
}

.help-btn:hover {
  opacity: 1;
}
</style>
