<template>
    <div class="nus_tabbar"
        :class="[isSpread && widthMap.totalWidth > (widthMap.wrapWidth - 10) && 'nu_tabbar-spread']">
        <div class="nu_tabbar-wrap"
            ref="hook_wrap"
            @mousedown="_onStart"
            @mousemove.prevent="_onMove"
            @mouseup="_onEnd"
            @mouseleave="_onEnd">
            <ul class="nu_tab-list">
                <li class="nu_tab-item"
                    ref="hook_tab"
                    v-for="(item, index) in list"
                    :class="((myActiveIndex + '') === (index + '')) && ['nu_tab-active', activeCls]"
                    :style="{width: _filterWidth(index)}"
                    :key="index + '_' + (item && item.key)"
                    @click="_click($event, item, index)"
                    @tap="_tap($event, item, index)">
                    <slot :itemData="_filterItem(item)"
                        :data="item"
                        :index="index">
                        <span class="nu_tab-text">{{_filterItem(item).text}}</span>
                    </slot>
                </li>
            </ul>
        </div>
        <div class="nu_spread"
            v-if="isSpread && widthMap.totalWidth > (widthMap.wrapWidth - 10)"
            @click="_setSpread">
            <div class="nu_spread-cont nu_icon">{{(mySpread &&'\ue605') || '\ue604'}}</div>
        </div>
    </div>
</template>
<script>
/* eslint-disable max-lines */
import { animation, callFn, diffData, extend } from 'nimble-lib';
import attrSync from '../../../Mixins/attrSync/attrSync';
import TabbarPc from './Tabbar.pc';
export default {
    extends: TabbarPc,
    props: {
        isSpread: { // 是否要显示展开按钮
            type: Boolean
        },
        list: { // tab列表
            type: Array
        },
        activeCls: { // 活动的class名称
            type: String
        },
        width: { // tab项的宽度
            default: true
        },
        filterItem: { // 过滤展示的文案
            type: Function
        }
    },
    mixins: [
        attrSync('spread'),
        attrSync('activeIndex', {
            myValueChange(nowVal) {
                this._initMyActiveIndex(nowVal);
            }
        }),
        attrSync('activeKey', {
            myValueChange(nowVal) {
                this._toKey(nowVal);
            }
        }),
        attrSync('tabsMap', {
            myValueInit(value) {
                let _that = this;
                let res = value;
                if (!(value instanceof Object)) {
                    res = {};
                }
                let _index = _that.myActiveIndex;
                if (typeof _index === 'number' && !res[_index]) {
                    if (!value) {
                        res.activeIndex = _index;
                        res[_index] = {};
                        _that.$emit('update:tabsMap', res);
                    } else {
                        _that.$set(res, _index, {});
                    }
                }
                return res;
            }
        })
    ],
    watch: {
        list() {
            this._refreshWidth();
        }
    },
    data() {
        return {
            isSetWidth: false, // 是否设置宽度
            widthMap: {} // 缓存默认的相关宽度
        };
    },
    created() {
        let _that = this;
        let _tabsMap = _that.tabsMap || {};
        if (_that.activeKey || _tabsMap.activeKey) {
            _that._toKey(_that.activeKey || _tabsMap.activeKey);
        } else {
            _that.myActiveIndex = _tabsMap.activeIndex || parseInt(_that.activeIndex, 10) || 0;
            _that._initMyActiveIndex(_that.myActiveIndex);
        }
    },
    mounted() {
        let _that = this;
        window.addEventListener('resize', _that._refreshWidth);
        _that.$nextTick(() => {
            setTimeout(() => {
                _that._refreshWidth();
            }, 20);
        });
    },
    beforeDestroy() {
        window.removeEventListener('resize', this._refreshWidth);
    },
    methods: {
        /**
         * 初始化index
         * @param {number} nowVal 当前值
         */
        _initMyActiveIndex(nowVal) {
            let _that = this;
            _that._calcPosition();
            if (!(_that.myTabsMap instanceof Object)) {
                _that.myTabsMap = {};
            }
            let _key = _that._getKey(nowVal);
            let _extMap = {activeIndex: nowVal};
            if (_key !== undefined) {
                _that.myActiveKey = _key;
                _extMap.activeKey = _key;
            }
            _that.myTabsMap = extend({}, _that.myTabsMap, _extMap);
            if (!_that.myTabsMap[nowVal]) {
                _that.myTabsMap[nowVal] = {};
            }
            if (!_that.widthMap || !_that.widthMap.wrapWidth) {
                _that._refreshWidth();
            }
        },
        _setSpread() {
            this.mySpread = !this.mySpread;
        },
        /**
         * 获取当前的key
         * @param {Number} index 索引
         * @returns {*}
         */
        _getKey(index) {
            let _that = this;
            let _key = ((_that.list || [])[index] || {}).key;
            if (_key !== undefined && _key !== null) {
                return _key;
            }
        },
        /**
         * 跳转到指定的key
         * @param {any} key 数据对应的key
         * @returns {Object} 返回该项数据
         */
        _toKey(key) {
            const _that = this;
            let _key = _that._getKey(_that.myActiveIndex);
            if (_key !== key && key !== undefined && key !== null) {
                let _list = _that.list || [];
                for (let i = 0; i < _list.length; i++) {
                    const item = _list[i] || {};
                    if (typeof item.key === 'undefined') {
                        return;
                    }
                    if (diffData(item.key, key)) {
                        _that.myActiveIndex = i;
                        return item;
                    }
                }
            }
        },
        /**
         * 过滤展示的导航栏的数据项
         * @param {Object} item tab数据项
         * @param {Number} index tab数据项索引
         * @returns {Object} 返回过滤后的数据项
         */
        _filterItem (item, index) {
            const _that = this;
            let res = callFn(_that.filterItem || item, [item, index], _that);
            if (!(res instanceof Object)) {
                res = {
                    text: res
                };
            }
            return res;
        },
        /**
         * 刷新宽度
         */
        _refreshWidth() {
            let _that = this;
            if (_that.width === true) {
                _that.isSetWidth = false;
                setTimeout(() => { // 刷新更新时宽度是上次设置的
                    _that.widthMap = _that._getInitWidth();
                    _that.isSetWidth = true;
                    setTimeout(() => {
                        _that._calcPosition();
                    }, 0);
                }, 0);
            }
        },
        /**
         * 获取初始化时默认的tab项宽度
         * @return {Array}
         */
        _getInitWidth() {
            let _that = this;
            let _refs = _that.$refs || {};
            let _tabEls = _refs.hook_tab || [];
            let _wrapEl = _refs.hook_wrap;
            let _wrapWidth = _wrapEl && _wrapEl.offsetWidth; // tab列表可视区宽度
            let _list = []; // tab项宽度列表
            let _totalWidth = 0; // 总宽度
            let _len = _tabEls.length || 0; // item个数
            let _average = _wrapWidth / (_len || 1); // 平均宽度
            let _smallTotal = 0; // 小于平均的tab项总宽度
            let _maxWidth = 0; // 最大的item宽度
            if (_len) {
                for (let i = 0; i < _len; i++) {
                    const item = _tabEls[i];
                    let _width = item.offsetWidth;
                    _totalWidth += _width;
                    _maxWidth = Math.max(_maxWidth, _width);
                    if (_width < _average) {
                        _smallTotal += _width;
                    }
                    _list.push(_width);
                }
            }
            let res = {
                totalWidth: _totalWidth, // 总宽度
                wrapWidth: _wrapWidth, // tab列表可视区宽度
                list: _list, // tab项宽度列表
                maxWidth: _maxWidth // 最大的item宽度
            };
            if (_wrapWidth > _totalWidth) { // 内容小于可视宽度
                if (_wrapWidth < (_maxWidth * _len)) {
                    res.average = _average; // 平均宽度
                    res.smallTotal = _smallTotal; // 小于平均的tab项总宽度
                    res.fillRatio = (_wrapWidth - _totalWidth) / _smallTotal; // 填充的比例
                } else {
                    res.itemWidth = _wrapWidth / _len;
                }
            }
            return res;
        },
        /**
         * 过滤item项宽度
         * @param {Number} index 索引
         * @returns {string}
         */
        _filterWidth(index) {
            let _that = this;
            let _width = _that.width;
            if (_width === true) {
                _width = '';
                if (_that.isSetWidth) {
                    let _widthMap = _that.widthMap || {};
                    let _list = _widthMap.list || [];
                    let _average = _widthMap.average;
                    _width = _widthMap.itemWidth;
                    if (_average && _average > _list[index]) {
                        _width = _list[index] + (_list[index] * _widthMap.fillRatio);
                    }
                }
            }
            return (_width && /^\s*\d+\.?\d+\s*$/.test(_width + '') ? (_width + 'px') : _width) || '';
        },
        /**
         * 设置滚动条位置
         */
        _calcPosition() {
            let _that = this;
            let _refs = _that.$refs || {};
            let _tabEl = (_refs.hook_tab || [])[_that.myActiveIndex];
            if (!_tabEl) {
                return;
            }
            let _widthMap = _that.widthMap || {};
            let _wrapWidth = _widthMap.wrapWidth || 0;
            let _left = _tabEl.offsetLeft || 0;
            let _width = _tabEl.offsetWidth || 0;
            let left = (_left - ((_wrapWidth - _width) / 2));
            _that._setScroll(left);
        },
        /**
         * 设置滚动条左边位置
         * @param {Number} left 增加或减少的距离
         */
        _setScroll(left) {
            let _that = this;
            let _refs = _that.$refs || {};
            let _wrapEl = _refs.hook_wrap;
            let oldLeft = _wrapEl.scrollLeft || 0;
            animation((start) => {
                _wrapEl.scrollLeft = oldLeft + start;
            }, 10, 100, left - oldLeft);
        },
        _click(evt, item, index) {
            let _that = this;
            _that._setActiveIndex(index);
            _that._onClick(evt);
            _that._onClickItem({
                Event: evt,
                data: item,
                index: index,
                itemData: _that._filterItem(item)
            });
        },
        _tap(evt, item, index) {
            let _that = this;
            _that._setActiveIndex(index);
            _that._onTap(evt);
            _that._onClickItem({
                Event: evt,
                data: item,
                index: index,
                itemData: _that._filterItem(item)
            });
        },
        /**
         * 设置活动项的index
         * @param {Number} index 索引
         */
        _setActiveIndex(index) {
            if (!this._ismove) {
                this.myActiveIndex = index;
            }
        }
    }
};
</script>

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

.nus_tabbar {
    width: 100%;
    user-select: none;
    position: relative;
    &.nu_tabbar-spread{
        padding-right: 40px;
    }
    .nu_spread{
        width: 43px;
        position: absolute;
        right: 0;
        top: 0;
        bottom: 0;
        overflow: hidden;
        padding-left: 3px;
        font-size: 26px;
    }
    .nu_spread-cont{
        background: #f4f4f4;
        box-shadow: -1px 0 2px 0px rgba(0, 0, 0, 0.4);
        width: 100%;
        height: 100%;
        line-height: 44px;
    }
    .nu_tabbar-wrap{
        position: relative;
        overflow-x: auto;
        white-space: nowrap;
        text-align: left;
        min-width: 100%;
        &::-webkit-scrollbar {
            display: none;
        }
    }
    .nu_tab-list {
        height: 100%;
        width: 100%;
        white-space: nowrap;
        display: inline-block;
        margin: 0;
        padding: 0;
    }
    .nu_tab-item {
        cursor: pointer;
        display: inline-block;
        text-align: center;
        box-sizing: border-box;
        vertical-align: middle;
        line-height: 1;
        padding: 0;
        margin: 0;
        height: 100%;
        color: $nutabber-color;
    }
    .nu_tab-text{
        padding: 0 8px;
        display: inline-block;
        height: 100%;
        width: 100%;
        line-height: 44px;
    }
    .nu_tab-active{
        color: $nutabber-active-color;
    }
}
</style>
