<template>
  <div class="language-input relative w-full">
    <el-input
      ref="inputRef"
      v-model="modelValue"
      spellcheck="false"
      :type="type"
      :rows="rows"
      v-bind="$attrs"
      @focus="syncSelection"
      @click="syncSelection"
      @keyup="syncSelection"
      @mouseup="syncSelection"
    />
    <LuLanguages
      size="12px"
      class="absolute cursor-pointer text-#909399 hover:text-#409eff"
      :class="type === 'textarea' ? 'right-8px top-8px' : 'right-8px top-1/2 -translate-y-1/2'"
      @click.stop="handleOpenLanguageModal"
    />
  </div>
  <LanguageSelectModal ref="languageModalRef" @select="handleSelectLanguage" />
</template>

<script setup lang="ts">
import { nextTick, ref } from 'vue'
import { LuLanguages } from 'vue-icons-plus/lu'
import LanguageSelectModal from '@/views/designer/config/property/components/LanguageSelectModal.vue'

withDefaults(
  defineProps<{
    type?: 'text' | 'textarea'
    rows?: number
  }>(),
  {
    type: 'text',
    rows: 2
  }
)

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

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

const syncSelection = () => {
  const inputEl = getInputElement()
  if (!inputEl) return

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

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

const handleSelectLanguage = (languageKey: string) => {
  if (!languageKey) return
  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 inputEl = getInputElement()
  inputEl?.focus?.()
  inputEl?.setSelectionRange?.(nextPosition, nextPosition)
  selection.value = {
    start: nextPosition,
    end: nextPosition
  }
}
</script>

<style scoped lang="less">
.language-input {
  ::v-deep(.el-input__wrapper) {
    padding-right: 24px;
  }

  ::v-deep(.el-textarea__inner) {
    padding-right: 24px;
  }
}
</style>
