<template>
    <div class="nus_floaticon"
        v-if="showList && showList.length > 0">
        <div class="nu_floaticon-wrap">
            <template
                v-for="(item, index) in showList">
                <div class="nu_floatIcon-item"
                    v-if="item"
                    :class="[item.className || '']"
                    :key="index">
                    <nu-funicon
                        class="nu_floatIcon"
                        :iconClass="iconClass"
                        :icon="item.icon"
                        :imgUrl="item.imgUrl"
                        :nameText="item.text"
                        :lazyOptions="lazyOptions"
                        @click="_click($event, item)"
                        @tap="_click($event, item)">
                    </nu-funicon>
                </div>
            </template>
        </div>
    </div>
</template>

<script>
import { callFn, scrollParent, animation, extend } from 'nimble-lib';
import WidgetTmp from '../_comm/WidgetTmp';
import NuFunicon from '../funicon';

/**
 * 事件类型
 */
const EVENT_TYPE = {
    SCROLL_CHANGE: 'scrollChange' // 滚动条位置变化
};

export default {
    extends: WidgetTmp,
    name: 'NuFloaticon',
    components: {
        NuFunicon
    },
    props: {
        /**
         * 懒加载参数
         */
        lazyOptions: {
            type: Object
        },
        /**
         * icon列表/返回icon列表的方法
         */
        list: {
            type: [Array, Function, Boolean]
        },
        /**
         * 滚动元素
         */
        scrollEl: {
        },
        /**
         * 自定义icon的class名称
         */
        iconClass: {
            type: String
        },
        /**
         * 过滤显示列表的方法
         */
        filterShowList: {
            type: Function
        }
    },
    data () {
        return {
            myList: this._filterList(),
            showList: []
        };
    },
    mounted () {
        const _that = this;
        _that.$nextTick(() => {
            setTimeout(() => {
                _that._addEvt();
                _that._setShowList();
            });
        });
    },
    watch: {
        /**
         * 监听滚动元素的变化
         */
        scrollEl () {
            this._addEvt();
        },
        /**
         * 监听列表
         * @param {Array} nowVal 当前icon列表
         */
        list() {
            this.myList = this._filterList();
        },
        myList() {
            this._setShowList();
        }
    },
    beforeDestroy () {
        const _that = this;
        let _scrollDom = _that._getScrollEl();
        _scrollDom && _scrollDom.removeEventListener('scroll', _that._onScroll);
    },
    methods: {
        /**
         * 组册事件监听
         */
        _addEvt () {
            const _that = this;
            let _scrollDom = _that._getScrollEl();
            _that._removeEvt();
            if (_scrollDom) {
                _scrollDom.removeEventListener('scroll', _that._onScroll);
                _scrollDom.addEventListener('scroll', _that._onScroll);
            }
        },
        /**
         * 解绑事件
         */
        _removeEvt() {
            const _that = this;
            let _scrollDom = _that._getScrollEl();
            _scrollDom && _scrollDom.removeEventListener('scroll', _that._onScroll);
        },
        /**
         * 获取scrollDom
         * @param {Boolean} isReset 是否重置
         * @returns {HTMLElement} 获取滚动元素
         */
        _getScrollEl (isReset) {
            const _that = this;
            let _el = (!isReset && _that._scrollElCache) || null;
            const _scrollEl = _that.scrollEl;
            if (!_el) {
                if (_scrollEl) {
                    if (typeof _scrollEl === 'string') {
                        _el = document.querySelector(_scrollEl);
                    } else {
                        _el = _scrollEl;
                    }
                } else {
                    _el = scrollParent(_that.$el);
                }
            }
            _that._scrollElCache = _el;
            return _el;
        },
        /**
         * 过滤列表
         * @returns {Array}
         */
        _filterList() {
            const _that = this;
            /**
             * 默认的列表
             */
            const DEFAULT_LIST = [{
                type: 'goTop',
                flag: 'goTop',
                // className: '',
                // imgUrl: '',
                icon: '\ue61f'
                // text: ''
            }];
            let _res = callFn(_that.list || DEFAULT_LIST, [DEFAULT_LIST]);
            if (typeof _res === 'undefined' ||
                _res === true) {
                _res = DEFAULT_LIST;
            }
            if (!(_res instanceof Array)) {
                _res = [_res];
            }
            return _res;
        },
        /**
         * 过滤列表
         * @returns {Array} 返回过滤后的列表
         */
        _setShowList () {
            const _that = this;
            const _list = _that.myList || [];
            const _el = _that._getScrollEl();
            const _scrollDom = _el || {};
            let _top = _scrollDom.scrollTop || _scrollDom.scrollY;
            let _res = callFn(_that.filterShowList, [{
                list: extend(true, _list),
                top: _top,
                el: _el,
                showList: _that.showList
            }]);
            if (typeof _res === 'undefined') {
                _res = _list.filter((item) => {
                    const _type = item.type || '';
                    if (_type === 'goTop') {
                        const _scrollTop = _top || 0;
                        return _scrollTop > 300;
                    }
                    return true;
                });
                _res = (_res.length === _list.length) ? _list : _res;
            }
            _that.showList = _res;
            return _res;
        },

        /**
         * 滚动回调方法
         * @param {Event} evt 事件对象
         */
        _onScroll (evt) {
            const _that = this;
            evt = evt || {};
            _that._setShowList();
            _that.$emit(EVENT_TYPE.SCROLL_CHANGE, {
                Event: evt,
                data: {
                    list: _that.myList,
                    showList: _that.showList,
                    el: evt && evt.target,
                    top: evt && evt.target && evt.target.scrollTop
                }
            });
        },

        /**
         * 设置scrollTop
         */
        _toTop() {
            let _that = this;
            let _el = _that._getScrollEl();
            if (_el && !_that._locked) {
                let oldTop = _el.scrollY || _el.scrollTop || 0;
                animation((start) => {
                    setTop(start, oldTop);
                }, 10, 200, 0 - oldTop);
            }

            /**
             * 设置滚动条位置
             * @param {Number} start 位置
             * @param {Number} oldTop 位置
             */
            function setTop(start, oldTop) {
                let _top = oldTop + start;
                if (_el === window) {
                    _el.scrollTo({
                        top: _top,
                        behavior: 'instant'
                    });
                } else {
                    _el.scrollTop = _top;
                }
                _that._locked = _top !== top;
            }
        },
        /**
         * 组装事件对象
         * @param {Object} item 数据项
         */
        _handle (item) {
            item = item || {};
            const _type = (item.type) || '';
            switch (_type) {
                case 'goTop':
                    this._toTop();
                    break;
            }
        },
        /**
         * 点击事件的回调方法
         * @param {Event} evt 事件对象
         * @param {Object} item 当前数据项
         */
        _click (evt, item) {
            const _that = this;
            _that._handle(item);
            _that._clickItem(evt, item);
            switch (evt && evt.type) {
                case 'click':
                    _that._onClick(evt);
                    break;
                case 'tap':
                    _that._onTap(evt);
                    break;
                default:
                    break;
            }
        },
        /**
         * 点击某个item项的回调方法
         * @param {Event} evt 事件对象
         * @param {Object} item 当前数据项
         */
        _clickItem (evt, item) {
            const _that = this;
            item = item || {};
            _that._onClickItem({
                Event: evt,
                data: {
                    item: item,
                    list: _that.myList,
                    el: _that.scrollDom,
                    top: _that.scrollDom && _that.scrollDom.scrollTop
                }
            });
        }
    }
};
</script>

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

.nus_floaticon {
    border-color: $nufloaticon-br-color;
    color: $nufloaticon-color;
    * {
        border-color: inherit;
        color: inherit;
        font-size: inherit;
    }
    .nu_floatIcon-item {
        display: block;
        margin-bottom: 10px;
        cursor: pointer;
        &:last-child {
            margin-bottom: 0;
        }
    }
    .nu_floatIcon{
        display: block;
    }
    .nu_fun-icon{
        box-sizing: content-box;
        background: $nufloaticon-bg-color;
        border: {
            width: 1px;
            style: solid;
        };
        border-radius: 50%;
        padding: 7px;
        line-height: 1;
        overflow: hidden;
    }
}
</style>
