<!--
  - Copyright (c) 2024 LangChat. TyCoding All Rights Reserved.
  -
  - Licensed under the GNU Affero General Public License, Version 3 (the "License");
  - you may not use this file except in compliance with the License.
  - You may obtain a copy of the License at
  -
  -     https://www.gnu.org/licenses/agpl-3.0.html
  -
  - Unless required by applicable law or agreed to in writing, software
  - distributed under the License is distributed on an "AS IS" BASIS,
  - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  - See the License for the specific language governing permissions and
  - limitations under the License.
  -->

<script lang="ts" setup>
import { computed, ref } from 'vue'
import { ElMessage } from 'element-plus'
import TextComponent from './TextComponent.vue'
import { copyToClip } from '@/utils/copy'

interface Props {
  dateTime?: string
  text?: string
  inversion?: boolean
  error?: boolean
  loading?: boolean
}

interface Emit {
  (ev: 'delete'): void
}

const props = defineProps<Props>()
const emit = defineEmits<Emit>()
const isHover = ref(false)
const textRef = ref<HTMLElement>()
const asRawText = ref(props.inversion)
const messageRef = ref<HTMLElement>()

const options = computed(() => {
  const common = [
    {
      label: '复制',
      key: 'copyText',
      icon: 'DocumentCopy'
    }
  ]

  if (!props.inversion) {
    common.push({
      label: asRawText.value ? '预览' : '显示原文',
      key: 'toggleRenderType',
      icon: asRawText.value ? 'View' : 'Document'
    })
  }

  return common
})

function handleSelect(key: 'copyText' | 'delete' | 'toggleRenderType') {
  switch (key) {
    case 'copyText':
      handleCopy()
      return
    case 'toggleRenderType':
      asRawText.value = !asRawText.value
      return
    case 'delete':
      emit('delete')
  }
}

async function handleCopy() {
  try {
    await copyToClip(props.text || '')
    ElMessage.success('复制成功')
  } catch {
    ElMessage.error('复制失败')
  }
}
</script>

<template>
  <div
    ref="messageRef"
    :class="[{ 'flex-row-reverse': inversion }]"
    class="flex w-full overflow-hidden"
  >
    <div
      :class="[inversion ? 'ml-2' : 'mr-2']"
      class="flex items-center justify-center bg-gray-200 flex-shrink-0 h-8 overflow-hidden rounded-full basis-8"
    >
      <el-icon v-if="inversion"><User /></el-icon>
      <el-icon v-else><Monitor /></el-icon>
    </div>
    <div :class="[inversion ? 'items-end' : 'items-start']" class="overflow-hidden text-sm">
      <p :class="[inversion ? 'text-right' : 'text-left']" class="text-xs text-[#b4bbc4]">
        {{ dateTime }}
      </p>
      <div
        @mouseover="isHover = true"
        @mouseleave="isHover = false"
        :class="[inversion ? 'flex-row-reverse' : 'flex-row']"
        class="flex items-end gap-1 mt-2 transition-all"
      >
        <TextComponent
          ref="textRef"
          :as-raw-text="asRawText"
          :error="error"
          :inversion="inversion"
          :loading="loading"
          :text="text"
        />
        <div class="flex flex-col transition-all w-[45px]">
          <div v-if="isHover" class="flex gap-1.5 flex-nowrap justify-end">
            <el-tooltip
              v-for="item in options"
              :key="item.key"
              :content="item.label"
              placement="top"
            >
              <el-button
                link
                :icon="item.icon"
                @click="handleSelect(item.key as any)"
                class="transition text-neutral-400 hover:text-neutral-800"
              />
            </el-tooltip>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
:deep(.el-button) {
  padding: 4px;
  height: auto;
}
</style>
