<template>
    <ul
        class="nus_scrollnav"
        v-if="list && list.length"
        @mousedown="_onMousedown"
        @touchmove="_onTouchMove"
        @touchstart="_onTouchStart">
        <template v-for="(item, index) in list">
            <nav-item
                ref="hook_navItems"
                class="nu_nav-item"
                :activeIndex.sync="myActiveIndex"
                :itemkey="_filterKey(item, index)"
                :nameText="item.navName"
                :key="index"
                :isNavTouch="isNavTouch"
                @checked="_onChecked(index)"
                @selectChange="_selectChange">
                <slot
                    :itemIndex="index"
                    :itemData="item"
                    :isNavTouch="isNavTouch"
                    :filterKey="filterKey">
                </slot>
            </nav-item>
        </template>
    </ul>
</template>

<script>
import { animation, navIndex, callFn } from 'nimble-lib';
import ScrollnavTmp from './_comm/ScrollnavTmp';
import navItem from './navItem/navItem';
import attrSync from '../../../Mixins/attrSync/attrSync';

export default {
    name: 'NuScrollnav',
    extends: ScrollnavTmp,
    props: {
        /**
         * 数据列表
         */
        list: {
            type: Array
        },
        /**
         * 过滤key
         */
        filterKey: {
            type: Function
        },
        /**
         * 是否开启手指滑动导航
         */
        isNavTouch: {
            default: true
        }
    },
    components: {
        navItem
    },
    mixins: [attrSync('activeIndex')],
    watch: {
        list() {
            let _that = this;
            _that.$nextTick(() => {
                _that.indexList.refresh(_that.$refs.hook_navItems);
            });
        }
    },
    created() {
        this.indexList = navIndex();
    },
    mounted() {
        let _that = this;
        _that.$nextTick(() => {
            _that.indexList.refresh(_that.$refs.hook_navItems);
            !_that.activeIndex && _that._toActiveIndex(0);
        });
        _that.resize = function() {
            _that.indexList.refresh(_that.$refs.hook_navItems);
        };
        setTimeout(() => {
            _that.indexList.refresh(_that.$refs.hook_navItems);
        }, 200);
        window.addEventListener('resize', _that.resize);
    },
    beforeDestroy() {
        let _that = this;
        window.removeEventListener('resize', _that.resize);
        window.removeEventListener('mouseup', _that._setMouseStart);
    },
    methods: {
        /**
         * 过滤索引名称
         * @param {Object} item 当前项的数据
         * @param {Number} index 索引
         * @returns {*}
         */
        _filterKey(item, index) {
            let _index = index;
            if (item && typeof item.index !== 'undefined') {
                _index = item.index;
            }
            return callFn(this.filterKey || _index, [item, index]);
        },
        /**
         * 选中时的动画
         * @param {Number} index 索引
         */
        _onChecked(index) {
            let _that = this;
            let item = _that.indexList.getItem(0);
            let cItem = _that.indexList.getItem(index || 0);
            let top = (cItem.top - item.top + (item.height / 2)) - (_that.$el.offsetHeight / 2);
            let _oldTop = _that.$el.scrollTop;
            animation((start) => {
                _that.$el.scrollTop = _oldTop + start;
            }, 10, 200, top - _oldTop);
        },
        /**
         * 兼容鼠标事件
         */
        _onMousedown() {
            let _that = this;
            if (_that.isNavTouch) {
                _that._mouseStart = true;
                _that._setMouseStart = _that._setMouseStart || function () {
                    _that._mouseStart = false;
                    window.removeEventListener('mouseup', _that._setMouseStart);
                };
                window.addEventListener('mouseup', _that._setMouseStart);
            }
        },
        /**
         * 选中选项的索引
         * @param {*} activeIndex 选项的索引
         */
        _selectChange(activeIndex) {
            if (this._mouseStart) {
                this.myActiveIndex = activeIndex;
            }
        },
        /**
         * index转换成activeIndex
         * @param {Number} index 列表的索引
         */
        _toActiveIndex(index) {
            let _that = this;
            if (_that.myIndex !== index) {
                _that.myIndex = index;
                _that.myActiveIndex = _that._filterKey(_that.list && _that.list[index], index);
            }
        },
        /**
         * 兼容event
         * @param {Event} evt 事件对象
         * @returns {Event}
         */
        _getEvent(evt) {
            return (evt.touches && evt.touches[0]) || evt;
        },
        /**
         * 点导航条
         */
        _onTouchStart () {
            let _that = this;
            if (_that.isNavTouch) {
                _that.myIndex = null;
                _that._scrollTop = _that._getScrollTop(true);
            }
        },
        /**
         * 手指移动事件
         * @param {Event} evt 事件对象
         */
        _onTouchMove (evt) {
            let _that = this;
            if (_that.isNavTouch) {
                evt.preventDefault();
                evt.stopPropagation();
                evt = _that._getEvent(evt);
                let _pageY = evt.pageY;
                if (Math.abs((_that.pageY || 0) - _pageY) > 4) {
                    _that._scrollTop = _that._getScrollTop();
                    _that.pageY = _pageY;
                    let index = _that.indexList.getIndex(_pageY + _that._scrollTop);
                    _that._toActiveIndex(index);
                }
            }
        },
        /**
         * 获取滚动条顶部距离
         * @param {Boolean} isReset 是否重置
         * @returns {Number}
         */
        _getScrollTop(isReset) {
            let _that = this;
            if (isReset || typeof _that._scrollTop !== 'number' || _that._scrollEl === window) {
                let sData = _that.indexList.getScrollTop() || {};
                // window有滚动条或isFixed并且当前取得top是window的时候不用计算位置
                _that._scrollTop = ((_that._hasWinScroll(isReset) && sData.isFixed) ||
                (!_that._hasWinScroll(isReset) && !sData.isFixed)) ? 0 : sData.scrollTop;
                _that._scrollEl = sData.el;
            }
            return _that._scrollTop || 0;
        },
        /**
         * 获取Scroll元素
         * @param {Boolean} isReset 是否重置
         * @returns {Element}
         */
        _hasWinScroll(isReset) {
            let _that = this;
            if (isReset || typeof _that._isWinScroll !== 'boolean') {
                let _scrollHeight = document.body.scrollHeight || document.documentElement.scrollHeight;
                if (_scrollHeight <= (window.innerHeight - 5)) {
                    _that._isWinScroll = true;
                } else {
                    _that._isWinScroll = false;
                }
            }
            return !!_that._isWinScroll;
        }
    }
};
</script>

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

.nus_scrollnav {
    display: flex;
    flex-direction: column;
    justify-content: center;
    width: 100%;
    height: 100%;
    max-height: 100%;
    color: $nuscrollnav-color;
    font-size: $nuscrollnav-size;
    user-select: none;
    ul,li{
        padding: 0;
        list-style: none;
    }
    .nu_nav-item {
        position: relative;
        list-style: none;
        cursor: pointer;
        width: 100%;
        max-height: 35px;
        min-height: 14px;
        display: flex;
        flex: 1;
        align-items: center;
        justify-content: center;
        font-weight: 400;
        @include iconPadding();
    }
    .nu_active {
        color: $nuscrollnav-active-color;
    }
}
</style>
