<template>
    <view class="range-slider" catchtap :style="'width:calc(' + contentWidth + ' - 40px);height:' + height + 'px'">
        <view class="range-bar" catchtap :style="'width:calc(' + width + 'rpx - 20rpx);height:' + 8 + 'rpx'">
            <view class="range-bar-bg" :style="'background-color:' + backgroundColor + ';margin-left:10px'"></view>
            <view class="range-bar-progress" :style="'margin-left:' + progressBarLeft + 'rpx;width:' + progressBarWidth + 'rpx;background-color:' + activeColor"></view>
        </view>
        <view
            class="block"
            :style="'margin-left:' + minBlockLeft + 'rpx'"
            @touchstart.stop.prevent="onBlockTouchStartFun"
            @touchmove.stop.prevent="onBlockTouchMoveFun"
            @touchend.stop.prevent="onBlockTouchEndFun"
            :data-left="minBlockLeft"
            data-tag="minBlock"
        >
            <slot name="minBlock"></slot>
        </view>
        <view
            class="block"
            :style="'margin-left:' + maxBlockLeft + 'rpx'"
            @touchstart.stop.prevent="onBlockTouchStartFun"
            @touchmove.stop.prevent="onBlockTouchMoveFun"
            @touchend.stop.prevent="onBlockTouchEndFun"
            :data-left="maxBlockLeft"
            data-tag="maxBlock"
        >
            <slot name="maxBlock"></slot>
        </view>
    </view>
</template>

<script>
const _windowWidth = uni.getSystemInfoSync().windowWidth;
export default {
    data() {
        return {
            MAX_LENGTH: 700,
            minBlockLeft: 0,
            maxBlockLeft: 700,
            progressBarLeft: 0,
            progressBarWidth: 700,
            fangdou: true
        };
    },
    props: {
        //组件宽度
        width: {
            type: Number,
            default: 700
        },
        contentWidth: {
            type: String,
            default: '100vw'
        },
        //组件高度
        height: {
            type: Number,
            default: 100
        },
        //滑块大小
        blockSize: {
            type: Number,
            default: 60
        },
        //区间进度条高度
        barHeight: {
            type: Number,
            default: 10
        },
        //背景条颜色
        backgroundColor: {
            type: String,
            default: '#e9e9e9'
        },
        //已选择的颜色
        activeColor: {
            type: String,
            default: '#E5EDFF'
        },
        //最小值
        min: {
            type: Number,
            default: 0
        },
        //最大值
        max: {
            type: Number,
            default: 100
        },
        //设置初始值
        values: {
            type: Object,
            default: () => [0, 100]
        }
    },
    mounted() {
        // 处理小程序 ready 生命周期
        this.$nextTick(() => this.ready());
    },
    options: {
        multipleSlots: true
    },
    methods: {
        /**
         * 组件生命周期函数，在组件布局完成后执行
         */
        ready() {
            // console.log(this.data.activeColor);
            // console.log(this.data.width);
            this.setData({
                progressBarWidth: this.width
            });
            this.refreshFun();
        },

        pxToRpxFun: function (px) {
            return (750 * px) / _windowWidth;
        },

        onBlockTouchStartFun: function (e) {
            console.log(e);
            this._blockDownX = e.changedTouches[0].pageX;
            this._blockLeft = e.target.dataset.left;
            this._curBlock = e.target.dataset.tag;
        },

        onBlockTouchMoveFun: function (e) {
            var that = this;
            if (that.fangdou) {
                that.fangdou = false;
                var values = that.calculateValuesFun(e);
                that.refreshProgressBarFun(values[2], values[3]);
                that.refreshBlockFun(values[2], values[3]);
                var eventDetail = {
                    minValue: values[0],
                    maxValue: values[1],
                    fromUser: true
                };
                var eventOption = {};
                that.$emit(
                    'rangechange',
                    {
                        detail: eventDetail
                    },
                    eventOption
                );
                setTimeout(() => {
                    that.fangdou = true;
                }, 5);
            }
        },

        onBlockTouchEndFun: function (e) {
            var that = this;
            var values = that.calculateValuesFun(e);
            that.refreshProgressBarFun(values[2], values[3]);
            that.refreshBlockFun(values[2], values[3]);
            var eventDetail = {
                minValue: values[0],
                maxValue: values[1],
                fromUser: true
            };
            var eventOption = {};
            that.$emit(
                'rangechange',
                {
                    detail: eventDetail
                },
                eventOption
            );
        },

        isValuesValidFun: function (values) {
            return values != null && values != undefined && values.length == 2;
        },

        /**
         * 根据手势计算相关数据
         */
        calculateValuesFun: function (e) {
            var that = this;
            var moveLength = e.changedTouches[0].pageX - that._blockDownX;
            var left = that._blockLeft + that.pxToRpxFun(moveLength);
            left = Math.max(0, left);
            left = Math.min(left, that.MAX_LENGTH);
            var minBlockLeft = that.minBlockLeft;
            var maxBlockLeft = that.maxBlockLeft;
            if (that._curBlock == 'minBlock') {
                minBlockLeft = left;
            } else {
                maxBlockLeft = left;
            }
            var range = that.max - that.min;
            var minLeft = Math.min(minBlockLeft, maxBlockLeft);
            var maxLeft = Math.max(minBlockLeft, maxBlockLeft);
            var minValue = (minLeft / that.MAX_LENGTH) * range + that.min;
            var maxValue = (maxLeft / that.MAX_LENGTH) * range + that.min;
            return [minValue, maxValue, minLeft, maxLeft];
        },

        /**
         * 计算滑块坐标
         */
        calculateBlockLeftFun: function (minValue, maxValue) {
            var that = this;
            var blockSize = that.blockSize;
            var range = that.max - that.min;
            var minLeft = ((minValue - that.min) / range) * that.MAX_LENGTH;
            var maxLeft = ((maxValue - that.min) / range) * that.MAX_LENGTH;
            return [minLeft, maxLeft];
        },

        /**
         * 刷新进度条视图
         */
        refreshProgressBarFun: function (minBlockLeft, maxBlockLeft) {
            var that = this;
            var blockSize = that.blockSize;
            that.setData({
                progressBarLeft: minBlockLeft + blockSize / 2,
                progressBarWidth: Math.abs(maxBlockLeft - minBlockLeft)
            });
        },

        /**
         * 刷新滑块视图
         */
        refreshBlockFun: function (minBlockLeft, maxBlockLeft) {
            var that = this;
            that.setData({
                minBlockLeft: minBlockLeft,
                maxBlockLeft: maxBlockLeft
            });
        },

        /**
         * 刷新整个视图
         */
        refreshFun: function () {
            var that = this;
            var MAX_LENGTH = that.width - that.blockSize;
            that.setData({
                MAX_LENGTH: MAX_LENGTH,
                maxBlockLeft: MAX_LENGTH,
                progressBarWidth: MAX_LENGTH
            });
            var values = that.values;
            if (that.isValuesValidFun(values)) {
                values[0] = Math.max(that.min, values[0]);
                values[0] = Math.min(values[0], that.max);
                values[1] = Math.max(that.min, values[1]);
                values[1] = Math.min(values[1], that.max);
                var leftValues = that.calculateBlockLeftFun(values[0], values[1]);
                that.refreshProgressBarFun(leftValues[0], leftValues[1]);
                that.refreshBlockFun(leftValues[0], leftValues[1]);
            }
        }
    },
    created: function () {},
    watch: {
        width: {
            handler: function (newVal, oldVal, changedPath) {
                var that = this;
                if (newVal != that.width) {
                    this.refreshFun();
                }
            },

            immediate: true
        },

        blockSize: {
            handler: function (newVal, oldVal, changedPath) {
                var that = this;
                if (newVal != that.blockSize) {
                    this.refreshFun();
                }
            },

            immediate: true
        },

        min: {
            handler: function (newVal, oldVal, changedPath) {
                var that = this;
                if (newVal != that.min) {
                    that.refreshFun();
                }
            },

            immediate: true
        },

        max: {
            handler: function (newVal, oldVal, changedPath) {
                var that = this;
                if (newVal != that.max) {
                    that.refreshFun();
                }
            },

            immediate: true
        },

        values: {
            handler: function (newVal, oldVal, changedPath) {
                var that = this;
                // var values = that.data.values;
                if (that.isValuesValidFun(newVal) && that.isValuesValidFun(oldVal)) {
                    if (oldVal[0] != newVal[0] || oldVal[1] != newVal[1]) {
                        that.refreshFun();
                    }
                }
            },

            immediate: true,
            deep: true
        }
    }
};
</script>
<style>
@import './range-slider.css';
</style>
