
import { Slot } from "../Slot";
import { MixBlend, binarySearch, Curve, readCurve } from "./utils";
import { SpineColor } from "../SpineColor";
import { BaseTrack } from "./BaseTrack";

export interface IColorAniData {
    curve: "stepped" | [number, number, number, number]
    color: string
    time: number
}
export class SpineColorAniTrack extends BaseTrack {
    resetValue(){
        this.slot.setToSetupPose()
    }
    private frames: Float32Array
    curve: Curve
    constructor(
        /**
         * 需要改变颜色的插槽
         */
        public slot: Slot,
        /**
         * 改一下到时记录进frams数组
         */
        times: IColorAniData[],
    ) {
        super();
        this._instanceType = "SpineColorAniTrack";
        let len = times.length
        this.frames = new Float32Array(len * SpineColorAniTrack.ENTRIES);
        this.curve = new Curve(len);
        var frameIndex = 0;
        for (var i = 0; i < len; i++) {
            var valueMap = times[i];
            var color = new SpineColor().setFromString(valueMap.color || "ffffffff");
            let fi = frameIndex * SpineColorAniTrack.ENTRIES;
            this.frames[fi] = valueMap.time || 0;
            this.frames[fi + SpineColorAniTrack.R] = color.r;
            this.frames[fi + SpineColorAniTrack.G] = color.g;
            this.frames[fi + SpineColorAniTrack.B] = color.b;
            this.frames[fi + SpineColorAniTrack.A] = color.a;
            readCurve(valueMap, this.curve, frameIndex);
            frameIndex++;
        }
    }

    setValue(time: number, alpha: number = 1, blend: MixBlend = MixBlend.replace) {
        var slot = this.slot;
        var frames = this.frames;
        if (time < frames[0]) {
            switch (blend) {
                case MixBlend.setup:
                    slot.color.setFromColor(slot.data.sColor);
                    return;
                case MixBlend.first:
                case MixBlend.replace:
                    var color = slot.color, setup = slot.data.sColor;
                    color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, (setup.a - color.a) * alpha);
            }
            return;
        }
        var r = 0, g = 0, b = 0, a = 0;
        if (time >= frames[frames.length - SpineColorAniTrack.ENTRIES]) {
            var i = frames.length;
            r = frames[i + SpineColorAniTrack.PREV_R];
            g = frames[i + SpineColorAniTrack.PREV_G];
            b = frames[i + SpineColorAniTrack.PREV_B];
            a = frames[i + SpineColorAniTrack.PREV_A];
        }
        else {
            var frame = binarySearch(frames, time, SpineColorAniTrack.ENTRIES);
            r = frames[frame + SpineColorAniTrack.PREV_R];
            g = frames[frame + SpineColorAniTrack.PREV_G];
            b = frames[frame + SpineColorAniTrack.PREV_B];
            a = frames[frame + SpineColorAniTrack.PREV_A];
            var frameTime = frames[frame];
            var percent = this.curve.getCurvePercent(frame / SpineColorAniTrack.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + SpineColorAniTrack.PREV_TIME] - frameTime));
            r += (frames[frame + SpineColorAniTrack.R] - r) * percent;
            g += (frames[frame + SpineColorAniTrack.G] - g) * percent;
            b += (frames[frame + SpineColorAniTrack.B] - b) * percent;
            a += (frames[frame + SpineColorAniTrack.A] - a) * percent;
        }
        if (alpha == 1)
            slot.color.set(r, g, b, a);
        else {
            var color = slot.color;
            if (blend == MixBlend.setup)
                color.setFromColor(slot.data.sColor);
            color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);
        }
    }
    static ENTRIES = 5;
    static PREV_TIME = -5;
    static PREV_R = -4;
    static PREV_G = -3;
    static PREV_B = -2;
    static PREV_A = -1;
    static R = 1;
    static G = 2;
    static B = 3;
    static A = 4;
}