;
/*
 * 原项目地址:https://github.com/AnCIity/ui-login-canvas
 * 原作者:AnCity
 * 修改:yhl452493373
 * 不依赖外部库，仅使用canvas
 */
(function () {
    /**
     * 生成颜色范围内随机色
     * https://stackoverflow.com/questions/25193110/random-color-between-two-selected-rgb-colors-javascript 最下方答案
     * @param color1 颜色1
     * @param color2 颜色2
     * @private
     */
    var randomColor = function (color1, color2) {
        this.regs = {
            "hex3": /^#([a-f\d])([a-f\d])([a-f\d])$/i,
            "hex6": /^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,
            "rgb": /^rgb\s*\(\s*([\d.]+%?)\s*,\s*([\d.]+%?)\s*,\s*([\d.]+%?)\s*\)$/
        };

        this.colorObject1 = this.getValues(color1);
        this.colorObject2 = this.getValues(color2);
    }

    /**
     * 将传颜色字符串转为带rgb数值的对象
     * @param color 颜色
     * @returns 转换结果，若为false，则转换失败，说明颜色字符串错误
     */
    randomColor.prototype.getValues = function (color) {
        var values = false;
        for (var prop in this.regs) {
            // noinspection JSUnfilteredForInLoop
            if (this.regs[prop].test(color)) {
                values = {};
                // noinspection JSUnfilteredForInLoop
                values.r = color.replace(this.regs[prop], "$1");
                // noinspection JSUnfilteredForInLoop
                values.g = color.replace(this.regs[prop], "$2");
                // noinspection JSUnfilteredForInLoop
                values.b = color.replace(this.regs[prop], "$3");
                if (prop === "rgb") {
                    values.r = Number(values.r);
                    values.g = Number(values.g);
                    values.b = Number(values.b);
                } else {
                    values.r = parseInt(values.r, 16);
                    values.g = parseInt(values.g, 16);
                    values.b = parseInt(values.b, 16);
                }
                break;
            }
        }
        return values;
    }

    /**
     * 生成随机色
     * @returns {string|boolean}
     */
    randomColor.prototype.getColor = function () {
        if (this.colorObject1 && this.colorObject2) {
            var random = Math.random();
            var r = randomColor.getRandom(this.colorObject1.r, this.colorObject2.r, random);
            var g = randomColor.getRandom(this.colorObject1.g, this.colorObject2.g, random);
            var b = randomColor.getRandom(this.colorObject1.b, this.colorObject2.b, random);
            return "#" + r + g + b;
        }
        return false;
    };

    /**
     * 字符串补位，如将a，左侧补位变为0a
     *
     * @param str 需要补位的字符串
     * @param pad_length 补位后字符串的长度
     * @param pad_string 用于补位的字符串
     * @param pad_type 补位方式
     * @returns {string|*}
     * @private
     */
    randomColor.str_pad = function (str, pad_length, pad_string, pad_type) {
        var len = pad_length - str.length;
        if (len < 0) {
            return str
        }
        var pad = new Array(len + 1).join(pad_string);
        if (pad_type === "STR_PAD_LEFT") {
            return pad + str
        }
        return str + pad;
    }

    /**
     * 获取R，G，B其中之一随机色范围
     * @param color1 颜色1 R，G，B其中之一
     * @param color2 颜色2 R，G，B其中之一
     * @param percent 随机到的范围百分比
     * @returns {string|*}
     * @private
     */
    randomColor.getRandom = function (color1, color2, percent) {
        var color = color1 + Math.floor((color2 - color1) * percent);
        if (color < 0)
            color = 0;
        return randomColor.str_pad(color.toString(16), 2, "0", "STR_PAD_LEFT");
    }

    /**
     *  定义插件对象
     *
     * @param options {{
     *     canvas:HTMLCanvasElement
     *     width:number?,
     *     height:number?,
     *     ballNumber:number,
     *     ballMinSize:number,
     *     ballMaxSize:number,
     *     fps:number,
     *     color:string|[string,string]
     * }}
     */
    var particle = function (options) {
        this.ball = [];
        this.canvas = options.canvas;
        if (this.canvas.style.width !== '' || this.canvas.style.height !== '') {
            throw new Error('请勿在粒子动效的canvas上的style中添加width，仅允许通过参数传递')
        } else if (this.canvas.getAttribute('width') != null || this.canvas.getAttribute('height') != null) {
            throw new Error('请勿在粒子动效的canvas上的添加width、height属性，仅允许通过参数传递')
        }
        this.canvas.width = options.width || parseInt(getComputedStyle(this.canvas).width);
        this.canvas.height = options.height || parseInt(getComputedStyle(this.canvas).height);
        this.canvas.style.width = this.canvas.width + 'px';
        this.canvas.style.height = this.canvas.height + 'px';
        this.context = this.canvas.getContext('2d');
        this.ballNumber = options.ballNumber
        this.ballMinSize = options.ballMinSize;
        this.ballMaxSize = options.ballMaxSize;
        this.color = options.color;
        if (this.color instanceof Array) {
            if (this.color.length > 1)
                this.randomColor = new randomColor(this.color[0], this.color[1]);
            else
                this.color = options.color[0];
        }
        var that = this;
        this.__draw(true);
        self.setInterval(function () {
            that.__draw(false);
        }, 1000 / options.fps);
    };

    /**
     * 插件重设方法
     *
     * @param options {{
     *     width:number?,
     *     height:number?,
     *     ballNumber:number?,
     *     ballMinSize:number?,
     *     ballMaxSize:number?,
     *     color:string?
     * }}
     */
    particle.prototype.reDraw = function (options) {
        if (options) {
            if (options.hasOwnProperty('width')) {
                this.canvas.width = options.width;
                this.canvas.style.width = this.canvas.width+'px';
            }
            if (options.hasOwnProperty('height')) {
                this.canvas.height = options.height;
                this.canvas.style.height = this.canvas.height+'px';
            }
            if (options.hasOwnProperty('ballNumber'))
                this.ballNumber = options.ballNumber;
            if (options.hasOwnProperty('ballMinSize'))
                this.ballMinSize = options.ballMinSize;
            if (options.hasOwnProperty('ballMaxSize'))
                this.ballMaxSize = options.ballMaxSize;
            if (options.hasOwnProperty('color')) {
                this.color = options.color;
                if (this.color instanceof Array) {
                    if (this.color.length > 0)
                        this.randomColor = new randomColor(this.color[0], this.color[1]);
                    else
                        this.color = options.color[0];
                }
            }
            this.__draw(true);
        } else {
            this.canvas.style.width = '';
            this.canvas.style.height = '';
            this.canvas.width='';
            this.canvas.height='';
            this.canvas.width = parseInt(getComputedStyle(this.canvas).width);
            this.canvas.height = parseInt(getComputedStyle(this.canvas).height);
            this.canvas.style.width = this.canvas.width+'px';
            this.canvas.style.height = this.canvas.height+'px';
            this.__draw(false);
        }
    }

    /**
     * 绘制点
     * @param force 是否强制绘制。为true时，会清空并重新生成所有点并重新绘制点，用于初始化；为false时，不会重新生成点，会清空并重绘点
     * @private
     */
    particle.prototype.__draw = function (force) {
        //初始化小球数据
        if (force) {
            this.ball = [];
            this.__ballConfigure();
        }

        //重绘canvas
        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
        var i = 0;
        while (i < this.ballNumber) {
            //绘制小球
            this.context.beginPath();
            if (this.ball[i].size > 0)
                this.context.arc(this.ball[i].x, this.ball[i].y, this.ball[i].size, 0, Math.PI * 2, true);
            this.context.closePath();
            this.context.fillStyle = this.ball[i].color;
            this.context.fill();
            //赋予小球加速度
            this.ball[i].x += this.ball[i].vx;
            this.ball[i].y += this.ball[i].vy;
            this.ball[i].size -= this.ball[i].sizeReduce;
            if (this.ball[i].size < this.ballMinSize || this.ball[i].size <= 0) {
                this.ball[i].size = this.ballMinSize;
                this.ball[i].sizeReduce *= -1;
                this.ball[i].color = this.__randomColor();
            } else if (this.ball[i].size > this.ballMaxSize) {
                this.ball[i].size = this.ballMaxSize;
                this.ball[i].sizeReduce *= -1;
            }
            //防止小球出界
            if (this.ball[i].x <= 0 || this.ball[i].x >= this.canvas.width) {
                this.ball[i].vx = -this.ball[i].vx;
            }
            if (this.ball[i].y <= 0 || this.ball[i].y >= this.canvas.height) {
                this.ball[i].vy = -this.ball[i].vy;
            }
            i++;
        }
    };

    /**
     * 根据配置生成小球并放入数组
     * @private
     */
    particle.prototype.__ballConfigure = function () {
        //获取随机小球配置
        var j = 0;
        while (j < this.ballNumber) {
            this.ball[j] = {
                x: Math.ceil(Math.random() * this.canvas.width),
                y: Math.ceil(Math.random() * this.canvas.height),
                vx: particle.__noZeroRandom(-1, 1),
                vy: particle.__noZeroRandom(-1, 1),
                size: particle.__noZeroRandom(this.ballMinSize, this.ballMaxSize),
                color: this.__randomColor(),
                sizeReduce: 0.1
            };
            j++;
        }
    };

    /**
     * 利用 randomColor 生成范围随机色，如果没有范围，则返回指定色
     *
     * @returns {*|string|string[]}
     */
    particle.prototype.__randomColor = function () {
        return this.color instanceof Array ? this.randomColor.getColor() : this.color;
    }

    /**
     * 生成不为0随机数,直接挂载到对象上，而非实例上
     * @param min 最小
     * @param max 最大
     * @returns {number} 生成值
     * @private
     */
    particle.__noZeroRandom = function (min, max) {
        var k = 0;
        while (k === 0) {
            k = Math.floor(Math.random() * (max - min + 1) + min);
        }
        return k;
    }


    window.Particle = particle;
})();