<template>
  <div class="w-full relative mt-8px" :class="{ 'mt-18px': useSymbol || supportLangues }">
    <el-input
      ref="textareaRef"
      type="textarea"
      spellcheck="false"
      v-model="modelValue"
      placeholder="请输入内容"
      :rows="rows"
      v-bind="$attrs"
      @focus="syncSelection"
      @click="syncSelection"
      @keyup="syncSelection"
    />
    <LuSmilePlus
      v-if="useSymbol"
      size="12px"
      class="cursor-pointer absolute top--16px right-0px"
      @click="handleOpenSymbolModal"
    />
    <LuLanguages
      v-if="supportLangues"
      size="12px"
      class="cursor-pointer absolute top--16px right-20px"
      @click="handleOpenLanguageModal"
    />
  </div>
  <SymbolSelectModal v-if="useSymbol" ref="symbolModalRef" @select="handleSelectSymbol" />
  <LanguageSelectModal
    v-if="supportLangues"
    ref="languageModalRef"
    @select="handleSelectLanguage"
  />
</template>

<script setup lang="ts">
import { nextTick, ref } from 'vue'
import { LuLanguages, LuSmilePlus } from 'vue-icons-plus/lu'
import SymbolSelectModal from './SymbolSelectModal.vue'
import LanguageSelectModal from './LanguageSelectModal.vue'

defineProps<{
  useSymbol?: boolean
  rows?: number
  supportLangues?: boolean
}>()

const modelValue = defineModel<string>('modelValue')
const textareaRef = ref()
const symbolModalRef = ref<InstanceType<typeof SymbolSelectModal>>()
const languageModalRef = ref<InstanceType<typeof LanguageSelectModal>>()
const selection = ref({
  start: 0,
  end: 0
})

const getTextareaElement = () => {
  const inputInstance = textareaRef.value as any
  return inputInstance?.textarea || inputInstance?.input || null
}

const syncSelection = () => {
  const textareaEl = getTextareaElement()
  if (!textareaEl) return

  selection.value = {
    start: textareaEl.selectionStart ?? 0,
    end: textareaEl.selectionEnd ?? textareaEl.selectionStart ?? 0
  }
}

const handleOpenSymbolModal = () => {
  syncSelection()
  symbolModalRef.value?.open()
}

const handleOpenLanguageModal = () => {
  syncSelection()
  languageModalRef.value?.open()
}

const handleSelectSymbol = (val: string) => {
  if (val) {
    insertContent(`{${val}}`)
  }
}

const handleSelectLanguage = (languageKey: string) => {
  if (languageKey) {
    insertContent(`#{${languageKey}}`)
  }
}

const insertContent = async (content: string) => {
  const currentValue = String(modelValue.value ?? '')
  const start = selection.value.start ?? currentValue.length
  const end = selection.value.end ?? start

  modelValue.value = `${currentValue.slice(0, start)}${content}${currentValue.slice(end)}`

  await nextTick()

  const nextPosition = start + content.length
  const textareaEl = getTextareaElement()
  textareaEl?.focus?.()
  textareaEl?.setSelectionRange?.(nextPosition, nextPosition)
  selection.value = {
    start: nextPosition,
    end: nextPosition
  }
}
</script>
