
// 节流 类
export default class Throttle  {

    /* 被创建的时候触发 */
    constructor(obj){

        obj = obj || {};

        // 兼容参数
        for (let key in Throttle.params) {
            if (Throttle.params.hasOwnProperty(key) && obj[key] === undefined) {
                obj[key] = Throttle.params[key];
            }
        }

        // 设置为 config
        this.config = obj || {};

        this.supper = this.hook[this.config.type];
    }

    /* 销毁 */
    destroy = ()=>{

        clearTimeout(this.config.time);
        clearTimeout(this.time);

        this.config = null;

    };

    /* 类型的钩子 */
    hook  = {
        'queue': (...data) => {
            if (!this.config) return;
            // 清楚上一次的计时器
            clearTimeout(this.time);
            // 获取 队列数据
            let count = (this.config.queue || []).length;
            // 是否 处于运行中
            if (
                (
                    this.config.running
                    ||
                    (!this.config.first && count === 0)
                )
            ) {
                // 设置为执行中
                this.config.running = true;
                // 添加进入队列
                this.addQueue(data);
                // 等待执行
                return this.time = setTimeout(()=>{
                    if (!this.config) return;
                    // 执行 函数
                    this.checkHandle(this.getQueue(this.config.point));
                    // 记录标记结束
                    this.config.running = false;
                    // 清空队列
                    return this.clearQueue();
                },this.config.delay);

            } else {
                // 打上标记
                this.config.running = true;
                // 执行 函数
                this.checkHandle(data);
                // 开启计时器
                return this.time = setTimeout(()=>{
                    // 记录标记结束
                    this.config.running = false;
                    // 清空队列
                    return this.clearQueue();
                },this.config.delay);
            }
        },
        'wait':(...data) => {
            if (!this.config) return;
            let count = (this.config.queue || []).length;
            if (this.config.running)  {
                // 添加 队列
                return this.addQueue(data);
            } else {
                // 打上标记
                this.config.running = true;

                if ((this.config.first && count === 0)) {
                    // 执行 函数
                    this.checkHandle(data);
                }

                // 向队列加入 一条数据
                this.addQueue(data);

                // 开启计时器
                return this.time = setTimeout(()=>{
                    if (!this.config) return;
                    // 执行 函数
                    this.checkHandle(this.getQueue(this.config.point));
                    // 记录标记结束
                    this.config.running = false;
                    // 清空队列
                    return this.clearQueue();
                },this.config.delay);
            }



        },
        'queueWait':(...data) => {
            if (!this.config) return;
            // 清楚上一次的计时器
            clearTimeout(this.time);
            // 获取 队列数据
            let count = (this.config.queue || []).length;
            // 设置时间戳 并获取是否 超过了这个时间段
            let next = this.setCurrTime();
            // 是否 处于运行中
            if (
                (
                    this.config.running
                    ||
                    (this.config.first && count === 0)
                )
                &&
                !next
            ) {
                // 设置为执行中
                this.config.running = true;
                // 添加进入队列
                this.addQueue(data);
                // 等待执行
                return this.time = setTimeout(()=>{
                    if (!this.config) return;
                    // 执行 函数
                    this.checkHandle(this.getQueue(this.config.point));
                    // 记录标记结束
                    this.config.running = false;
                    // 清空队列
                    return this.clearQueue();
                },this.config.delay);

            } else {
                // 打上标记
                this.config.running = true;
                // 执行 函数
                this.checkHandle(data);
                // 开启计时器
                return this.time = setTimeout(()=>{
                    if (!this.config) return;
                    // 记录标记结束
                    this.config.running = false;
                    // 清空队列
                    return this.clearQueue();
                },this.config.delay);
            }
        },
        'implement':(...data)=>{
            // 清楚上一次的计时器
            clearTimeout(this.time);
            // 获取 队列数据
            let count = (this.config.queue || []).length;
            // 是否 处于运行中
            if (
                (
                    this.config.running
                    ||
                    (!this.config.first && count === 0)
                )
            ) {
                // 设置为执行中
                this.config.running = true;
                // 添加进入队列
                this.addQueue(data);
                // 等待执行
                return this.time = setTimeout(()=>{
                    if (!this.config) return;
                    // 记录标记结束
                    this.config.running = false;
                    // 清空队列
                    return this.clearQueue();
                },this.config.delay);

            } else {
                // 打上标记
                this.config.running = true;
                // 执行 函数
                this.checkHandle(data);
                // 开启计时器
                return this.time = setTimeout(()=>{
                    if (!this.config) return;
                    // 记录标记结束
                    this.config.running = false;
                    // 清空队列
                    return this.clearQueue();
                },this.config.delay);
            }
        }

    };

    /* 添加队列 */
    addQueue = (params)=>{
        if (this.config.queue.length >= 10) {
            this.config.queue.shift();
        }
        return this.config.queue.push(params);
    };

    /* 清空队列 */
    clearQueue = ()=>{
        return this.config.queue = [];
    };

    /* 获取队列的数据 */
    getQueue = (point)=>{

        let count = this.config.queue.length;

        if (point >= 0) {
            point = point >= count?(count - 1):point;
        } else {
            point = count + point;
        }

        point = point <= 0? 0:point;

        return this.config.queue[point];
    };

    /* 执行函数 */
    checkHandle = (data)=>{
        return this.config.handle && this.config.handle.apply(this.config.call,data);
    };

    // 设置 时间戳
    setCurrTime = ()=>{
        let diff = this.config.beforeStamp;
        this.config.stamp = Throttle.getCurrTime();

        if (diff > 0) {
            diff = this.config.stamp - diff;
            diff = diff > this.config.mustDelay;
            this.config.beforeStamp = this.config.stamp;
        } else {
            diff = false;
        }

        return diff;
    };

    /* 获取时间戳 */
    static getCurrTime = function(){
        return new Date().getTime();
    };

    /* 执行钩子 */
    static handleHook = function(that,name){

        let value = undefined;
        if (typeof name === 'string'){
            if (name.indexOf('static::') >=0){
                name = name.replace('static::','') || '';
                if (Throttle[name]) {
                    value = typeof Throttle[name] === 'function'?Throttle[name](that):Throttle[name];
                }

            } else {
                if (that[name]) {
                    value = typeof that[name] === 'function'?that[name]():that[name];
                }
            }

            return value;
        } else {
            return typeof name === 'function'? name(that):name;
        }

    };

    /* 参数配置 */
    static params = {

        delay: 30,  // 多久执行一次

        mustDelay: 300, // 多久必须执行一次  queueWait 时 有效

        handle:undefined, // 执行 方法

        /*
         *  分为 三种状态
         *  	queue 队列执行 如果 没有队列 直接执行 如果 存在队列 将会 等到 该函数停止触发 后 执行 最后一次操作
         *		wait  等待模式 delay 指定时间 执行一次 如果 为 第一次 默认 直接触发
         *		queueWait 队列等待模式 delay 为 必须执行一次 后 等待 停止 点击之后 执行最后一次
         */
        type:'queue',   // 执行类型

        first: true,  // 第一次 是否 默认 开启执行

        call: undefined,  // 当前指向

        point: -1,  // 默认 将会执行 最后一次的 行为  -2 代表 倒数第 二个 正数代表 正数

        stamp:0,   // 当前时间戳

        beforeStamp:0, // 上一个时间戳

        running:false,  // 是否处于运行中

        queue: [],  // 队列

        time:''

    };


}

