import {emitNames} from '../enum/emit';
import ScrollApi from '../api/scroll';
import {
    Config,
    EventTypes,
    ListenerEventTarget,
    ScrollConfig,
    ScrollXConfig,
    ScrollYConfig
} from "../types/on";

export default <LibMixins>{

    computed:{
        scrollEl:function (){
            return this.$refs.scroll
        },
        scrollTakeEl:function (){
            return this.$refs.scrollTake;
        }
    },

    created(){

        let _scrollConfig:ScrollConfig = {
            look:false,
            stipitate:undefined,
            x:{
                x:0,
                width:0,
                actualWidth:0,
                maxScroll:0
            },
            y:{
                y:0,
                height:0,
                actualHeight:0,
                maxScroll:0
            }
        };
        let _scrollApi:ScrollApi | undefined = undefined;
        let _config:Config = {};
        let _listeners = undefined;

        this._config = _config;
        this._scrollApi = _scrollApi;
        this._listeners = _listeners;
        this._scrollConfig = _scrollConfig;

    },

    mounted(){
        // 执行安装
        return this.installScroll();
    },

    // 释放组件的时候触发
    beforeUnmount(){
        this._scrollApi && this._scrollApi.destroy();
        this._scrollConfig.stipitate&&clearTimeout(this._scrollConfig.stipitate);
        this._scrollApi = undefined;
        this.scrollEl && this._config.scrollUnique && this.removeEventListener(this.scrollEl,'scroll',this._config.scrollUnique);
    },

    methods:{
        // 配置滚动系列参数
        setScrollConfig(){
            if (this._scrollConfig.look) return;
            // 设置锁
            this._scrollConfig.look = true;
            // 配置 x 轴
            this.scrollX && this.setScrollAxisConfig('x');
            // 配置 y 轴
            this.scrollY && this.setScrollAxisConfig('y');
            // 帧频率不允许重复
            this._scrollConfig.stipitate = setTimeout(()=>{
                this._scrollConfig.stipitate = undefined;
                this._scrollConfig.look = false;
            },16.66);
        },

        // 配置单独轴系列参数
        setScrollAxisConfig(axis:'x' | 'y'){

            if (this.scrollEl === undefined || this.scrollTakeEl === undefined) return;

            let sizeKey: 'width' | 'height' = axis === 'x' ? 'width':'height';
            let actualKey : 'actualWidth' | 'actualHeight' = axis === 'x' ? 'actualWidth' :'actualHeight';
            let scrollAxis: 'scrollLeft' | 'scrollTop' = axis === 'x'? 'scrollLeft' :'scrollTop';
            let elSizeKey:'offsetWidth' | 'offsetHeight' = axis === 'x' ? 'offsetWidth' :'offsetHeight';

            // 设置配置文件
            // @ts-ignore
            this._scrollConfig[axis] = {
                [sizeKey]: this.scrollEl[elSizeKey] || 0,
                [axis]: this.scrollEl[scrollAxis] || 0,
                [actualKey]: this.scrollTakeEl[elSizeKey] || 0,
                maxScroll:0
            };
            //
            // // 设置最大滚动
            // @ts-ignore
            (this._scrollConfig[axis] as ScrollYConfig | ScrollXConfig).maxScroll = Math.max(0,this._scrollConfig[axis][actualKey] - this._scrollConfig[axis][sizeKey]);

        },
        // 安装
        installScroll(){

            // 设置当前的配置文件
            this.setScrollConfig();

            // 创建滚动Api
            if (this.scrollEl !== undefined) {
                this._scrollApi = new ScrollApi(this._scrollConfig,this.scrollEl);
            }

            // 如果存在此三种的任何一种 事件开启监听
            if (
                (this.$attrs[emitNames.onScroll]
                    ||
                    this.$attrs[emitNames.onScrollLower]
                    ||
                    this.$attrs[emitNames.onScrollUpper]) && this.scrollEl !== undefined
            ) {

                // 获取存储的唯一标识
                this._config.scrollUnique = this.addEventListener(this.scrollEl,'scroll',()=> this.onScroll());
            }

        },
        // 滚动时触发
        onScroll(){
            if (this.scrollEl) {
                // 设置配置
                this.setScrollConfig();

                if (this.$attrs[emitNames.onScrollUpper] || this.$attrs[emitNames.onScrollLower]) {


                    if (this.scrollY) {
                        if ( this.$attrs[emitNames.onScrollLower] && this.testScrollDistance('y','lowerThreshold','_lowerThresholdYStatus')) {
                            this.emitScrollLower('y');
                        } else if (this.$attrs[emitNames.onScrollUpper] && this.testScrollDistance('y','upperThreshold','_upperThresholdYStatus')) {
                            this.emitScrollUpper('y');
                        }
                    }

                    if (this.scrollX) {
                        if ( this.$attrs[emitNames.onScrollLower] && this.testScrollDistance('x','lowerThreshold','_lowerThresholdXStatus')) {
                            this.emitScrollLower('x');
                        } else if (this.$attrs[emitNames.onScrollUpper] && this.testScrollDistance('x','upperThreshold','_upperThresholdXStatus')) {
                            this.emitScrollUpper('x');
                        }
                    }

                }

                if(this.$attrs[emitNames.onScroll]) {
                    return this.emitScroll(this._scrollConfig);
                }

            }
        },

        // 校验是否满足条件
        testScrollDistance(axis:'x' | 'y',key:'lowerThreshold' | 'upperThreshold',testKey:'_lowerThresholdXStatus'|'_lowerThresholdYStatus'|'_upperThresholdXStatus'|'_upperThresholdYStatus'){


            if (
                this[key] !== undefined
                &&
                key === 'upperThreshold' ? this._scrollConfig[axis][axis] <= this[key] : this._scrollConfig[axis].maxScroll - this._scrollConfig[axis][axis] <= this[key]
            ) {

                if (!this[testKey]) {
                    this[testKey] = true;

                    return true;
                }

            } else {
                this[testKey] = false;
            }
            return false;

        },

        // 添加监听
        addEventListener:function <T extends EventTypes>(this:any,el:HTMLElement,event:T,target:ListenerEventTarget){
            // 如果没有监听器对象创建
            if (this._listeners === undefined) {
                this._listeners = {};
            }

            let unique:string = this.getUnique(event);

            this._listeners[unique] = target;

            if (window.addEventListener !== undefined) {
                el.addEventListener(event,target,{
                    passive:true
                });
            } else {
                // @ts-ignore 兼容策略
                el.attachEvent('on'+event,target,{
                    passive:true
                });
            }

            return unique;
        },

        // 移除兼容
        removeEventListener<K extends EventTypes>(this:any,el:HTMLElement,event:K,unique:string){
            if (this._listeners !== undefined && this._listeners[unique] !== undefined) {
                if (window.removeEventListener !== undefined) {
                    el.removeEventListener(event, this._listeners[unique]);
                } else {
                    // @ts-ignore 兼容策略
                    el.detachEvent('on' + event, this._listeners[unique]);
                }
                return  true;
            } else {
                return false;
            }
        },

        // 获取唯一值
        getUnique(value:string=''):string{
            return  new Date().getTime() + value  + Math.floor(Math.random() * 10000) ;
        }
    }
}