//对对象进行深度合并
export const assign = (v = {}, n = {}) => {
    let K = v;
    for (let key in n) {
        if (n.hasOwnProperty(key)) {
            const type = Object
                .prototype
                .toString
                .call(K[key]);
            if (K[key] && type === "[object Object]" || type === "[object Array]") {
                K[key] = assign(v[key], n[key]);
            } else {
                K[key] = n[key]
            }
        }
    }
    return K;
}
//对象深复制
export const depthCopy = obj => {
    if (obj === null || typeof obj !== 'object') 
        return obj;
    var cpObj = obj instanceof Array
        ? []
        : {};
    for (var key in obj) 
        cpObj[key] = depthCopy(obj[key]);
    return cpObj;
}
/**
 * 递归查找集合数据
 * @param {Object} set 需要取值的对象
 * @param {String} key 取值结构 data.list.a
 */
export const getSet = (set, key) => {
    key = (key + "").split(".");
    const obj = set[key.shift()];
    return key.length
        ? getSet(obj, key.join('.'))
        : obj;
}
/**
 * 设置集合数据
 * @param {*} set 接收数据对象
 * @param {*} key 取值结构 data.list.a
 * @param {*} data 数据
 */
export const setData = (set, key, data, fun) => {
    key = (key + "").split(".");
    const k = key.shift();
    set[k] = set[k] || {};
    if (key.length) {
        set[k] = setData(set[k], key.join('.'), data, fun);
    } else {
        set[k] = typeof fun == "function"
            ? fun(set[k], data)
            : data;
    }
    return set;
}
/**
 * @desc 贝塞尔曲线算法，包含了3阶贝塞尔
 */
export class Bezier {
    /**
     * @desc 获取点，这里可以设置点的个数
     * @param {number} num 点个数
     * @param {Array} p1 点坐标 起点
     * @param {Array} p2 点坐标 动态基点（可选）
     * @param {Array} p3 点坐标 动态基点（可选）
     * @param {Array} p4 点坐标 终点
     * 如果参数是 num, p1, p2 为一阶贝塞尔
     * 如果参数是 num, p1, c1, p2 为二阶贝塞尔
     * 如果参数是 num, p1, c1, c2, p2 为三阶贝塞尔
     */
    getBezierPoints(num = 100, p1, p2, p3, p4) {
        let func = null;
        const points = [];
        if (!p3 && !p4) {
            func = this.oneBezier;
        } else if (p3 && !p4) {
            func = this.twoBezier;
        } else if (p3 && p4) {
            func = this.threeBezier;
        }
        for (let i = 0; i < num; i++) {
            points.push(func(i / num, p1, p2, p3, p4));
        }
        if (p4) {
            points.push([...p4]);
        } else if (p3) {
            points.push([...p3]);
        }
        return points;
    }

    /**
     * @desc 一阶贝塞尔
     * @param {number} t 当前百分比
     * @param {Array} p1 起点坐标
     * @param {Array} p2 终点坐标
     */
    oneBezier(t, p1, p2) {
        const [x1, y1] = p1;
        const [x2, y2] = p2;
        let x = x1 + (x2 - x1) * t;
        let y = y1 + (y2 - y1) * t;
        return [x, y];
    }

    /**
     * @desc 二阶贝塞尔
     * @param {number} t 当前百分比
     * @param {Array} p1 起点坐标
     * @param {Array} p2 终点坐标
     * @param {Array} cp 控制点
     */
    twoBezier(t, p1, cp, p2) {
        const [x1, y1] = p1;
        const [cx, cy] = cp;
        const [x2, y2] = p2;
        let x = (1 - t) * (1 - t) * x1 + 2 * t * (1 - t) * cx + t * t * x2;
        let y = (1 - t) * (1 - t) * y1 + 2 * t * (1 - t) * cy + t * t * y2;
        return [x, y];
    }

    /**
     * @desc 三阶贝塞尔
     * @param {number} t 当前百分比
     * @param {Array} p1 起点坐标
     * @param {Array} p2 终点坐标
     * @param {Array} cp1 控制点1
     * @param {Array} cp2 控制点2
     */
    threeBezier(t, p1, cp1, cp2, p2) {
        const [x1, y1] = p1;
        const [x2, y2] = p2;
        const [cx1, cy1] = cp1;
        const [cx2, cy2] = cp2;
        let x =
            x1 * (1 - t) * (1 - t) * (1 - t) +
            3 * cx1 * t * (1 - t) * (1 - t) +
            3 * cx2 * t * t * (1 - t) +
            x2 * t * t * t;
        let y =
            y1 * (1 - t) * (1 - t) * (1 - t) +
            3 * cy1 * t * (1 - t) * (1 - t) +
            3 * cy2 * t * t * (1 - t) +
            y2 * t * t * t;
        return [x, y];
    }
}

export default new Bezier();