<template>
    <div ref="compRef" class="wq-text-ellipsis">
        <div v-if="!isExpanded" class="ellipsis-content">
            <span>{{ truncatedText }}</span>
            <slot v-if="textOver" name="ellipsis">
                <span>{{ ellipsis }}</span>
            </slot>
            <span v-if="textOver" class="show-more" @click="toggleExpand">
                <slot name="more">
                    {{ moreText }}
                </slot>
            </span>
        </div>
        <div v-else class="full-content">
            <span>{{ fullText }}</span>
            <span class="show-less" @click="toggleExpand">
                <slot name="less">
                    {{ lessText }}
                </slot>
            </span>
        </div>
    </div>
</template>

<script setup>
import { computed, reactive, ref, watch, nextTick } from 'vue';
import { useResizeObserver } from '@vueuse/core';
import { debounce } from 'lodash';

const props = defineProps({
    text: String,
    maxLines: {
        type: Number,
        default: 3
    },
    ellipsis: String,
    moreText: String,
    lessText: String
});

const compRef = ref(null);
const isExpanded = ref(false);
const truncatedText = ref(props.text);
const fullText = computed(() => props.text);
const textOver = computed(() => truncatedText.value !== fullText.value);
const ellipsis = props.ellipsis || '...';
const moreText = props.moreText || '展开';
const lessText = props.lessText || '收起';

const toggleExpand = () => {
    isExpanded.value = !isExpanded.value;
};

watch(
    fullText,
    (newValue) => {
        truncatedText.value = fullText.value;      isExpanded.value = false;
  },  {
        immediate: true,
    }
);

const isOver = () => {
    const { height, lineHeight } = getComputedStyle(compRef.value);
    return parseFloat(height) > props.maxLines * parseFloat(lineHeight);
};

const refresh = async () => {
    let left = 0;
    let right = props.text.length;
    while (left <= right) {
        const mid = Math.floor((left + right) / 2);
        truncatedText.value = props.text.slice(0, mid);
        await nextTick(() => {
            if (isOver()) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        });
    }
    truncatedText.value = props.text.slice(0, left - 1);
};

const init = () =>{
 if (!isExpanded.value) refresh();
};

const debounceInit = debounce(init, 50);
useResizeObserver(compRef, () => {
    debounceInit();
});
</script>

<style lang="scss" scoped>
.wq-text-ellipsis {
    position: relative;
    white-space: normal;
    word-break: break-all;

    .show-more,
    .show-less {
        cursor: pointer;
        color: rgb(20, 127, 111);
        margin-left: 2px;
    }

    .ellipsis-content {
        position: relative;
    }
}
</style>