<script setup lang="ts">
import type { BlockData } from '@vigilkids/section-core'

import { computed } from 'vue'

import { useInlineEdit } from '../../../composables/useInlineEdit'

interface TocGroup {
  id: string
  text: string
  anchor: string
  children: { id: string, text: string, anchor: string, hot: boolean }[]
}

const props = defineProps<{
  blockOrder: string[]
  blocks: Record<string, BlockData>
  editorMode?: boolean
  settings: Record<string, unknown>
}>()

const emit = defineEmits<{
  (e: 'update:setting', key: string, value: unknown): void
  (e: 'update:block-setting', blockId: string, key: string, value: unknown): void
  (e: 'inline-edit-start', key: string): void
  (e: 'inline-edit-end'): void
  (e: 'undo-redo', action: 'redo' | 'undo'): void
}>()

const title = computed(() => String(props.settings.title || 'Table Of Contents'))

const tocGroups = computed<TocGroup[]>(() => {
  const groups: TocGroup[] = []

  for (const blockId of props.blockOrder) {
    const block = props.blocks[blockId]
    if (!block)
      continue

    if (block.type === 'toc-h2') {
      groups.push({
        id: blockId,
        text: String(block.settings.text || ''),
        anchor: String(block.settings.anchor || ''),
        children: [],
      })
    }
    else if (block.type === 'toc-h3' && groups.length > 0) {
      groups[groups.length - 1]!.children.push({
        id: blockId,
        text: String(block.settings.text || ''),
        anchor: String(block.settings.anchor || ''),
        hot: Boolean(block.settings.hot),
      })
    }
  }

  return groups
})

const { editableAttrs } = useInlineEdit({
  editorMode: () => !!props.editorMode,
  onSettingUpdate: (key, value) => emit('update:setting', key, value),
  onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
  onEditStart: key => emit('inline-edit-start', key),
  onEditEnd: () => emit('inline-edit-end'),
  onUndoRedo: action => emit('undo-redo', action),
})
</script>

<template>
<div class="blog-toc">
    <div class="blog-toc-header">
      <!-- #triangle-full -->
      <svg
        class="blog-toc-icon"
        width="16"
        height="16"
        viewBox="0 0 20 20"
        fill="none"
        xmlns="http://www.w3.org/2000/svg"
      >
        <mask
          id="triangle-full-mask0"
          style="mask-type: alpha"
          maskUnits="userSpaceOnUse"
          x="0"
          y="0"
          width="20"
          height="20"
        >
          <rect width="20" height="20" fill="#D9D9D9" />
        </mask>
        <g mask="url(#triangle-full-mask0)">
          <path
            d="M8.43188 5.98075C9.23262 4.96929 10.7673 4.96929 11.5681 5.98075L16.9339 12.7586C17.9719 14.0697 17.0381 16 15.3658 16H4.6342C2.96193 16 2.02812 14.0697 3.0661 12.7586L8.43188 5.98075Z"
            fill="black"
          />
        </g>
      </svg>
      <h2 class="blog-toc-title" v-bind="editableAttrs('title')">
        {{ title }}
      </h2>
    </div>

    <ul class="blog-toc-list">
      <template v-for="group in tocGroups" :key="group.id">
        <li v-if="group.children.length === 0" class="blog-toc-list-item">
          <a :href="`#${group.anchor}`" class="blog-toc-link">{{ group.text }}</a>
        </li>

        <li v-else class="blog-toc-list-item">
          <a :href="`#${group.anchor}`" class="blog-toc-link">{{ group.text }}</a>
          <ol class="blog-toc-numbered-list">
            <li v-for="child in group.children" :key="child.id">
              <div class="blog-toc-numbered-item">
                <a :href="`#${child.anchor}`" class="blog-toc-link">
                  <span>{{ child.text }}</span>
                </a>
                <div v-if="child.hot" class="blog-toc-hot-tag-wrapper">
                  <!-- #hot-tag -->
                  <svg
                    class="blog-toc-hot-tag-bg"
                    viewBox="0 0 23 12"
                    fill="none"
                    xmlns="http://www.w3.org/2000/svg"
                  >
                    <path
                      d="M19.3997 0C21.0565 0 22.3997 1.34315 22.3997 3V9C22.3997 10.6569 21.0565 12 19.3997 12H4.39966C2.7428 12 1.39966 10.6569 1.39966 9V6.42188L0.300049 5.78711C-0.0999011 5.55615 -0.0999345 4.97898 0.300049 4.74805L1.39966 4.11328V3C1.39966 1.34315 2.7428 7.24787e-08 4.39966 0H19.3997Z"
                      fill="#FF0000"
                    />
                  </svg>
                  <span class="blog-toc-hot-tag-text">HOT</span>
                </div>
              </div>
            </li>
          </ol>
        </li>
      </template>
    </ul>
  </div>
</template>

<style scoped>
.blog-toc{background:#f7f8fa;border-radius:10px;margin-top:40px;padding:20px 16px}.blog-toc-header{align-items:center;display:flex;gap:8px;margin-bottom:16px}.blog-toc-icon{flex-shrink:0;height:16px;width:16px}.blog-toc-title{color:#000;font-size:16px;font-weight:600;margin:0}.blog-toc-list{color:#000;font-size:14px;list-style:none;margin:0;padding:0}.blog-toc-list-item{list-style-position:inside;list-style-type:disc;padding-left:8px}.blog-toc-list-item+.blog-toc-list-item{margin-top:8px}.blog-toc-numbered-list{font-size:12px;font-weight:300;margin-top:8px;padding-left:36px}.blog-toc-numbered-list,.blog-toc-numbered-list>li{list-style-position:outside;list-style-type:decimal}.blog-toc-numbered-list>li{display:list-item}.blog-toc-numbered-list>li+li{margin-top:8px}.blog-toc-numbered-item{align-items:center;display:flex;gap:8px}.blog-toc-link{color:inherit;text-decoration:none}.blog-toc-hot-tag-wrapper{align-items:center;display:flex;gap:4px;position:relative}.blog-toc-hot-tag-bg{min-height:12px;min-width:22px;position:absolute;width:100%}.blog-toc-hot-tag-text{color:#fff;font-family:Roboto,sans-serif;font-size:12px;font-style:italic;font-weight:900;position:relative;transform:scale(.75);transform-origin:center}@media (min-width:768px){.blog-toc{border-radius:20px;padding:40px 32px}.blog-toc-title{font-size:20px}.blog-toc-list,.blog-toc-numbered-list{font-size:14px}}@media (max-width:639px){.blog-toc-list{font-size:14px}.blog-toc-numbered-list{font-size:12px}}
</style>
