<template>
    <div :class="`${prefix}-scrollbar`"
         :style="jddScrollStyle"
         @mouseenter="handleMouseEnter"
         @mouseleave="handleMouseLeave"
         @mousewheel="handleMouseWheel">
        <!--
             @mousedown="handleThumbMouseDown"
         @mousemove="handleThumbMouseMove"
         @mouseup="handleThumbMouseUp">
-->
        <div ref="container"
             :class="`${prefix}-scrollbar-container`"
             :style="{...containerStyle,...containerOffsetStyle}">
            <slot></slot>
        </div>
        <div v-if="showHorizontal"
             :class="`${prefix}-scrollbar--horizontal`">
            <div :class="`${prefix}-scrollbar-thumb ${prefix}-scrollbar--horizontal-thumb`"
                 :style="horizontalThumbStyle"></div>
        </div>
        <div v-if="showVertical"
             :class="`${prefix}-scrollbar--vertical`">
            <div :class="`${prefix}-scrollbar-thumb ${prefix}-scrollbar--vertical-thumb`"
                 :style="verticalThumbStyle"></div>
        </div>
    </div>
</template>

<script>
import { prefix, stylePrefix, prefixMixins, on, off } from 'jdd-design/utils';
import { debounce, throttle } from 'throttle-debounce';
export default {
    name: `${prefix}-scrollbar`,
    mixins: [prefixMixins],
    props: {
        width: Number,
        height: Number,
        offset: {
            type: Number,
            default: 10
        }
    },
    data() {
        return {
            horizontalThumbWidth: null,
            verticalThumbHeight: null,
            containerStyle: null,
            x: 0,
            y: 0,
            top: 0,
            left: 0,
            clientX: 0,
            clientY: 0,
            hasHorizontal: false,
            hasVertical: false,
            show: false,
            realSize: {
                width: this.width,
                height: this.height
            },
            dragHorizontal: false,
            dragVertical: false
        };
    },
    computed: {
        jddScrollStyle() {
            let { width, height } = this.realSize;
            return {
                width: `${width}px`,
                height: `${height}px`
            };
        },
        horizontalThumbStyle() {
            return {
                width: `${this.horizontalThumbWidth}px`,
                left: `${this.left}px`
            };
        },
        verticalThumbStyle() {
            return {
                height: `${this.verticalThumbHeight}px`,
                top: `${this.top}px`
            };
        },
        containerOffsetStyle() {
            return {
                paddingRight: this.hasVertical ? `${this.offset}px` : 0,
                paddindBottom: this.hasHorizontal ? `${this.offset}px` : 0
            };
        },
        showHorizontal() {
            return (this.show && this.hasHorizontal) || this.dragHorizontal;
        },
        showVertical() {
            return (this.show && this.hasVertical) || this.dragVertical;
        }
    },
    methods: {
        handleMouseEnter() {
            this.show = true;
            this.realSize = this.getRealSize();
        },
        handleMouseLeave() {
            this.show = false;
        },
        handleMouseWheel(evt) {
            let { height } = this.realSize;
            evt.preventDefault();
            this.y -= evt.deltaY;

            if (this.y > 0) {
                this.y = 0;
            } else if (this.y < height - this.containerRect.height) {
                this.y = height - this.containerRect.height;
            }
            this.top =
                ((height - this.verticalThumbHeight - 10) * this.y) /
                (height - this.containerRect.height);
            this.containerStyle = {
                transform: `translateY(${this.y}px)`
            };
            this.$emit('v-scroll', this);
        },
        handleThumbMouseDown(evt) {
            evt.preventDefault();
            evt.stopPropagation();
            this.clientX = evt.clientX;
            this.clientY = evt.clientY;
            if (
                this.getCloest(evt.target, `${prefix}-scrollbar`) === this.$el
            ) {
                if (evt.target.className.indexOf('vertical-thumb') > -1) {
                    this.dragVertical = true;
                } else if (
                    evt.target.className.indexOf('horizontal-thumb') > -1
                ) {
                    this.dragHorizontal = true;
                }
            }
        },
        getCloest(node, cls) {
            if (node.className.split(' ').indexOf(cls) > -1) {
                return node;
            }
            if (node == document.body) {
                return null;
            }
            while (node.parentNode) {
                return this.getCloest(node.parentNode, cls);
            }
        },
        handleThumbMouseMove(evt) {
            evt.preventDefault();
            let { width, height } = this.realSize;
            let style = {};
            if (this.dragVertical) {
                let offsetY = evt.clientY - this.clientY;
                this.top += offsetY;
                this.clientY = evt.clientY;
                if (this.top < 0) {
                    this.top = 0;
                } else if (this.top > height - this.verticalThumbHeight - 10) {
                    this.top = height - this.verticalThumbHeight - 10;
                }
                this.y =
                    (this.top * (height - this.containerRect.height)) /
                    (height - this.verticalThumbHeight - 10);

                style[stylePrefix('transform')] = `translate(${this.x}px,${
                    this.y
                }px)`;
                this.containerStyle = style;
                debugger;
                this.$emit('v-scroll', this);
            } else if (this.dragHorizontal) {
                let offsetX = evt.clientX - this.clientX;
                this.left += offsetX;
                this.clientX = evt.clientX;
                if (this.left < 0) {
                    this.left = 0;
                } else if (this.left > width - this.horizontalThumbWidth - 10) {
                    this.left = width - this.horizontalThumbWidth - 10;
                }
                this.x =
                    (this.left * (width - this.containerRect.width)) /
                    (width - this.horizontalThumbWidth - 10);

                style[stylePrefix('transform')] = `translate(${this.x}px,${
                    this.y
                }px)`;
                this.containerStyle = style;
                this.$emit('h-scroll', this);
            }
        },
        handleThumbMouseUp(evt) {
            evt.preventDefault();
            this.$set(this, 'dragVertical', false);
            this.$set(this, 'dragHorizontal', false);
        },
        scrollTo(pos) {
            this.x = -pos.x || 0;
            this.y = -pos.y || 0;
            let { height } = this.realSize;
            this.containerStyle = {
                transform: `translate(${this.x}px,${this.y}px)`,
                transition: 'all .3s'
            };
            this.top =
                ((height - this.verticalThumbHeight - 10) * this.y) /
                (height - this.containerRect.height);
        },
        getRealSize() {
            this.boxRect = this.$el.getBoundingClientRect();
            this.realSize.width =
                this.width || (this.boxRect && this.boxRect.width);
            this.realSize.height =
                this.height || (this.boxRect && this.boxRect.height);
            return this.realSize;
        },
        bindEvent() {
            on(document, 'mousedown', this.handleThumbMouseDown);
            on(document, 'mousemove', this.handleThumbMouseMove);
            on(document, 'mouseup', this.handleThumbMouseUp);
        },
        unBindEvent() {
            off(document, 'mousedown', this.handleThumbMouseDown);
            off(document, 'mousemove', this.handleThumbMouseMove);
            off(document, 'mouseup', this.handleThumbMouseUp);
        }
    },
    mounted() {
        this.bindEvent();
        this.$nextTick(() => {
            this.realSize = this.getRealSize();
            let { width, height } = this.realSize;
            this.containerRect = {
                width: this.$refs.container.scrollWidth,
                height: this.$refs.container.scrollHeight
            };
            if (height) {
                let heightScale = height / this.containerRect.height;
                if (heightScale < 1) {
                    this.hasVertical = true;
                    this.verticalThumbHeight = (height - 10) * heightScale;
                }
            }
            if (width) {
                let widthScale = width / this.containerRect.width;
                if (widthScale < 1) {
                    this.hasHorizontal = true;
                    this.horizontalThumbWidth = (width - 10) * widthScale;
                }
            }
        });
    },
    beforeDestroy() {
        this.unBindEvent();
    },
    beforeCreate() {
        if (this.$isServer) return;
        let tmpFunc = this.handleMouseWheel;
        this.handleMouseWheel = throttle(200, args => {
            tmpFunc(args);
        });
    }
};
</script>
