<template lang='pug'>
q-page.column
  .page-breadcrumbs.q-py-sm.q-px-md.row(
    v-if='!editorStore.isActive'
    )
    .col
      q-breadcrumbs(
        active-color='grey-7'
        separator-color='grey'
        )
        template(v-slot:separator)
          q-icon(
            name='las la-angle-right'
          )
        q-breadcrumbs-el(icon='las la-home', to='/', aria-label='Home')
          q-tooltip Home
        q-breadcrumbs-el(
          v-for='brd of pageStore.breadcrumbs'
          :key='brd.id'
          :icon='brd.icon'
          :label='brd.title'
          :aria-label='brd.title'
          :to='brd.path'
          )
    .col-auto.flex.items-center.justify-end
      template(v-if='!pageStore.publishState === `draft`')
        .text-caption.text-accent: strong Unpublished
        q-separator.q-mx-sm(vertical)
      .text-caption.text-grey-6 Last modified on #[strong {{lastModified}}]
  page-header
  .page-container.row.no-wrap.items-stretch(style='flex: 1 1 100%;')
    .col(
      :style='siteStore.theme.tocPosition === `left` ? `order: 2;` : `order: 1;`'
      )
      q-no-ssr(
        v-if='editorStore.isActive'
        )
        component(:is='editorComponents[editorStore.editor]')
      q-scroll-area.page-container-scrl(
        v-else
        :thumb-style='thumbStyle'
        :bar-style='barStyle'
        style='height: 100%;'
        )
        .q-pa-md
          .page-contents(ref='pageContents', v-html='pageStore.render')
          template(v-if='pageStore.relations && pageStore.relations.length > 0')
            q-separator.q-my-lg
            .row.align-center
              .col.text-left(v-if='relationsLeft.length > 0')
                q-btn.q-mr-sm.q-mb-sm(
                  padding='sm md'
                  outline
                  :icon='rel.icon'
                  no-caps
                  color='primary'
                  v-for='rel of relationsLeft'
                  :key='`rel-id-` + rel.id'
                  )
                  .column.text-left.q-pl-md
                    .text-body2: strong {{rel.label}}
                    .text-caption {{rel.caption}}
              .col.text-center(v-if='relationsCenter.length > 0')
                .column
                  q-btn(
                    :label='rel.label'
                    color='primary'
                    flat
                    no-caps
                    :icon='rel.icon'
                    v-for='rel of relationsCenter'
                    :key='`rel-id-` + rel.id'
                  )
              .col.text-right(v-if='relationsRight.length > 0')
                q-btn.q-ml-sm.q-mb-sm(
                  padding='sm md'
                  outline
                  :icon-right='rel.icon'
                  no-caps
                  color='primary'
                  v-for='rel of relationsRight'
                  :key='`rel-id-` + rel.id'
                  )
                  .column.text-left.q-pr-md
                    .text-body2: strong {{rel.label}}
                    .text-caption {{rel.caption}}
    .page-sidebar(
      v-if='showSidebar'
      :style='siteStore.theme.tocPosition === `left` ? `order: 1;` : `order: 2;`'
      )
      template(v-if='pageStore.showToc')
        //- TOC
        .q-pa-md.flex.items-center
          q-icon.q-mr-sm(name='las la-stream', color='grey')
          .text-caption.text-grey-7 Contents
        .q-px-md.q-pb-sm
          q-tree.page-toc(
            :nodes='pageStore.toc'
            icon='las la-caret-right'
            node-key='key'
            dense
            v-model:expanded='state.tocExpanded'
            v-model:selected='state.tocSelected'
          )
      //- Tags
      template(v-if='pageStore.showTags')
        q-separator(v-if='pageStore.showToc')
        .q-pa-md(
          @mouseover='state.showTagsEditBtn = true'
          @mouseleave='state.showTagsEditBtn = false'
          )
          .flex.items-center
            q-icon.q-mr-sm(name='las la-tags', color='grey')
            .text-caption.text-grey-7 Tags
            q-space
            transition(name='fade')
              q-btn(
                v-show='state.showTagsEditBtn'
                size='sm'
                padding='none xs'
                icon='las la-pen'
                color='deep-orange-9'
                flat
                label='Edit'
                no-caps
                @click='state.tagEditMode = !state.tagEditMode'
              )
          page-tags.q-mt-sm(:edit='state.tagEditMode')
      template(v-if='siteStore.features.ratingsMode !== `off` && pageStore.allowRatings')
        q-separator(v-if='pageStore.showToc || pageStore.showTags')
        //- Rating
        .q-pa-md.flex.items-center
          q-icon.q-mr-sm(name='las la-star-half-alt', color='grey')
          .text-caption.text-grey-7 Rate this page
        .q-px-md
          q-rating(
            v-if='siteStore.features.ratingsMode === `stars`'
            v-model='state.currentRating'
            icon='las la-star'
            color='secondary'
            size='sm'
          )
          .flex.items-center(v-else-if='siteStore.features.ratingsMode === `thumbs`')
            q-btn.acrylic-btn(
              flat
              icon='las la-thumbs-down'
              color='secondary'
            )
            q-btn.acrylic-btn.q-ml-sm(
              flat
              icon='las la-thumbs-up'
              color='secondary'
            )
    page-actions-col

  side-dialog
</template>

<script setup>
import { useMeta, useQuasar } from 'quasar'
import { computed, defineAsyncComponent, nextTick, onMounted, reactive, ref, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { DateTime } from 'luxon'

import { useCommonStore } from '@/stores/common'
import { useEditorStore } from '@/stores/editor'
import { useFlagsStore } from '@/stores/flags'
import { usePageStore } from '@/stores/page'
import { useSiteStore } from '@/stores/site'
import { useUserStore } from '@/stores/user'

// COMPONENTS

import LoadingGeneric from '@/components/LoadingGeneric.vue'
import PageActionsCol from '@/components/PageActionsCol.vue'
import PageHeader from '@/components/PageHeader.vue'
import PageTags from '@/components/PageTags.vue'
import SideDialog from '@/components/SideDialog.vue'

const editorComponents = {
  markdown: defineAsyncComponent({
    loader: () => import('../components/EditorMarkdown.vue'),
    loadingComponent: LoadingGeneric
  }),
  wysiwyg: defineAsyncComponent({
    loader: () => import('../components/EditorWysiwyg.vue'),
    loadingComponent: LoadingGeneric
  })
}

// QUASAR

const $q = useQuasar()

// STORES

const commonStore = useCommonStore()
const editorStore = useEditorStore()
const flagsStore = useFlagsStore()
const pageStore = usePageStore()
const siteStore = useSiteStore()
const userStore = useUserStore()

// ROUTER

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

// I18N

const { t } = useI18n()

// META

useMeta({
  title: pageStore.title
})

// DATA

const state = reactive({
  showSideDialog: false,
  sideDialogComponent: null,
  showGlobalDialog: false,
  globalDialogComponent: null,
  showTagsEditBtn: false,
  tagEditMode: false,
  tocExpanded: ['h1-0', 'h1-1'],
  tocSelected: [],
  currentRating: 3
})
const thumbStyle = {
  right: '2px',
  borderRadius: '5px',
  backgroundColor: $q.dark.isActive ? '#FFF' : '#000',
  width: '5px',
  opacity: 0.15
}
const barStyle = {
  backgroundColor: $q.dark.isActive ? '#161b22' : '#FAFAFA',
  width: '9px',
  opacity: 1
}

const pageContents = ref(null)

// COMPUTED

const showSidebar = computed(() => {
  return pageStore.showSidebar && siteStore.showSidebar && siteStore.theme.tocPosition !== 'off' && !editorStore.isActive
})
const relationsLeft = computed(() => {
  return pageStore.relations ? pageStore.relations.filter(r => r.position === 'left') : []
})
const relationsCenter = computed(() => {
  return pageStore.relations ? pageStore.relations.filter(r => r.position === 'center') : []
})
const relationsRight = computed(() => {
  return pageStore.relations ? pageStore.relations.filter(r => r.position === 'right') : []
})
const lastModified = computed(() => {
  return pageStore.updatedAt ? DateTime.fromISO(pageStore.updatedAt).toLocaleString(DateTime.DATETIME_MED) : 'N/A'
})

// WATCHERS

watch(() => route.path, async (newValue) => {
  // -> Ignore route change (e.g. from page create route fix)
  if (editorStore.ignoreRouteChange) {
    editorStore.$patch({ ignoreRouteChange: false })
    return
  }

  // -> Enter Create Mode?
  if (newValue.startsWith('/_create')) {
    if (!route.params.editor) {
      $q.notify({
        type: 'negative',
        message: 'No editor specified!'
      })
      return router.replace('/')
    }
    $q.loading.show()
    const pageCreateArgs = { editor: route.params.editor, fromNavigate: true }
    if (route.query.path) {
      pageCreateArgs.path = route.query.path
    }
    if (route.query.locale) {
      pageCreateArgs.locale = route.query.locale
    }
    await pageStore.pageCreate(pageCreateArgs)
    $q.loading.hide()
    return
  }

  // -> Enter Edit Mode?
  if (newValue.startsWith('/_edit')) {
    if (!route.params.pagePath) {
      return router.replace('/')
    }
    $q.loading.show()
    await pageStore.pageEdit({ path: route.params.pagePath, fromNavigate: true })
    $q.loading.hide()
    return
  }

  // -> Moving to a non-page path? Ignore
  if (newValue.startsWith('/_')) { return }

  // -> Load Page
  try {
    await pageStore.pageLoad({ path: newValue })
    if (editorStore.isActive) {
      editorStore.$patch({
        isActive: false
      })
    }
    // -> Load Blocks
    nextTick(() => {
      for (const block of pageContents.value.querySelectorAll(':not(:defined)')) {
        commonStore.loadBlocks([block.tagName.toLowerCase()])
      }
    })
  } catch (err) {
    if (err.message === 'ERR_PAGE_NOT_FOUND') {
      if (newValue === '/') {
        if (!userStore.authenticated) {
          router.push('/login')
        } else if (!userStore.can('write:pages')) {
          router.replace('/_error/unauthorized')
        } else {
          siteStore.overlay = 'Welcome'
        }
      } else {
        $q.notify({
          type: 'negative',
          message: 'This page does not exist (yet)!'
        })
      }
    } else {
      $q.notify({
        type: 'negative',
        message: err.message
      })
    }
  }
}, { immediate: true })

watch(() => pageStore.toc, () => { refreshTocExpanded() }, { immediate: true })
watch(() => pageStore.tocDepth, () => { refreshTocExpanded() })

// METHODS

function refreshTocExpanded (baseToc, lvl) {
  const toExpand = []
  let isRootNode = false
  if (!baseToc) {
    baseToc = pageStore.toc
    isRootNode = true
    lvl = 1
  }
  if (baseToc.length > 0) {
    for (const node of baseToc) {
      if (lvl >= pageStore.tocDepth.min && lvl < pageStore.tocDepth.max) {
        toExpand.push(node.key)
      }
      if (node.children?.length && lvl < pageStore.tocDepth.max - 1) {
        toExpand.push(...refreshTocExpanded(node.children, lvl + 1))
      }
    }
  }
  if (isRootNode) {
    state.tocExpanded = toExpand
  } else {
    return toExpand
  }
}
</script>

<style lang="scss">
.page-breadcrumbs {
  @at-root .body--light & {
    background: linear-gradient(to bottom, $grey-1 0%, $grey-3 100%);
    border-bottom: 1px solid $grey-4;
  }
  @at-root .body--dark & {
    background: linear-gradient(to bottom, $dark-3 0%, $dark-4 100%);
    border-bottom: 1px solid $dark-3;
  }
}
.page-header {
  height: 95px;

  @at-root .body--light & {
    background: linear-gradient(to bottom, $grey-2 0%, $grey-1 100%);
    border-bottom: 1px solid $grey-4;
    border-top: 1px solid #FFF;
  }
  @at-root .body--dark & {
    background: linear-gradient(to bottom, $dark-4 0%, $dark-3 100%);
    // border-bottom: 1px solid $dark-5;
    border-top: 1px solid $dark-6;
  }

  .no-height .q-field__control {
    height: auto;
  }

  &-title {
    @at-root .body--light & {
      color: $grey-9;
    }
    @at-root .body--dark & {
      color: #FFF;
    }
  }
  &-subtitle {
    @at-root .body--light & {
      color: $grey-7;
    }
    @at-root .body--dark & {
      color: rgba(255,255,255,.6);
    }
  }
}
.page-container {
  @at-root .body--light & {
    border-top: 1px solid #FFF;
  }
  // @at-root .body--dark & {
  //   border-top: 1px solid $dark-6;
  // }

  .page-container-scrl > .q-scrollarea__container > .q-scrollarea__content {
    width: 100%;
  }
}
.page-sidebar {
  flex: 0 0 300px;

  @at-root .body--light & {
    background-color: $grey-2;
  }
  @at-root .body--dark & {
    background-color: $dark-5;
  }

  .q-separator {
    background-color: rgba(0,0,0,.05);
    border-bottom: 1px solid;

    @at-root .body--light & {
      background-color: rgba(0,0,0,.05);
      border-bottom-color: #FFF;
    }
    @at-root .body--dark & {
      background-color: rgba(255,255,255,.04);
      border-bottom-color: #070a0d;
    }
  }
}

.floating-syncpanel {
  .q-dialog__inner {
    margin-top: 14px;
    right: 140px;
    left: auto;

    .q-card {
      border-radius: 17px;
    }
  }

  &-msg {
    padding-top: 1px;
    font-weight: 500;
    font-size: .75rem;
    padding-right: 16px;
    display: flex;
    align-items: center;
  }
}

.q-card {
  @at-root .body--light & {
    background-color: #FFF;
  }
  @at-root .body--dark & {
    background-color: $dark-3;
  }
}

.page-toc {
  &.q-tree--dense .q-tree__node {
    padding-bottom: 5px;
  }
}
</style>
