<template>
    <div class="nus_swiper">
        <div
            class="nu_slides hook_wrap swiper-wrapper">
            <template v-if="list">
                <div
                    class="nu_slide swiper-slide"
                    :style="slideStyle"
                    v-for="(item, index) in list"
                    :key="index">
                    <filter-slide
                        :item="item"
                        :filterItem="filterItem">
                        <template slot-scope="{ itemData, data }">
                            <slot :itemData="itemData" :data="data" :index="index"></slot>
                        </template>
                    </filter-slide>
                </div>
            </template>
            <template v-else>
                <slot></slot>
            </template>
        </div>
        <slot name="hook_indicator">
            <div class="nu_indicator">
                <slot name="hook_indicator-cont"></slot>
            </div>
        </slot>
    </div>
</template>

<script>
import { Swiper, extend, throttle } from 'nimble-lib';
import BaseTmp from '../_comm/BaseTmp';
import { DEFAULT_EVENTS } from './constant';
import FilterSlide from './filterSlide/FilterSlide';
import attrSync from '../../../Mixins/attrSync/attrSync';

export default {
    name: 'NuSwiper',
    extend: BaseTmp,
    components: {
        FilterSlide
    },
    props: {
        /**
         * 数据列表
         */
        list: {
            type: Array
        },
        /**
         * swiper的参数
         */
        options: {
            type: Object
        },
        /**
         * 过滤方法
         */
        filterItem: {
            type: Function
        }
    },
    mixins: [attrSync('activeIndex', {
        mValueChange(nowVal) {
            let _that = this;
            let options = _that.myOptions || {};
            if (_that.myActiveIndex === nowVal) {
                _that.lock = true;
                return false;
            } else {
                _that.swiper && _that.swiper.slideTo(nowVal, options.speed || 0);
            }
        }
    })],
    watch: {
        options() {
            let _that = this;
            _that._updateOptions();
            _that.refresh();
        },
        isUpdate() {
            this.isUpdate = false;
        }
    },
    data() {
        let _that = this;
        return {
            /**
             * slot是否更新
             */
            isUpdate: false,
            /**
             * slot默认个数
             */
            defLen: 0,
            /**
             * 默认参数
             */
            myOptions: {
                initialSlide: _that.activeIndex || 0, // 初始化的index
                wrapperClass: 'hook_wrap',
                slideClass: 'nu_slide', // 动态加入
                loop: true,
                autoplay: true,
                paginationClickable: true,
                disableOnInteraction: false, // 用户操作swiper之后，是否禁止autoplay。默认为true：停止
                touchMoveStopPropagation: false, // 阻止移动事件冒泡
                preventClicksPropagation: false,
                freeMode: false, // freeMode: true,//不对齐视图
                observer: true, // 修改swiper自己或子元素时，自动初始化swiper
                observeParents: true,
                longSwipesRatio: 0.3, // 进行longSwipes时触发swiper所需要的最小拖动距离比例，即定义longSwipes距离比例。值越大触发Swiper所需距离越大。最大值0.5。
                touchRatio: 1, // 触摸距离与slide滑动距离的比率。设置为0.5后slide滑动距离只有触摸距离的一半，变得难以滑动，缓慢拖动查看效果。
                centeredSlides: false, // 设定为true时，活动块会居中，而不是默认状态下的居左。
                grabCursor: true // 设置为true时，鼠标覆盖Swiper时指针会变成手掌形状，拖动时指针会变成抓手形状。（根据浏览器形状有所不同）
            }
        };
    },
    computed: {
        slideStyle() {
            let res = null;
            let _slidesPerView = this.myOptions.slidesPerView;
            if (_slidesPerView > 1) {
                res = {
                    width: (100 / _slidesPerView).toFixed(3) + '%'
                };
            }
            return res;
        }
    },
    mounted() {
        this._updateOptions();
        this._updateSlide();
        this._initCom();
    },
    updated() {
        this._updateSlide();
        this.lock = false;
    },
    methods: {
        /**
         * 刷新swiper
         */
        refresh() {
            let _that = this;
            let sw = _that._swiper;
            let _options = _that.myOptions;
            if (!sw) {
                return;
            }
            if (_options && _options.loop) {
                _that.throttle = _that.throttle || throttle(function() {
                    sw.loopDestroy();
                    sw.loopCreate();
                }, 100);
                _that.throttle();
            }
        },
        /**
         * 更新选项
         * @returns {Object}
         */
        _updateOptions() {
            let _that = this;
            let _pagination = _that._initPagination();
            _that.myOptions = extend(_that.myOptions, _that.options, _pagination);
            return _that.myOptions;
        },
        /**
         * 初始化Swiper
         */
        _initCom() {
            let _that = this;
            let _el = _that.$el;
            if (_that.swiper) {
                return;
            }
            let _options = _that.myOptions;
            let sw = Swiper(_el, _options);
            let slidesPerView = _options.slidesPerView;
            let _time = ((slidesPerView && slidesPerView !== 1) && 200) || 0;
            setTimeout(() => {
                sw.preload().then((res) => {
                    if (!_that._swiper) {
                        _that._swiper = res;
                        _that.$emit('init', {
                            context: res
                        });
                    }
                    if (_options.loop && _el) {
                        let imgList = res.imagesToLoad;
                        for (let i = 0; i < imgList.length; i++) {
                            const img = imgList[i];
                            if (img) {
                                let load = function() {
                                    // 防止图片被更改
                                    // img.removeEventListener('load', load);
                                    _that.refresh();
                                };
                                // 销毁Swiper解除img load的监听
                                res.on('beforeDestroy', () => {
                                    img.removeEventListener('load', load);
                                });
                                img.addEventListener('load', load);
                            }
                        }
                    }
                    DEFAULT_EVENTS.forEach((item) => {
                        res.on(item, (evt) => {
                            _that.$emit(item, {
                                Event: evt,
                                context: res
                            });
                        });
                    });
                    res.on('slideChange', () => {
                        _that.myActiveIndex = res.realIndex;
                    });
                    res.on('touchStart', _that._onStart);
                    res.on('touchMove', _that._onMove);
                });
            }, _time);
            _that.swiper = sw;
        },
        /**
         * 初始化分页器
         * @returns {Object}
         */
        _initPagination() {
            let _that = this;
            let res = {};
            let _el = _that.$el;
            let _pagination = (_that.options && _that.options.pagination) || {};
            let _indicatorEl = _that.$slots.hook_indicator;
            _indicatorEl = _indicatorEl && _indicatorEl[0];
            _indicatorEl = _indicatorEl && _indicatorEl.tag && _indicatorEl.elm;
            let _pel = _indicatorEl;
            let _type = _pagination.type;
            if (!_pel) {
                let _inds = _el.querySelector(_pagination.el || '.nu_indicator');
                let _ind = _inds && _inds.childNodes[0];
                if (_inds && !_ind && !_type) {
                    _inds.parentNode.removeChild(_inds);
                }
                _pel = (!_type || _type === 'bullets') ? _ind : _inds;
            }
            if (_pel) {
                let _typeData = {
                    bulletClass: 'nu_indicator-item',
                    bulletActiveClass: 'nu_indicator-active'
                };
                switch (_type) {
                    case 'fraction':
                        _typeData = {
                            currentClass: 'nu_indicator-current',
                            totalClass: 'nu_indicator-total'
                        };
                        break;
                }
                res = {
                    pagination: extend({
                        type: 'bullets',
                        modifierClass: 'nu_indicator-'
                    }, _typeData, _pagination, {
                        el: _pel
                    })
                };
            }
            return res;
        },
        /**
         * 更新Slide
         */
        _updateSlide() {
            let _that = this;
            let _options = _that.myOptions;
            if (!_that.list && _options.slideClass) {
                let _list = _that.$slots.default || [];
                if ((!_that.isUpdate && !_that.lock) || (_that.defLen !== _list.length)) {
                    _that.defLen = _list.length;
                    _list.forEach((item) => {
                        if (item.tag) {
                            if (!item.elm.classList.contains(_options.slideClass)) {
                                _that.isUpdate = true;
                                item.elm.classList.add(_options.slideClass);
                            }
                        }
                    });
                }
            }
        },
        /**
         * 滑动开始
         * @param {Event} evt 事件对象
         */
        _onStart (evt) {
            const _that = this;
            let _point = evt.touches ? evt.touches[0] : evt;
            _that._pointX = _point.pageX;
            _that._pointY = _point.pageY;
        },
        /**
         * 滑动
         * @param {Event} evt 事件对象
         */
        _onMove (evt) {
            const _that = this;
            let _point = evt.touches ? evt.touches[0] : evt;
            let _deltaX = _point.pageX - _that._pointX;
            let _deltaY = _point.pageY - _that._pointY;
            if ((Math.atan(Math.abs(_deltaY) / Math.abs(_deltaX)) * (180 / Math.PI)) < 50) {
                evt.cancelable && evt.preventDefault();
            }
        }
    }
};
</script>

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

.nus_swiper{
    position: relative;
    width: 100%;
    overflow: hidden;
    .nu_slides,.nu_slide{
        display: inline-block;
        width: 100%;
        height: 100%;
        white-space: nowrap;
        font-size: 0;
        vertical-align: top;
    }
    img{
        max-width: 100%;
        max-height: 100%;
    }
    &.swiper-container-coverflow {
        .swiper-wrapper {
            -ms-perspective: 1200px;
        }
    }
    &.swiper-container-3d {
        -webkit-perspective: 1200px;
        perspective: 1200px;
        .swiper-wrapper {
            -webkit-transform-style: preserve-3d;
            transform-style: preserve-3d;
        }
    }
    .nu_indicator{//导航圆点列表
        position: absolute;
        width:100%;
        bottom: 9px;
        text-align: center;
        z-index: 3;
        font-size: 0;
    }
    .nu_indicator-fraction {
        position: absolute;
        text-align: center;
        font-size: $fontSizeDefault;
        color: $nuswiper-indicator-item-color;
        width:100%;
        bottom: 9px;
        z-index: 3;
    }
    .nu_indicator-item{
        background: $nuswiper-indicator-item-color;
        display: inline-block;
        width:6px;
        border-radius: 50%;
        opacity: .4;
        margin: 5px 6px;
        line-height: 1;
        cursor:pointer;
        &::after{
            content: '';
            display: inline-block;
            width: 100%;
            padding-top: 100%;
        }
    }
    .nu_indicator-active{
        opacity: 1;
    }
    .nu_indicator-box{ // 加盒子
        display: inline-block;
        text-align: center;
        line-height: 0;
        padding: 6px 4px;
        background: $nuswiper-indicator-box-bg;
        border-radius: 9px;
        .nu_indicator-item{
            width:5px;
            margin: 1px 6px;
        }
    }
}
</style>
