

export function buildBezierProps(pt1, pt2, pt3, pt4, startIndex, endIndex, points, fnc, limit?: number) {
    var bezierData = buildBezierData(pt1, pt2, pt3, pt4);
    //处理完所有的点
    for (var i = startIndex; i < endIndex; i++) {
        if (limit) {
            //小于0的不算了，浪费时间
            if (i < 0) continue;
            //超出的也不要了
            if (i >= limit) break;//遇到那种
        }
        var perc = fnc((i - startIndex) / (endIndex - startIndex));
        var distanceInLine = bezierData.segmentLength * perc;
        if (perc == 0) {
            points[i] = bezierData.points[0].point;
            continue;
        }
        //找最近的点
        points[i] = findNearest(distanceInLine, bezierData.points);
    }
}

function findNearest(distanceInLine: number, bezierDataPoints: PointData[]) {
    for (var i = 0; i < bezierDataPoints.length; i++) {
        var preLength = bezierDataPoints[i].preLength;
        if (distanceInLine < preLength) {//前一帧后当前帧做补间，且i肯定不会为0，因为distanceInLine不会小于0；
            var segmentPerc = (distanceInLine - bezierDataPoints[i - 1].preLength) / bezierDataPoints[i].partialLength;
            var kLen = bezierDataPoints[i - 1].point.length;
            var newValue = [];
            for (var k = 0; k < kLen; k += 1) {
                newValue[k] = bezierDataPoints[i - 1].point[k] + (bezierDataPoints[i].point[k] - bezierDataPoints[i - 1].point[k]) * segmentPerc;
            }
            return newValue;//取补间
        }
    }
    //没有返回最后一个
    return bezierDataPoints[bezierDataPoints.length - 1].point;
}

var storedData = {};
function buildBezierData(pt1, pt2, pt3, pt4): BezierData {
    var bezierName = (pt1[0] + '_' + pt1[1] + '_' + pt2[0] + '_' + pt2[1] + '_' + pt3[0] + '_' + pt3[1] + '_' + pt4[0] + '_' + pt4[1]).replace(/\./g, 'p');
    if (!storedData[bezierName]) {
        var curveSegments = 150//defaultCurveSegments;
        var k, i, len;
        var ptCoord, perc, addedLength = 0;
        var ptDistance;
        var point, lastPoint = null;
        if (pt1.length === 2 && (pt1[0] != pt2[0] || pt1[1] != pt2[1]) && pointOnLine2D(pt1[0], pt1[1], pt2[0], pt2[1], pt1[0] + pt3[0], pt1[1] + pt3[1]) && pointOnLine2D(pt1[0], pt1[1], pt2[0], pt2[1], pt2[0] + pt4[0], pt2[1] + pt4[1])) {
            curveSegments = 2;
            //这种情况只会生成两个点
        }
        var bezierData = {
            segmentLength: 0,
            points: new Array(curveSegments)
        }
        len = pt3.length;
        for (k = 0; k < curveSegments; k += 1) {
            point = new Array(len);
            perc = k / (curveSegments - 1);
            ptDistance = 0;
            for (i = 0; i < len; i += 1) {
                ptCoord = Math.pow(1 - perc, 3) * pt1[i] + 3 * Math.pow(1 - perc, 2) * perc * (pt1[i] + pt3[i]) + 3 * (1 - perc) * Math.pow(perc, 2) * (pt2[i] + pt4[i]) + Math.pow(perc, 3) * pt2[i];
                point[i] = ptCoord;
                if (lastPoint !== null) {
                    ptDistance += Math.pow(point[i] - lastPoint[i], 2);
                }
            }
            ptDistance = Math.sqrt(ptDistance);
            addedLength += ptDistance;
            bezierData.points[k] = {
                partialLength: ptDistance,
                preLength: addedLength,//记录一下前面所有的总长
                point
            }
            lastPoint = point;
        }
        bezierData.segmentLength = addedLength;
        storedData[bezierName] = bezierData;
    }
    return storedData[bezierName];
}

interface PointData {
    point: number[],
    partialLength: number,
    preLength: number,
}

interface BezierData {
    segmentLength: number,
    points: PointData[]
}

function pointOnLine2D(x1, y1, x2, y2, x3, y3) {
    var det1 = (x1 * y2) + (y1 * x3) + (x2 * y3) - (x3 * y2) - (y3 * x1) - (x2 * y1);
    return det1 > -0.001 && det1 < 0.001;
}