<script setup lang="ts">
import { ref } from 'vue'
import { createErrorBlock, createXamlBlock, type Xaml } from '@/components/xaml-block.tsx'

const showModal = defineModel('showModal', { required: true })

const mode = ref<'xaml' | 'visual'>('xaml')
const xamlContent = ref('')

/**
 * 目前使用的是芒果手搓的一个极简 xaml 解析函数，不会语法验证，也不支持任何高级的 xaml 特性，甚至在遇到错误时不会报错而只是循环下去。
 * 以后会尝试搓一个更厉害的，或者用上一个更厉害的方案。目前版本仅作原理验证。
 */

// 记录循环次数，在循环次数异常大时直接结束解析
let count_ = 0

function parseXamlsContent(content: string): Xaml[] {
  const final_xamls: Xaml[] = []

  let content_ = content
  while (content_.indexOf('<') >= 0) {
    count_ += 1
    if (count_ > 100) {
      throw TypeError('Xaml 解析循环超过上限次数，已终止。')
    }

    console.log(`(${count_})[接下来] ${content_}`)
    const first_tag_start_start = content_.indexOf('<')
    const first_tag_start_end = content_.indexOf('>')
    const first_tag_start = content_.slice(first_tag_start_start, first_tag_start_end + 1)
    const first_tag_name = content_.slice(first_tag_start_start + 1, first_tag_start_end)

    const first_tag_end_start = content_.search(`</${first_tag_name}>`)
    const first_tag_end_end = first_tag_end_start + first_tag_name.length + 2
    const first_tag_end = content_.slice(first_tag_end_start, first_tag_end_end + 1)

    console.log(
      `(${count_})[解析标签] ${first_tag_start} ${first_tag_end} (${first_tag_start_start}/${first_tag_start_end} - ${first_tag_end_start}/${first_tag_end_end})`,
    )

    const sub_content_ = content_.slice(first_tag_start_end + 1, first_tag_end_start)

    if (sub_content_.indexOf('<') >= 0) {
      final_xamls.push({
        name: first_tag_name,
        message: sub_content_.slice(0, sub_content_.indexOf('<')),
        subXamls: parseXamlsContent(sub_content_.slice(sub_content_.indexOf('<'))),
      })
    } else {
      final_xamls.push({
        name: first_tag_name,
        message: sub_content_,
        subXamls: [],
      })
    }

    content_ = content_.slice(first_tag_end_end + 1)
  }

  return final_xamls
}
</script>

<template>
  <n-modal
    v-model:show="showModal"
    title="Xaml 可视化"
    preset="card"
    content-scrollable
    style="height: 60vh; width: 50vw"
    :z-index="999"
    draggable
  >
    <n-flex vertical>
      <n-radio-group v-model:value="mode">
        <n-radio-button value="xaml">Xaml</n-radio-button>
        <n-radio-button value="visual">可视化</n-radio-button>
      </n-radio-group>

      <n-alert v-if="mode === 'xaml'" type="info">
        Xaml 格式的提示词便于简洁地向 AI 提供复杂的设定。你也可以不使用 Xaml 格式。<br />
        你可以拖动此模态框，但不允许在保持本窗口开启的状态下从遮罩下方复制代码……
      </n-alert>
      <n-input v-model:value="xamlContent" v-if="mode === 'xaml'" type="textarea" :rows="10" />

      <component
        v-if="mode === 'visual'"
        :is="
          () => {
            count_ = 0
            try {
              return createXamlBlock(parseXamlsContent(xamlContent))
            } catch (err) {
              return createErrorBlock(err!.toString())
            }
          }
        "
      />
    </n-flex>
  </n-modal>
</template>

<style scoped></style>
