/**
 * 复杂模式
 * @author xiufu.wang
 */
import {
    getLineHeight,
    registerWordBreak,
    getElementHeight,
    setWordBreak,
    isString,
    wrapTextChildNodesWithSpan,
    binarySearch
} from './util'
import ProResizeObserver from 'mars-pro/packages/pro-resize-observer'
import showTooltipMore from './mixins/show-tooltip-more'

export default {
    name: 'js-ellipsis-impl',
    mixins: [showTooltipMore],
    components: {
        ProResizeObserver
    },
    created() {
        this.jsimpl = true
    },
    props: {
        /**
         * 内容:可以是富文本(仅当useRichText才有效)、普通文本
         */
        text: String,
        // 当true时,则代表text为富文本
        useRichText: {
            type: Boolean,
            default: false
        },
        // 最大行数
        maxLines: {
            type: Number,
            default: 1
        },
        //可以精确指定高度
        maxHeight: Number,
        //是否启用
        ellipsis: {
            type: Boolean,
            default: true
        }
    },
    computed: {
        forceUpdate() {
            return [this.text, this.useRichText, this.maxLines, this.maxHeight]
        },
        ellipsisRef() {
            return this.$refs.ellipsisRef
        },
        ref() {
            return this.$refs.contaner
        },
        textRef() {
            return this.$refs.textRef
        }
    },
    watch: {
        forceUpdate() {
            this.resolveEllipsis()
        }
    },
    methods: {
        resolveEllipsis() {
            //临时隐藏: 便于计算文本或富文本高度
            this.ellipsisRef.style.display = "none";
            //插入内容
            if (this.useRichText) {
                this.textRef.innerHTML = this.text;
            } else {
                this.textRef.innerText = this.text;
            }

            //获取行高
            if (!this.ellipsis) {
                return
            }

            //获取行高
            const lineHeight = getLineHeight(this.ref);
            // 临时注入 break-word属性
            const wordBreak = registerWordBreak(this.textRef);
            //获取最大高度
            let maxHeight;
            if (this.maxLines || this.maxHeight) {
                maxHeight = this.maxHeight || (this.maxLines * lineHeight)
            } else {
                return
            }
            // 插入内容后 、获取容器的高度
            const height = getElementHeight(this.ref);
            // height 小于 maxHeight不需要做任何处理，并且提交reflow事件
            if (height <= maxHeight) {
                if (isString(wordBreak)) {
                    setWordBreak(this.textRef, wordBreak);
                }
                this.$emit('reflow', false)
                return
            }

            // 显示ellipsis
            this.ellipsisRef.style.display = "inline";

            if (this.useRichText) {
                //处理富文本:将所有的文本节点包裹span元素
                wrapTextChildNodesWithSpan(this.textRef);
                this.truncateHTML(this.ref, this.textRef, maxHeight);
            } else {
                this.truncateText(this.ref, this.textRef, maxHeight);
            }

            if (isString(wordBreak)) {
                setWordBreak(this.textRef, wordBreak);
            }
        },
        //截断富文本
        truncateHTML(container, textContainer, maxHeight) {
            const children = textContainer.childNodes;
            if (children.length === 1) {
                const node = children[0];
                if (node.nodeType === Node.TEXT_NODE) {
                    this.truncateText(container, textContainer, maxHeight);
                } else {
                    const html = node.innerHTML;
                    node.innerHTML = "";
                    const height = getElementHeight(container);
                    if (height > maxHeight) {
                        textContainer.removeChild(node);
                        this.$emit('reflow', true)
                        return;
                    }
                    node.innerHTML = html;
                    this.truncateHTML(container, node, maxHeight);
                }
            } else {
                const nodes = [].slice.call(children);
                const _nodes = [];
                let i = 0;
                binarySearch(
                    0,
                    nodes.length,
                    //计算
                    (l, r, m) => {
                        //清空文本内容
                        textContainer.innerHTML = "";
                        const currentNodes = nodes.slice(l, m);
                        _nodes.forEach((node) => {
                            textContainer.appendChild(node);
                        });
                        currentNodes.forEach((node) => {
                            textContainer.appendChild(node);
                        });
                        const height = getElementHeight(container);
                        const isExceededMaximun = height > maxHeight;
                        if (!isExceededMaximun) {
                            currentNodes.forEach((node) => {
                                _nodes.push(node);
                            });
                        }
                        return isExceededMaximun;
                    },
                    // 计算值
                    (l, r, m) => {
                        if (l === m) {
                            const height = getElementHeight(container);
                            // 高度 > 最大高度
                            const isExceededMaximun = height > maxHeight;
                            i = m;
                            if (!isExceededMaximun) {
                                textContainer.appendChild(nodes[i]);
                            }
                            return true;
                        }
                        return false;
                    }
                );
                if (textContainer.childNodes[i]) {
                    this.truncateHTML(
                        container,
                        textContainer.childNodes[i],
                        maxHeight
                    );
                }
            }
        },
        //截断文本格式
        truncateText(container, textContainer, maxHeight) {
            const text = textContainer.textContent || "";
            let currentText = "";
            binarySearch(0, text.length, (l, r, m) => {
                const temp = text.slice(l, m);
                textContainer.innerText = currentText + temp;
                const height = getElementHeight(container);
                const isExceededMaximun = height > maxHeight;
                if (!isExceededMaximun) {
                    currentText += temp;
                }
                return isExceededMaximun;

            }, (l, r, m) => l === m)
            textContainer.innerText = currentText;
            this.$emit('reflow', true)
        },
        handEllipsisClick() { 
            this.$emit('more')
        }
    },
    render() {
        return (
            <ProResizeObserver on-resize={this.resolveEllipsis}>
                <div ref="contaner" {
                    ...({
                        on: {
                            mouseenter: this.handleMouseenter,
                            mouseleave: this.handleMouseleave,
                            click: this.handleMouseleave
                        }
                    })
                }>
                    {/* 内容 */}
                    <span ref="textRef" class="content"></span>
                    {/* 更多dom */}
                    <span ref="ellipsisRef" class="ellipsis" on-click={this.handEllipsisClick}>
                        {this.$slots.ellipsisNode || '...'}
                    </span>
                </div>
            </ProResizeObserver>
        )
    },
    mounted() {
        this.resolveEllipsis()
    }
}