import { BaseTrack } from "./BaseTrack";
import { MixBlend, MixDirection, arrayCopy, newArray } from "./utils";
import { Slot } from "../Slot";

export interface IDrawOrderAniData {
    time: number,
    offsets?: {
        slot: string,
        offset: number
    }[],
    //将上面的offsets转成下面这个
    drawOrder?: number[]
}

export class DrawOrderAniTrack extends BaseTrack {

    constructor(
        public slots: Slot[],
        public drawOrder: Slot[],
        public times: IDrawOrderAniData[]
    ) {
        super();
        this._instanceType = "DrawOrderAniTrack";
    }
    setValue(time: number, alpha: number = 1, blend: MixBlend = MixBlend.replace, direction: MixDirection = MixDirection.in) {
        var drawOrder = this.drawOrder;
        var slots = this.slots;
        if (direction == MixDirection.out && blend == MixBlend.setup) {
            arrayCopy(slots, 0, drawOrder, 0, slots.length);
            return;
        }
        var frames = this.times;
        if (time < frames[0].time) {
            if (blend == MixBlend.setup || blend == MixBlend.first)
                arrayCopy(slots, 0, drawOrder, 0, slots.length);
            return;
        }
        var frame = 0;
        if (time >= frames[frames.length - 1].time)
            frame = frames.length - 1;
        else
            frame = binarySearch(frames, time) - 1;
        var drawOrderToSetupIndex = frames[frame].drawOrder;
        if (!drawOrderToSetupIndex)
            arrayCopy(slots, 0, drawOrder, 0, slots.length);
        else {
            for (var i = 0, n = drawOrderToSetupIndex.length; i < n; i++)
                drawOrder[i] = slots[drawOrderToSetupIndex[i]];
        }
    }
    /**
     * 层级需要加个重置方法，因为部分动画并没有层级时间轴，会导致当前动画层级根据上一个动画来
     */
    resetValue() {
        this.slots.forEach((s, i) => {
            this.drawOrder[i] = s;
        })
    }
}
function binarySearch(values: IDrawOrderAniData[], target: number) {
    var low = 0;
    var high = values.length - 2;
    if (high == 0) return 1;
    var current = high >>> 1;
    while (true) {
        if (values[current + 1].time <= target)
            low = current + 1;
        else
            high = current;
        if (low == high)
            return low + 1;
        current = (low + high) >>> 1;
    }
};