<template>
    <div contenteditable @input="onchange" ref="text" v-html="rawhtml(value)">
    </div>
</template>

<script>
export default {
    name: 'FormatedText',
    props: {
        value: {
            type: String,
            required: true
        },
        format: {
            type: Function,
            default: null
        }
    },
    data() {
        return {
            selection: {start: 0, end: 0}
        };
    },
    emits: ['input'],
    methods: {
        rawhtml(value) {
            if (typeof this.format === 'function') {
                return this.format(value);
            } else {
                return value;
            }
        },
        onchange(event) {
            const div = this.$refs.text;
            const sel = window.getSelection();
            if (sel.rangeCount > 0) {
                this.selection.start = this.calculateOffset(div, sel.anchorNode, sel.anchorOffset);
                this.selection.end = this.calculateOffset(div, sel.focusNode, sel.focusOffset);
            }
            this.$emit('input', event.target.innerText);
        },
        calculateOffset(container, node, offset) {
            let position = 0;
            let found = false;
            const walk = (node) => {
                if (node === container) {
                    found = true;
                    return;
                }
                if (node.nodeType === 3) {
                    position += node.length;
                } else {
                    for (let i = 0; i < node.childNodes.length; i++) {
                        walk(node.childNodes[i]);
                        if (found) {
                            return;
                        }
                    }
                }
            };
            walk(node);
            return position + offset;
        }
    },
    watch: {
        value() {
            if (this.selection) {
                const div = this.$refs.text;
                const range = document.createRange();
                console.log(this.selection);
                range.setStart(div, Math.min(this.selection.anchorOffset, this.value.length));
                range.setEnd(div, Math.min(this.selection.focusOffset, this.value.length));
                this.selection.removeAllRanges();
                this.selection.addRange(range);
            }
        }
    }
};
</script>