import { AnimationManager } from "../2d/AnimationManager";
import { AnimationClip } from "../2d/AnimationClip";
import { MixBlend, MixDirection } from "./animation/utils";
import { AttachmentAniTrack } from "./animation/AttachmentAniTrack";


export class SpineAniClip extends AnimationClip {

    alpha: number = 1;
    blend: MixBlend = MixBlend.replace;
    direction: MixDirection = MixDirection.in

    fromClip: SpineAniClip
    toClip: SpineAniClip

    /**
     * 已执行的过度时间
     */
    mixTime: number
    /**
     * 过度总时间，上一个和自身的过度总时间
     */
    mixDuration: number

    protected rectify() {
        if (!this.tracks || !this.tracks.length) return;


        for (var i = 0; i < this.tracks.length; i++) {
            //@ts-ignore
            this.tracks[i].setValue(this.curTime, this.alpha, this.blend, this.direction)
        }

        //设置相等
        this.lastTime = this.curTime;
    }
}


export class SpineAniManager extends AnimationManager {
    currentClip: SpineAniClip
    /**
     * 切换动画
     * 有切换闪帧问题时尝试setTimeout延时0后执行showAni，
     * 因为resetState更新的部分插槽初始值并不是0时间，所以延时到本帧结束，下帧开始前，利用下帧逻辑覆盖显示
     * @param name 
     * @param loops 
     * @param callback 
     * @param mix 带这个后，上一个动画的回调可能会失效，得看过度时间，对于有某些，a动画隐藏的皮肤，b动画没有处理该插槽，需要重置去掉a动画的效果,最好别赋值mix
     */
    showAni(name: string, loops: number = 0, callback?: (loop: number) => void, mix: number = 0) {
        //如果不设置过度
        if (!mix || !this.currentClip) {
            return super.showAni(name, loops, callback)
        }
        var from = this.currentClip;
        var to = this.getAniClipByName(name) as SpineAniClip
        if (!to) return null;
        //同一个动作
        if (from == to) {
            return super.showAni(name, loops, callback)
        }

        if (from.fromClip) {
            this.resetFrom(from.fromClip)
            from.fromClip = null;
        }
        to.mixTime = 0;
        to.mixDuration = mix;
        to.fromClip = from;
        (this.currentClip = to).startAniRange(0, undefined, loops, callback)
        //返回当前
        return this.currentClip;
    }

    update(deltaTime: number = 0.0167) {
        this.applyMixingFrom(this.currentClip, deltaTime, MixBlend.first);
        //更新过度的
        super.update(deltaTime)
    }

    private applyMixingFrom(to: SpineAniClip, deltaTime: number, blend: MixBlend) {
        if (!to) return
        var from = to.fromClip;
        if (!from) return;
        to.mixTime += deltaTime;
        // if (from.mixingFrom != null)
        //     this.applyMixingFrom(from, skeleton, blend);
        var mix = 0;
        if (to.mixDuration == 0) {
            mix = 1;
            if (blend == MixBlend.first) blend = MixBlend.setup;
        }
        else {
            mix = to.mixTime / to.mixDuration;
            if (mix > 1) mix = 1;
            if (blend != MixBlend.first) blend = from.blend;
        }
        to.alpha = mix;
        //执行赋值
        from.alpha = 1 - mix;
        from.blend = blend;

        if (from.alpha == 0) {
            this.resetFrom(from)
            //@ts-ignore 单独对attachMent的进行一次重置，因为本来就硬切，不会有太大影响
            to.fromClip.tracks.forEach((t: AttachmentAniTrack) => {
                if (t.instanceType == "AttachmentAniTrack") t.resetValue();
            })

            to.fromClip = null;
        }


    }
    private resetFrom(from: SpineAniClip) {
        //@ts-ignore
        from._isPlaying = false;
        from.alpha = 1;
        from.blend = MixBlend.replace;
    }
}