import { Slot } from "../Slot";
import { MeshAttachment } from "../attachment/MeshAttachment";
import { MixBlend, binarySearch, Curve, readCurve, arrayCopy, setArraySize } from "./utils";
import { VertexAttachment } from "../attachment/Attachment";
import { BaseTrack } from "./BaseTrack";

export interface IDeformAniData {
    curve: "stepped" | [number, number, number, number]
    offset: number,//没有就是0
    time: number,
    vertices: number[]
}
export class SpineDeformAniTrack extends BaseTrack {
    curve: Curve
    public frameTimes: Float32Array
    private frameVertices: Float32Array[];
    constructor(
        /**
         * 需要改变属性的节点对象
         */
        public slot: Slot,
        /**
         * 皮肤上获取的，slot可能不一致
         */
        public attachment: MeshAttachment,
        /**
         * 记录所有时间的数组，按顺序递增，没有的按最后一个时间的数据
         */
        public times: IDeformAniData[],
    ) {
        super();
        this._instanceType = "SpineDeformAniTrack";

        var weighted = attachment.bones != null;
        var vertices = attachment.vertices;
        var deformLength = weighted ? vertices.length / 3 * 2 : vertices.length;
        this.frameTimes = new Float32Array(times.length)
        this.frameVertices = new Array(times.length);
        this.curve = new Curve(times.length);
        var frameIndex = 0;
        for (var j = 0; j < times.length; j++) {
            let valueMap = times[j];
            var deform = void 0;
            var verticesValue = valueMap.vertices || null;
            if (verticesValue == null)
                deform = weighted ? new Float32Array(deformLength) : vertices;
            else {
                deform = new Float32Array(deformLength);
                var start = valueMap.offset || 0
                arrayCopy(verticesValue, 0, deform, start, verticesValue.length);
                if (!weighted) {
                    for (var i = 0; i < deformLength; i++)
                        deform[i] += vertices[i];
                }
            }
            // timeline.setFrame(frameIndex, valueMap.time, deform);
            this.frameTimes[frameIndex] = valueMap.time || 0;
            this.frameVertices[frameIndex] = deform;
            readCurve(valueMap, this.curve, frameIndex);
            frameIndex++;
        }

    }
    //到时后两个参数直接赋值track吧
    setValue(time: number, alpha: number = 1, blend: MixBlend = MixBlend.replace) {
        var slotAttachment = this.slot.getAttachment();
        if (!(slotAttachment instanceof VertexAttachment) || !slotAttachment.applyDeform(this.attachment))
            return;
        var verticesArray = this.slot.deform;
        if (verticesArray.length == 0)
            blend = MixBlend.setup;
        var frameVertices = this.frameVertices;
        var vertexCount = frameVertices[0].length;
        var frames = this.frameTimes;
        if (time < frames[0]) {
            var vertexAttachment = slotAttachment;
            switch (blend) {
                case MixBlend.setup:
                    verticesArray.length = 0;
                    return;
                case MixBlend.first:
                    if (alpha == 1) {
                        verticesArray.length = 0;
                        break;
                    }
                    var vertices_1 = setArraySize(verticesArray, vertexCount);
                    if (vertexAttachment.bones == null) {
                        var setupVertices = vertexAttachment.vertices;
                        for (var i = 0; i < vertexCount; i++)
                            vertices_1[i] += (setupVertices[i] - vertices_1[i]) * alpha;
                    }
                    else {
                        alpha = 1 - alpha;
                        for (var i = 0; i < vertexCount; i++)
                            vertices_1[i] *= alpha;
                    }
            }
            return;
        }
        var vertices = setArraySize(verticesArray, vertexCount);
        if (time >= frames[frames.length - 1]) {
            var lastVertices = frameVertices[frames.length - 1];
            if (alpha == 1) {
                if (blend == MixBlend.add) {
                    var vertexAttachment = slotAttachment;
                    if (vertexAttachment.bones == null) {
                        var setupVertices = vertexAttachment.vertices;
                        for (var i = 0; i < vertexCount; i++) {
                            vertices[i] += lastVertices[i] - setupVertices[i];
                        }
                    }
                    else {
                        for (var i = 0; i < vertexCount; i++)
                            vertices[i] += lastVertices[i];
                    }
                }
                else {
                    arrayCopy(lastVertices, 0, vertices, 0, vertexCount);
                }
            }
            else {
                switch (blend) {
                    case MixBlend.setup: {
                        var vertexAttachment_1 = slotAttachment;
                        if (vertexAttachment_1.bones == null) {
                            var setupVertices = vertexAttachment_1.vertices;
                            for (var i = 0; i < vertexCount; i++) {
                                var setup = setupVertices[i];
                                vertices[i] = setup + (lastVertices[i] - setup) * alpha;
                            }
                        }
                        else {
                            for (var i = 0; i < vertexCount; i++)
                                vertices[i] = lastVertices[i] * alpha;
                        }
                        break;
                    }
                    case MixBlend.first:
                    case MixBlend.replace:
                        for (var i = 0; i < vertexCount; i++)
                            vertices[i] += (lastVertices[i] - vertices[i]) * alpha;
                    case MixBlend.add:
                        var vertexAttachment = slotAttachment;
                        if (vertexAttachment.bones == null) {
                            var setupVertices = vertexAttachment.vertices;
                            for (var i = 0; i < vertexCount; i++) {
                                vertices[i] += (lastVertices[i] - setupVertices[i]) * alpha;
                            }
                        }
                        else {
                            for (var i = 0; i < vertexCount; i++)
                                vertices[i] += lastVertices[i] * alpha;
                        }
                }
            }
            return;
        }
        //找的后一帧时间
        var frame = binarySearch(frames, time);
        var prevVertices = frameVertices[frame - 1];
        var nextVertices = frameVertices[frame];
        var frameTime = frames[frame];
        var percent = this.curve.getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime));
        if (alpha == 1) {
            if (blend == MixBlend.add) {
                var vertexAttachment = slotAttachment;
                if (vertexAttachment.bones == null) {
                    var setupVertices = vertexAttachment.vertices;
                    for (var i = 0; i < vertexCount; i++) {
                        var prev = prevVertices[i];
                        vertices[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i];
                    }
                }
                else {
                    for (var i = 0; i < vertexCount; i++) {
                        var prev = prevVertices[i];
                        vertices[i] += prev + (nextVertices[i] - prev) * percent;
                    }
                }
            }
            else {
                for (var i = 0; i < vertexCount; i++) {
                    var prev = prevVertices[i];
                    vertices[i] = prev + (nextVertices[i] - prev) * percent;
                }
            }
        }
        else {
            switch (blend) {
                case MixBlend.setup: {
                    var vertexAttachment_2 = slotAttachment;
                    if (vertexAttachment_2.bones == null) {
                        var setupVertices = vertexAttachment_2.vertices;
                        for (var i = 0; i < vertexCount; i++) {
                            var prev = prevVertices[i], setup = setupVertices[i];
                            vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha;
                        }
                    }
                    else {
                        for (var i = 0; i < vertexCount; i++) {
                            var prev = prevVertices[i];
                            vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha;
                        }
                    }
                    break;
                }
                case MixBlend.first:
                case MixBlend.replace:
                    for (var i = 0; i < vertexCount; i++) {
                        var prev = prevVertices[i];
                        vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha;
                    }
                    break;
                case MixBlend.add:
                    var vertexAttachment = slotAttachment;
                    if (vertexAttachment.bones == null) {
                        var setupVertices = vertexAttachment.vertices;
                        for (var i = 0; i < vertexCount; i++) {
                            var prev = prevVertices[i];
                            vertices[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha;
                        }
                    }
                    else {
                        for (var i = 0; i < vertexCount; i++) {
                            var prev = prevVertices[i];
                            vertices[i] += (prev + (nextVertices[i] - prev) * percent) * alpha;
                        }
                    }
            }
        }


    }
}

