<template>
  <v-app
    id="pacificoApp"
    :class="{
      'tw:select-none': isDraggingOrResizingAnything,
      klingon: locale === 'tl-TL',
    }"
  >
    <!-- Global Toolbar -->
    <v-app-bar
      :order="-10"
      v-if="availableInterfaces.indexOf('topBar') > -1"
      id="appAppbar"
      ref="appAppbar"
      color="topbar-bg"
      density="compact"
      flat
      app
      class="tw:border-0 tw:border-b tw:border-solid"
      :class="{
        'tw:border-gray-300': theme === 'light',
        'tw:border-[#444]': theme === 'dark',
      }"
    >
      <div class="tw:flex tw:items-center">
        <!-- home icon -->
        <div class="tw:flex tw:justify-center">
          <RouterLink
            :to="{
              path: '/',
            }"
          >
            <img
              class="tw:cursor-pointer tw:h-[40px] tw:ml-2"
              src="/home-icon.png"
            />
          </RouterLink>
        </div>

        <img v-if="logoExists" class="tw:h-[40px]" :src="logoSrc" alt="Logo" />
      </div>
      <v-spacer />
      <AppBarMenu />
      <v-spacer />

      <DevIndicator v-if="isDevelopment" />

      <UserNotifications />
      <ServerStatus />
      <UserMenu
        :class="{
          klingon: locale === 'tl-TL',
        }"
      />
    </v-app-bar>

    <snackbarStack />
    <!-- Navigation Drawer -->
    <PageNavigation
      :key="locale"
      v-if="availableInterfaces.indexOf('pageNavigation') > -1"
    />

    <!-- Main content -->
    <v-main
      class="tw:flex tw:flex-col tw:min-h-0 tw:overflow-y-auto tw:h-screen"
      id="appMainContent"
      :aria-busy="loading"
    >
      <div class="tw:w-full tw-h-1 tw:top-[49px]">
        <v-progress-linear
          :height="2"
          :indeterminate="loading"
          color="primary"
          role="progressbar"
          :aria-hidden="!loading"
          :aria-label="$t('core.app_loading')"
        />
      </div>

      <span
        v-if="loading"
        class="tw:sr-only"
        role="status"
        aria-live="polite"
      >
        {{ $t("core.app_loading") }}
      </span>

      <component v-if="showWelcomeScreen" :is="welcomeScreenComponent" />

      <template v-else>
        <WidgetsLayoutLoader
          v-if="widgetsLayout"
          class="tw:min-h-0 tw:pb-0"
          :class="{ '!tw:invisible': loading }"
          :aria-hidden="loading"
          :widgets-layout="widgetsLayout"
          slot-type="page"
          :slot-layout="slotLayout"
        />

        <v-empty-state
          v-else
          :headline="$t('core.error.404')"
          :title="$t('core.error.page_not_foundTitle')"
          :text="$t('core.error.page_not_foundSubtitle')"
          image="/Logo_Main_V1.png"
        >
          <v-btn :to="{ path: '/' }">{{
            $t("core.error.return_to_home")
          }}</v-btn>
        </v-empty-state>
      </template>

      <v-footer
        :order="-1"
        color="footer-bg"
        ref="appFooter"
        border-thin
        v-if="configService.getPleaseLetUsAdvertiseOurselves()"
        class="tw:items-center tw:text-center tw:flex tw:flex-col tw:border-t tw:grow-0! tw:mt-auto"
      >
        <a
          href="https://www.raclettejs.com"
          rel="noopener noreferrer"
          target="_blank"
          title="raclette"
          class="tw:text-[0.9rem] tw:text-neutral-500 tw:no-underline hover:tw:no-underline hover:tw:text-neutral-700 tw:transition-colors"
        >
          Cooked with <span class="raclette">raclette 🧀</span></a
        >
        <span
          v-if="configService.getAdvertiseYourself().length"
          v-html="configService.getAdvertiseYourself()"
          class="footerLink tw:text-[0.9rem] tw:text-neutral-500 tw:no-underline hover:tw:no-underline hover:tw:text-neutral-700 tw:transition-colors"
        ></span>
      </v-footer>
    </v-main>

    <CompositionOverlay v-if="availableInterfaces.includes('modalTools')" />
  </v-app>
</template>

<script setup lang="ts">
import {
  onMounted,
  onUnmounted,
  useTemplateRef,
  ref,
  watch,
  computed,
  defineAsyncComponent,
} from "vue"
import UserNotifications from "./components/menu/UserNotifications.vue"
import PageNavigation from "./components/navigation/PageNavigationSidebar.vue"
import snackbarStack from "./components/snackbar/SnackStack.vue"
import ServerStatus from "./components/menu/ServerStatus.vue"
import UserMenu from "./components/menu/UserMenu.vue"
import DevIndicator from "./components/menu/DevIndicator.vue"
import { useTheme, useLocale } from "vuetify"
import { useRoute } from "vue-router"
import useUiState from "./composables/useUiState"
import useRouteState from "./composables/useRouteState"
import CompositionOverlay from "./components/composition/CompositionOverlay.vue"
import { useTitle, useLocalStorage } from "@vueuse/core"
import loginUserNotifications from "./helpers/loginUserNotifications"
import configService from "@racletteCore/lib/configService"
import { isDevelopmentMode } from "@racletteCore/helpers/devMode"
import useDragAndDrop from "./composables/useDragAndDrop"
import { useCurrentComposition } from "./composables"
import WidgetsLayoutLoader from "./components/composition/WidgetsLayoutLoader.vue"
import AppBarMenu from "./components/menu/AppBarMenu.vue"
import { useWindowSize } from "@vueuse/core"
const { height: windowHeight } = useWindowSize()

useTitle(`raclette - ${configService.getApplicationTitle()}`)
const route = useRoute()
const vuetifyLocale = useLocale()
const vuetifyTheme = useTheme()
const userTheme = useLocalStorage<string>("user-theme", null)
const { loading, theme, locale, landingPage, availableInterfaces } =
  useUiState()
useRouteState()
const { isDraggingOrResizingAnything } = useDragAndDrop()
const { widgetsLayout, slotLayout } = useCurrentComposition()

const appAppbarRef = useTemplateRef("appAppbar")
const appFooterRef = useTemplateRef("appFooter")
const availableComponentHeight = ref(0)

const updateAvailableHeight = () => {
  const appbarHeight =
    (appAppbarRef.value?.$el as HTMLElement | undefined)?.offsetHeight || 0
  const appFooterHeight =
    (appFooterRef.value?.$el as HTMLElement | undefined)?.offsetHeight || 0
  const progressBarHeight = 2 // Progress bar height
  const borderAndPadding = 8 // Border and padding buffer
  availableComponentHeight.value =
    windowHeight.value -
    appbarHeight -
    appFooterHeight -
    progressBarHeight -
    borderAndPadding
}
const showWelcomeScreen = computed(() => {
  const isDynamicPage = route.name === "app.space.page"
  let hasPageIdParameter = Boolean(route.params.pageId?.length)
  //TODO Fix this properly. If we have no page path but a modal on, we need to prevent the disapearance of the welcome screen
  if (route.params?.pageId?.indexOf("modal:") === 0) hasPageIdParameter = false

  const hasLandingPage = !!landingPage.value
  return isDynamicPage && !hasPageIdParameter && !hasLandingPage
})

const WelcomeScreenComponent = defineAsyncComponent({
  loader: () => import("./WelcomeScreen.vue"),
  errorComponent: {
    template: `
      <div class="tw:flex tw:items-center tw:justify-center tw:h-full tw:text-center tw:p-8">
        <div>
          <h1 class="tw:text-4xl tw:font-bold tw:mb-4 tw:text-gray-800">Welcome to racletteJS</h1>
          <p class="tw:text-gray-600 tw:text-lg">Get started by selecting a page from the navigation.</p>
        </div>
      </div>
    `,
  },
  delay: 0,
  timeout: 3000,
  suspensible: false,
  onError: (error, retry, fail, attempts) => {
    console.warn("WelcomeScreen component failed to load:", error)
    fail() // Don't retry, just fail gracefully
  },
})

const welcomeScreenComponent = computed(() => {
  return showWelcomeScreen.value ? WelcomeScreenComponent : null
})

const logoExists = ref(false)
const logoSrc = ref("/logo.png")

const checkImageExists = async (url: string): Promise<boolean> => {
  try {
    const response = await fetch(url, { method: "HEAD" })

    if (!response.ok) {
      return false
    }

    // Check if the response is actually an image
    const contentType = response.headers.get("content-type")
    return contentType ? contentType.startsWith("image/") : false
  } catch {
    return false
  }
}

const isDevelopment = ref(false)

const setTheme = (theme: "dark" | "light") => {
  vuetifyTheme.change(theme)

  // tailwind support
  if (theme === "dark") {
    document.body.classList.add("dark")
  } else {
    document.body.classList.remove("dark")
  }
}

onMounted(async () => {
  setTheme(theme.value)
  vuetifyLocale.current.value = locale.value
  isDevelopment.value = isDevelopmentMode()
  logoExists.value = await checkImageExists(logoSrc.value)
  // check if we have a message from checkToken to display as a snackbar
  loginUserNotifications()
  updateAvailableHeight()
  window.addEventListener("resize", updateAvailableHeight)
})
onUnmounted(() => {
  window.removeEventListener("resize", updateAvailableHeight)
})
watch(theme, () => {
  setTheme(theme.value)
})

// set vuetify locale here, the rest is done in setup/i18n
watch(locale, () => {
  vuetifyLocale.current.value = locale.value
})
window
  .matchMedia("(prefers-color-scheme: dark)")
  .addEventListener("change", (event) => {
    const newColorScheme = event.matches ? "dark" : "light"
    if (userTheme.value === null) {
      setTheme(theme.value)
    }
  })
</script>
<style lang="css">
.footerLink a {
  text-decoration: none;
  color: var(--tw-color-neutral-500);
}
</style>
