<script lang="ts" setup>
import { computed, onMounted, onUnmounted, toRefs, watch } from "vue"

import HeaderNote from "@/components/HeaderNote.vue"
import SignInGithub from "@/components/SignInGithub.vue"
import SkeletonLoader from "@/components/SkeletonLoader.vue"
import StackedNote from "@/components/StackedNote.vue"
import { useGitHubLogin } from "@/hooks/useGitHubLogin.hook"
import { useLinks } from "@/hooks/useLinks.hook"
import { markdownBuilder } from "@/hooks/useMarkdown.hook"
import { useMarkdownPostRender } from "@/hooks/useMarkdownPostRender.hook"
import { useNoteView } from "@/hooks/useNoteView.hook"
import { useResizeContainer } from "@/hooks/useResizeContainer.hook"
import { useRouteQueryStackedNotes } from "@/hooks/useRouteQueryStackedNotes.hook"
import { useVisitRepo } from "@/modules/history/hooks/useVisitRepo.hook"
import CacheAllNotes from "@/modules/note/components/CacheAllNote.vue"
import { useUserRepoStore } from "@/modules/repo/store/userRepo.store"
import { useUserSettings } from "@/modules/user/hooks/useUserSettings.hook"

const props = withDefaults(
  defineProps<{
    user: string
    repo: string
    content?: string | null
    parseContent?: boolean
    withContent?: boolean
    withHeader?: boolean
  }>(),
  {
    content: null,
    parseContent: true,
    withContent: true,
    withHeader: true
  }
)

const user = computed(() => props.user)
const repo = computed(() => props.repo)

const refProps = toRefs(props)
const store = useUserRepoStore()
useUserSettings()
const { visitRepo } = useVisitRepo({ user: user, repo: repo })
const { toHTML } = markdownBuilder(repo)
const { listenToClick } = useLinks("note-display")
const { stackedNotes, scrollToFocusedNote } = useRouteQueryStackedNotes()

const { titles } = useNoteView()
const { isLogged } = useGitHubLogin()
useResizeContainer("note-container", stackedNotes)

const renderedContent = computed(() =>
  props.content !== null
    ? props.parseContent
      ? toHTML(props.content)
      : props.content
    : store.readme
)

const isLoading = computed(() => renderedContent.value === undefined)
const hasContent = computed(() => !!renderedContent.value)

useMarkdownPostRender(renderedContent, () => ".note-display", {
  onReady: () => listenToClick(),
  tikz: true
})

watch(
  [refProps.user, refProps.repo],
  () => {
    store.setUserRepo(props.user, props.repo)
  },
  { immediate: true }
)

const retryLoad = () => {
  store.setUserRepo(props.user, props.repo)
}

onMounted(() => visitRepo())

onUnmounted(() => {
  store.resetFiles()
})
</script>

<template>
  <main class="flux-note repo-note content note-container">
    <div class="note readme">
      <header-note v-if="withHeader" class="header" :user="user" :repo="repo" />
      <div class="repo-title-breadcrumb">
        <a
          class="title-stacked-note-link"
          @click.prevent="scrollToFocusedNote()"
          >{{ repo }}</a
        >
      </div>
      <div class="repo-title">
        <div class="repo-header">
          <h1 class="heading-1">
            {{ repo }}
          </h1>
          {{ user }}
        </div>
        <cache-all-notes />
      </div>
      <slot />
      <skeleton-loader v-if="isLoading" />
      <div
        v-else-if="withContent && !hasContent && store.loadError === 'network'"
        class="repo-network-error"
      >
        <p>Couldn't reach GitHub. Check your connection.</p>
        <button class="btn btn-primary" @click="retryLoad">Retry</button>
      </div>
      <div v-else-if="withContent && !hasContent" class="repo-not-found">
        <template v-if="isLogged">
          <p>This repository is not accessible.</p>
        </template>
        <template v-else>
          <p>This repository is private. Sign in to view it.</p>
          <sign-in-github />
        </template>
      </div>
      <p
        v-else-if="withContent && hasContent"
        class="note-display"
        v-html="renderedContent"
      />
    </div>
    <stacked-note
      v-for="(stackedNote, index) in stackedNotes"
      :key="stackedNote"
      class="note"
      :index="index"
      :sha="stackedNote"
      :user="user"
      :repo="repo"
      :title="titles[stackedNote]"
    />
  </main>
</template>

<style lang="scss">
$header-height: 40px;

.flux-note {
  display: flex;
  flex: 1;

  &.content {
    .title,
    h1,
    h2,
    h3,
    h4,
    h5,
    h6,
    strong {
      color: var(--color-base-content);
    }

    table {
      color: var(--color-base-content);
      background-color: var(--color-base-100);

      thead {
        th {
          color: var(--color-base-content);
        }
      }
    }

    blockquote {
      background-color: var(--color-base-100);
      color: var(--color-base-content);
    }
  }

  .header {
    height: $header-height;
  }

  .readme {
    position: sticky;
    left: 0;
    top: 0;
    padding: 0 2rem;
    scrollbar-width: none;

    .repo-title {
      margin-top: 1rem;
      display: flex;
      flex-direction: column;
      align-items: center;

      .title {
        margin-bottom: 0;
      }

      .title,
      .subtitle {
        text-align: center;
      }

      img {
        vertical-align: middle;
      }
    }
  }

  .repo-not-found,
  .repo-network-error {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    padding: 2rem 0;
    color: var(--color-base-content);
  }

  .note-display {
    padding-bottom: 2rem;
  }

  .note {
    display: flex;
    flex-direction: column;
    overflow-y: auto;

    .title {
      text-align: left;
    }
  }

  @media screen and (min-width: 769px) {
    background-color: var(--note-canvas-bg);

    .repo-title-breadcrumb {
      padding: 0.5rem 1rem 0;
      transform-origin: 0 0;
      transform: rotate(90deg);
      font-size: 0.8em;

      a {
        color: var(--color-base-content);
        display: block;
        text-align: center;
      }
    }

    .note {
      min-width: var(--note-width);
      max-width: var(--note-width);
      background-color: var(--color-base-100);
    }

    .readme {
      box-shadow: var(--note-sheet-shadow);
    }
  }
}

@media print, screen and (max-width: 768px) {
  .flux-note {
    .readme {
      padding: 0 0.75rem;
      position: relative;
    }
  }

  .flux-note {
    flex-wrap: wrap;
  }

  .note {
    width: 100vw;
    height: 100svh;
    overflow-y: visible;
  }

  .repo-title-breadcrumb {
    display: none;
    visibility: hidden;
  }
}
</style>
