<template>
  <div
    ref="boxRef"
    :style="styleMap?.mainStyle"
    class="w-full h-full relative overflow-hidden box-border flex items-start"
    :class="
      styleMap?.mainStyle?.textAlign === 'left'
        ? 'justify-start'
        : styleMap?.mainStyle?.textAlign === 'right'
          ? 'justify-end'
          : 'justify-center'
    "
  >
    <ImageBg :src="styleMap?.mainStyle?.imageSrc" :imageStyle="styleMap?.mainStyle?.imageStyle" />
    <span
      ref="txtRef"
      class="z-2 lv_label_txt break-all whitespace-pre-wrap"
      :style="textStyle"
      v-html="innerText"
    ></span>
  </div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
import { symbols } from '@/constants'
import { useWidgetStyle } from '../hooks/useWidgetStyle'
import ImageBg from '../ImageBg.vue'
import { useLongMode } from '../hooks/useLongMode'
import { useLanguage } from '../hooks/useLanguage'

const props = defineProps<{
  width: number
  height: number
  text?: string
  styles: any
  state?: string
  part?: string
  longMode?: 'circular' | 'clip' | 'dot' | 'scroll' | 'wrap'
  lightStart?: number
  lightEnd?: number
}>()

const txtRef = ref<HTMLSpanElement>()
const boxRef = ref<HTMLDivElement>()
const { resolveText, getTextStyle } = useLanguage()

/**
 * 高亮文本
 * @param html
 * @param start
 * @param end
 */
const highlight = (html: string, start: number, end: number): string => {
  if (start >= end || start < 0 || end < 0) {
    return html
  }

  let result = ''
  let charIndex = 0 // 字符计数（每个<i>标签算一个字符）
  let i = 0 // HTML 字符串索引

  // 第一部分：高亮开始之前的内容
  while (i < html.length && charIndex < start) {
    if (html.substring(i, i + 3) === '<i ') {
      // 找到 <i> 标签开始
      const tagEnd = html.indexOf('</i>', i) + 4
      if (charIndex < start) {
        result += html.substring(i, tagEnd)
        i = tagEnd
        charIndex++
      }
    } else {
      if (charIndex < start) {
        result += html[i]
        i++
        charIndex++
      }
    }
  }

  // 第二部分：高亮内容
  result += '<span class="highlight">'

  while (i < html.length && charIndex < end) {
    if (html.substring(i, i + 3) === '<i ') {
      // 处理 <i> 标签
      const tagEnd = html.indexOf('</i>', i) + 4
      result += html.substring(i, tagEnd)
      i = tagEnd
      charIndex++
    } else {
      result += html[i]
      i++
      charIndex++
    }
  }

  result += '</span>'

  // 第三部分：高亮之后的内容
  while (i < html.length) {
    result += html[i]
    i++
  }

  return result
}

// 处理symbol图标
const normalizeLineBreaks = (text: string) => text.replace(/\\r\\n|\\n|\\r/g, '\n')

const innerText = computed(() => {
  const text = normalizeLineBreaks(resolveText(props.text, true).text)
  const pattern = /\{LV[^}]*\}/g
  const matches = text.match(pattern)
  const map: Record<string, string> = {}
  matches?.forEach((match) => {
    const key = match.replace('{', '').replace('}', '')
    const value = symbols.find((item) => item.label === key)?.value
    map[match] = value || match
  })

  let html = text.replace(pattern, (match) => `<i class="lvgl-icon not-italic" >${map[match]}</i>`)

  const l = props.lightStart ?? -1
  const r = props.lightEnd ?? -1
  const start = Math.min(l, r)
  const end = Math.max(l, r)
  // 高亮内容 tag内容算作一个字符
  if (start >= 0 && end >= 1) {
    html = highlight(html, start, end)
  }

  return html
})

const textStyle = getTextStyle(
  () => undefined,
  () => props.text
)

const styleMap = useWidgetStyle({
  widget: 'lv_label',
  props
})

useLongMode(txtRef, boxRef, props, { preserveLineBreaks: true })
</script>

<style scoped>
.lv_label_txt::-webkit-scrollbar {
  display: none;
}
:deep(.highlight) {
  background: white;
}
</style>
