<template>
    <div class="nus_drawer"
        @mousedown="_onStart"
        @mousemove="_onMove"
        @mouseup="_onEnd"
        @mouseleave="_onEnd"
        @mousecancel="_onEnd"
        @touchstart="_onStart"
        @touchmove="_onMove"
        @touchend="_onEnd"
        @touchcancel="_onEnd"
        @click="_onClick"
        @tap="_onTap">
        <transition name="t_drawer-mask">
            <div class="nu_drawer-mask"
                v-if="isMask"
                @mousemove="_onStopPropagation('mask', $event)"
                @touchmove="_onStopPropagation('mask', $event)">
            </div>
        </transition>
        <div class="nu_drawer-main"
            ref="hook_main"
            :class="movedActive && 'nu_move-active'"
            :style="mainStyle"
            @mousemove="_onStopPropagation('main', $event)"
            @touchmove="_onStopPropagation('main', $event)">
            <slot></slot>
        </div>
        <div class="nu_drawer-right"
            ref="hook_right"
            :class="movedActive && 'nu_move-active'"
            @mousemove="_onStopPropagation('right', $event)"
            @touchmove="_onStopPropagation('right', $event)">
            <div class="nu_drawer-list"
                v-if="list && list.length">
                <div class="nu_drawer-item"
                    ref="hook_listItem"
                    v-for="(item, index) in list"
                    :key="index"
                    :class="item && item.style"
                    :style="_getItemStyle(item, index)"
                    @click="_onItemClick(item, $event)">
                    <slot name="hook_item" :itemData="item">
                        <span class="nu_drawer-text">
                            {{ _filterBtnText(item) }}
                        </span>
                    </slot>
                </div>
            </div>
            <template v-else>
                <slot name="hook_right">
                </slot>
            </template>
        </div>
    </div>
</template>

<script>
/* eslint-disable */
import { callFn, getStyle } from 'nimble-lib';
import DrawerCore from './DrawerCore';
import { eventType, MOUSE_EVENT, STATUS_TYPE, styleName, eventName, EVENT_TYPE } from './constants';

export default {
    extends: DrawerCore,
    name: 'NuDrawer',
    data () {
        const _that = this;
        return {
            isInTransition: false, // 是否在动画中
            itemWidth: [], // 每个item项的宽度
            x: 0, // drawer的左边的滑动距离
            status: STATUS_TYPE.INIT, // 右边内容快的状态
            tranTime: _that.duration, // 动画时长
            tranFunc: 'ease', // 动画规则
            movedActive: false // 是否启动滑动
        };
    },
    computed: {
        /**
         * 是否显示mask遮罩
         * @return {Boolean} 返回是否显示
         */
        isMask () {
            const _that = this;
            return _that.mask && _that.status === STATUS_TYPE.VISIBLE;
        },
        /**
         * 获取主模块的样式
         * @return {Array} 返回主模块的样式
         */
        mainStyle () {
            const _that = this;
            let _style = [{
                [styleName.transform]: `translateX(${_that.x}px`
            }];
            if (_that.isInTransition) {
                _style.push(_that._getTransitionStyle());
            }
            return _style;
        }
    },
    mounted () {
        const _that = this;
        _that.$nextTick(() => {
            _that._initCom();
        });
        if (!_that.maxDisWidth) { // 解决可能第一次没有获取到dom元素的宽度
            setTimeout(() => {
                _that._resetCom();
            }, 100);
        }
    },
    beforeDestroy () {
        const _that = this;
        _that.$el && _that.$el.removeEventListener(eventName.transitionEnd, _that._onTransitionEnd);
        window.removeEventListener('resize', _that._resetCom);
    },
    watch: {
        /**
         * 观察list的变化
         */
        list () {
            const _that = this;
            _that._resetCom();
        },
        /**
         * 监听右边内容是否打开的状态
         * @param {String} nowVal 当前状态
         */
        status (nowVal) {
            const _that = this;
            const _index = _that.index;
            if (typeof _index !== 'undefined') {
                if (nowVal === STATUS_TYPE.VISIBLE) {
                    _that.myState = _index;
                } else {
                    _that.myState = null;
                }
            } else {
                _that.myState = nowVal === STATUS_TYPE.VISIBLE ? -3 : -1;
            }
        }
    },
    methods: {
        /**
         * 初始化组件
         */
        _initCom () {
            const _that = this;
            _that._initWatcher();
            _that._setBasicData((listItems) => {
                // 每项模块的默认宽度
                return _that._calculateWidth(listItems);
            });
            let _state = _that.myState + '';
            if (typeof _that.index !== 'undefined' &&
                _state !== '-1' && _state !== '-2' &&
                _state !== '-3' && _state !== '-4' &&
                _that.index == _state) {
                _that._showR(_that.duration);
            } else if (_state === '-3' || _state === '-4') {
                setTimeout(() => {
                    _that._showR(_state === '-3' ? _that.duration : 0);
                });
            }
            // 注册动画结束的回调方法
            if (_that.$el) {
                _that.$el.addEventListener(eventName.transitionEnd, _that._onTransitionEnd);
            }
            window.addEventListener('resize', _that._resetCom);
        },
        /**
         * 重置组件
         */
        _resetCom () {
            const _that = this;
            _that.itemWidth = new Array((_that.listItems && _that.listItems.length) || 0).fill('auto'); // 每项模块的当前宽度
            _that.$nextTick(() => {
                _that._setBasicData((listItems) => {
                    return _that._calculateWidth(listItems);
                });
            });
        },
        /**
         * 过滤按钮文案的方法
         * @param {Object} item 按钮数据
         * @returns {String} 返回按钮文案
         */
        _filterBtnText (item) {
            const _that = this;
            let res = callFn(_that.filterText, [item], _that);
            if (typeof res !== 'string') {
                res = (item && item.text) || '';
            }
            return res;
        },
        /**
         * 获取item项的样式
         * @param {Object} item 每个模块的数据
         * @param {Number} index 索引
         * @returns {Array} 返回每个模块的样式
         */
        _getItemStyle (item, index) {
            const _that = this;
            let _style = [];
            if (item && item.style) {
                _style.push(item.style);
            }
            let _width = _that.itemWidth[index];
            if (typeof _width !== 'undefined') {
                if (typeof _width === 'number') {
                    _width = _width + 'px';
                }
                _style.push({
                    width: _width
                });
            }
            if (_that.isInTransition) {
                _style.push(_that._getTransitionStyle());
            }
            return _style;
        },
        /**
         * 获取动画的样式
         * @returns {Object}  返回动画的样式
         */
        _getTransitionStyle () {
            const _that = this;
            return {
                [styleName.transitionDuration]: `${_that.tranTime}ms`,
                [styleName.transitionTimingFunction]: _that.tranFunc
            };
        },
        /**
         * 获取当前的位置
         * @returns {Number} 返回新的位置
         */
        _getComputedPosition () {
            const _that = this;
            _that.mainDom = _that.mainDom || _that.$refs['hook_main'];
            let _matrix = getStyle(_that.mainDom, styleName.transform);
            let _x = 0;
            try {
                if (_matrix) {
                    _matrix = _matrix.split(')')[0].split(', ');
                    _x = _matrix[12] || _matrix[4];
                    _x = parseFloat(_x);
                }
            } catch (err) {
                console.error(err);
                _x = 0;
            }

            return _x;
        },
        /**
         * 停止动画然后重新计算位置
         */
        _stop () {
            const _that = this;
            if (_that.isInTransition) {
                _that._setTransiton(0, null);
                _that._setWidthPos(null, _that._calculateWidth(_that.listItems), _that._getComputedPosition());
            }
        },
        /**
         * 滑动开始事件
         * @param {Event} evt 事件对象
         */
        _onStart (evt) {
            const _that = this;
            const _evtType = eventType[evt.type];
            if (_evtType === MOUSE_EVENT) {
                const _button = evt.button + '';
                if (_button !== '0') {
                    return;
                }
            }
            if (_that.initiated && _that.initiated !== _evtType) {
                return;
            }
            _that._stop();
            _that.initiated = _evtType;
            // evt.stopPropagation();
            let _point = evt.touches ? evt.touches[0] : evt;
            _that.pointX = _point.pageX;
            _that.pointY = _point.pageY;
            _that.directionLocked = 0;
            _that.distX = 0;
            _that.distY = 0;
            _that.movingDirection = 0;
        },
        /**
         * 滑动事件
         * @param {Event} evt 事件对象
         */
        _onMove (evt) {
            const _that = this;
            const _evtType = eventType[evt.type];
            if (_that.initiated !== _evtType) {
                return;
            }
            evt.stopPropagation();
            let _deltaX = _that._handleDelta(evt);
            if (_that.directionLocked === 'h') {
                _that.movedActive = true;
            }
            const _newX = _that.x + _deltaX;
            const _rSide = _that.$refs['hook_right'];
            const _rSideW = (_rSide && _rSide.offsetWidth) || 0;
            if (_newX < 0 || _rSideW > 0) {
                _that.status = STATUS_TYPE.VISIBLE;
                _that._setWidthPos(_deltaX);
            } else {
                _that._hideR();
            }
        },
        /**
         * 滑动结束事件
         * @param {Event} evt 事件对象
         */
        _onEnd (evt) {
            const _that = this;
            const _evtType = eventType[evt.type];
            if (_that.initiated !== _evtType) {
                return;
            }
            evt.stopPropagation();
            _that.movedActive = false;
            _that.initiated = false;
            _that._resetWidthPos();
        },
        /**
         * 动画结束的回调方法
         */
        _onTransitionEnd () {
            const _that = this;
            _that._setTransiton(0, null);
            const _rSide = _that.$refs['hook_right'];
            if (_rSide && (_rSide.offsetWidth === 0)) {
                _that.status = STATUS_TYPE.HIDDEN;
            }
        },
        /**
         * 点击item项的回调方法
         * @param {Object} item item项数据
         * @param {Event} evt 事件对象
         */
        _onItemClick (item, evt) {
            const _that = this;
            _that.$emit(EVENT_TYPE.CONFIRM_CHANGE, {
                Evt: evt,
                data: item
            });
            _that.$emit(EVENT_TYPE.CLICK_ITEM, {
                Event: evt,
                data: item
            })
        },
        /**
         * 阻止事件冒泡
         * @param {String} type 模块类型（是左边模块还是右边模块）
         * @param {Event} evt 事件对象
         */
        _onStopPropagation (type, evt) {
            const _fixed = (this.fixed || 0) + '';
            let _isStop = false;
            if (_fixed === '-1' && type === 'main') {
                _isStop = true;
            } else if (_fixed === '1' && type === 'right') {
                _isStop = true;
            }
            if (type === 'mask') {
                _isStop = true;
            }
            if (_isStop) {
                evt.stopPropagation();
            }
        }
    }
};
</script>

<style lang="scss">
@import '../../../_assets/style/_iconFont.scss';
@import '../../../_assets/style/_var.scss';
@import '../../../_assets/style/_mixin.scss';

.nus_drawer {
    width: 100%;
    height: 100%;
    position: relative;
    overflow: hidden;
    .nu_drawer-{
        &mask {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: $nudrawer-mask-bg;
            z-index: 1;
            &.t_drawer-mask-{
                &enter-active, &leave-active {
                    transition: opacity 500ms
                }
                &enter, &leave-to {
                    opacity: 0;
                }
            }
        }
        &main {
            height: 100%;
            width: 100%;
        }
        &right {
            position: absolute;
            right: 0;
            top: 0;
            height: 100%;
            z-index: 2;
        }
        &list {
            width: 100%;
            height: 100%;
            display: flex;
            white-space: nowrap;
        }
        &item {
            text-align: center;
            color: $nudrawer-btn-color;
            display: inline-block;
            height: 100%;
            width: 100%;
        }
        &text {
            display: inline-block;
            width: 100%;
            height: 100%;
        }
    }
    .nu_move-active {
        pointer-events: none;
    }
}
</style>
