<template>
    <ul class="nus_sticky-list">
        <template v-if="list">
            <template v-for="(item, index) in list">
                <sticky-item
                    ref="hook_items"
                    :itemKey="_filterKey(item, index)"
                    :itemData="item"
                    :key="index"
                    :activeIndex="myActiveIndex"
                    @selectChange="_onSelectChange(index, item)">
                    <template slot-scope="{itemKey, itemData}">
                        <slot
                            :itemKey="itemKey"
                            :itemIndex="index"
                            :itemData="itemData">
                        </slot>
                    </template>
                </sticky-item>
            </template>
        </template>
    </ul>
</template>

<script>
import {
    throttle,
    getElementTop,
    navIndex,
    animation,
    callFn,
    getScrollEl
} from 'nimble-lib';
import attrSync from '../../../../Mixins/attrSync';
import StickyTmp from '../_comm/StickyTmp';
import StickyItem from './stickyItem/StickyItem';

export default {
    extends: StickyTmp,
    components: {
        StickyItem
    },
    mixins: [attrSync('activeIndex')],
    watch: {
        list(nowval) {
            let _that = this;
            if (nowval && nowval.length) {
                setTimeout(() => {
                    _that._getScrollEl(true);
                    _that._refresh();
                }, 50);
            }
        }
    },
    created() {
        let _that = this;
        _that.indexList = navIndex();
        _that.indexList.$on('itemmove', (res) => {
            _that.$emit('itemmove', res);
        });

        /**
         * 刷新列表
         */
        _that._refreshHandler = throttle(() => {
            let _scrollEl = _that._getScrollEl();
            let _myScrollHeight = (_scrollEl && _scrollEl.scrollHeight) || 0;
            if (Math.abs((_that._myScrollHeight || 0) - _myScrollHeight) > 50) {
                _that._myScrollHeight = _myScrollHeight;
                _that._refresh();
            }
        }, 200) || _that._refresh;
        let _timeout;
        /**
         * 事件方法
         * @param {Event} evt 事件对象
         */
        _that._onScroll = function (evt) {
            if (_that.lock) {
                return;
            }
            let el = _that._getScrollEl();
            let scrollTop = el && (el.scrollTop || el.scrollY);
            if (typeof _timeout !== 'undefined') {
                clearTimeout(_timeout);
            }
            _timeout = setTimeout(() => {
                _that._refreshHandler(evt);
            }, 100);
            _that._setActiveIndex(scrollTop);
        };

        _that._onResize = function() {
            _that._refresh();
        };
    },
    mounted() {
        let _that = this;
        _that.$nextTick(() => {
            _that._initCom();
            setTimeout(() => {
                _that._getScrollEl(true);
                _that._refresh();
            }, 50);
        });
    },
    beforeDestroy() {
        let _that = this;
        _that.scrollEl && _that.scrollEl.removeEventListener('scroll', _that._onScroll);
        window.removeEventListener('resize', _that._onResize);
    },
    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]);
        },
        /**
         * 初始化
         */
        _initCom() {
            let _that = this;
            _that._getScrollEl(true);
            window.addEventListener('resize', _that._onResize, false);
            _that._refresh();
            !_that.activeIndex && _that._setActiveIndex(0);
        },
        /**
         * 获取Scroll元素
         * @param {Boolean} isReset 是否重置
         * @returns {Element}
         */
        _getScrollEl(isReset) {
            let _that = this;
            if (isReset && _that.scrollEl) {
                _that.scrollEl.removeEventListener('scroll', _that._onScroll);
                _that.scrollEl.removeEventListener('load', _that._refreshHandler);
            }
            let res = (!isReset && _that.scrollEl) || getScrollEl(_that.$el);
            if ((!_that.scrollEl || isReset) && res) {
                _that._scrollElTop = getElementTop(res) || 0;
                _that._myScrollHeight = res.scrollHeight || 0;
                res.addEventListener('scroll', _that._onScroll, false);
                res.addEventListener('load', _that._refreshHandler, true);
            }
            _that.scrollEl = res;
            return res;
        },
        /**
         * 刷新
         */
        _refresh() {
            let _that = this;
            _that.indexList.refresh(_that.$refs.hook_items);
            _that._onScroll();
        },
        /**
         * 选中index的时的事件
         * @param {Number} index 索引
         * @param {Number} itemData 数据
         */
        _onSelectChange(index, itemData) {
            let _that = this;
            if (_that.myIndex !== index) {
                _that.myIndex = index;
                let item = _that.indexList.getItem(index);
                if (typeof item.top === 'number') {
                    let _top = item.top - (_that._scrollElTop || 0);
                    _that._setScrollTop(_top);
                }
            }
            _that.$emit('checked', itemData);
        },
        /**
         * 设置scrollTop
         * @param {Number} top 顶部距离
         */
        _setScrollTop(top) {
            let _that = this;
            let _el = _that.scrollEl;
            let oldTop = (_el === window ? _el.scrollY : _el.scrollTop);
            if (_el) {
                if (typeof _that._timeout !== 'undefined') {
                    clearTimeout(_that._timeout);
                }
                /**
                 * 处理window异常
                 */
                _that.lock = true;
                if (_that.scrollAanimation) {
                    animation(setTop, _that.time, _that.duration, top - oldTop);
                } else {
                    setTop(top - oldTop);
                }
            }
            /**
             * 设置滚动条位置
             * @param {Number} start 位置
             */
            function setTop(start) {
                let scrollY;
                let _top = oldTop + start;

                if (_el === window) {
                    _el.scrollTo({
                        top: _top,
                        behavior: 'instant'
                    });
                    scrollY = _el.scrollY;
                } else {
                    _el.scrollTop = _top;
                    scrollY = _el.scrollTop;
                }
                if (Math.abs(top - _top) < 1) {
                    _that._timeout = setTimeout(() => {
                        _that.lock = false;
                        /**
                         * 修复超范围的问题
                         */
                        if (typeof scrollY === 'number' && top !== scrollY) {
                            _that._onScroll(scrollY);
                        }
                    }, 20);
                }
            }
        },
        /**
         * index转换成activeIndex
         * @param {Number} index 列表的索引
         * @return {*}
         */
        _toActiveIndex(index) {
            let _that = this;
            let myActiveIndex = _that._filterKey(_that.list && _that.list[index], index);
            if (_that.myIndex !== index || myActiveIndex !== _that.activeIndex) {
                _that.myIndex = index;
                return myActiveIndex;
            }
        },
        /**
         * 手指移动事件
         * @param {Number} top 事件对象
         */
        _setActiveIndex (top) {
            let _that = this;
            let index = _that.indexList.getIndex(top + _that._scrollElTop);
            let myActiveIndex = _that._toActiveIndex(index);
            if (typeof myActiveIndex !== 'undefined') {
                _that.myActiveIndex = myActiveIndex;
            }
        }
    }
};
</script>

<style lang="scss">
@import '../../../../_assets/style/_iconFont.scss';
@import '../../../../_assets/style/_var.scss';
@import '../../../../_assets/style/_mixin.scss';
.nus_sticky-list {
    height: 100%;
    overflow-y: auto;
    overflow-x: hidden;
    ul,li{
        padding: 0;
        list-style: none;
    }
}
</style>
