
import { IAnimationTrack } from "../AnimationClip";
import { HashObject } from "../HashObject";
import { Sprite } from "../display";
import { Texture } from "../texture";



interface LottieData {
    "fr": number,//珍露  30  60等
    "ip": number,//开始帧
    "op": number,//结束帧
    "w": number,//宽度
    "h": number,//高度
    "nm": string,//名字
    "layers": LayerData[],
    "assets"?: {
        "id": string,//图片id，与layers里的refId对应
        "w": number,
        "h": number,
        "p": string,//base64数据
    }[],
    "textures"?: { [key: string]: Texture }//缓存的贴图，为了上面的assets里的图片数据，不进全局缓存，
}
interface LayerData {
    "ind": number,//id唯一
    "ty": number,//类型，暂时只有2
    "nm": string//"owl_sleep.png",//暂时就是图片
    "refId": string,
    "parent"?: number,//父级id
    "ks": KsData;
    "ip": number,//开始帧
    "op": number,//结束帧
}
interface KsData {
    o: KeyData //透明度
    r: KeyData //旋转
    p: KeyData //位置
    a: KeyData //锚点
    s: KeyData //缩放
}
interface KeyData {
    a: number,//貌似没用
    k: KeyAniData[] | number[] | number,
    x: string,//可能有表达式
}

export interface KeyAniData {
    t: number,
    s: number[],

    i: { x: number | number[], y: number | number[] },
    o: { x: number | number[], y: number | number[] },

    to: number[],
    ti: number[],

    h: number,//暂时用是否存在判断。有标识瞬切，不缓动，待测试

    //后面记录的东西
    bezierData?,//to存在时的贝塞尔数据
    fnc?,//贝塞尔函数，可能是数组，

}


enum LoopType {
    pingpong = "pingpong",
    cycle = "cycle",
}

interface LoopData {
    loopInOrOut: 0 | 1 | 2,//0表示没有,1表示in前面循环，2表示out后续循环
    type: LoopType,
    duration: number,//为0表示全循环
}
/**
 * 内部使用,不对外导出,这里track的时间统统是帧时间,所以对于AnimationClip的update传的时间做换算
 * 注意lottie的透明度是不影响子级的
 */
class LottieBaseTrack extends HashObject implements IAnimationTrack {
    constructor(
        protected obj: Sprite,
        private times?: KeyAniData[],
        private loop?: LoopData
    ) {
        super()
    }
    setValue(time: number) {
        if (this.loop && this.loop.loopInOrOut) {
            time = (this.loop.loopInOrOut == 1 ? loopIn : loopOut)(this.loop.type, this.loop.duration, this.times, time)
        }
        //判断始末就行了
        time = Math.max(time, this.times[0].t)
        time = Math.min(time, this.times[this.times.length - 1].t);
        //
    }
    /**
     * 因为有些表达式
     * @param time 
     */
    protected cacTrueTime(time: number) {
        if (this.loop && this.loop.loopInOrOut) {
            time = (this.loop.loopInOrOut == 1 ? loopIn : loopOut)(this.loop.type, this.loop.duration, this.times, time)
        }
        return time;
    }

    protected cacValue(time: number) {
        if (time <= this.times[0].t) return this.times[0].s;
        if (time >= this.times[this.times.length - 1].t) return this.times[this.times.length - 1].s;

    }

    // protected findIndex(time: number): number {

    //     var low = 0;
    //     var high = values.length - 2;
    //     if (high == 0) return step;
    //     var current = high >>> 1;
    //     while (true) {
    //         if (values[(current + 1) * step].t <= target)
    //             low = current + 1;
    //         else
    //             high = current;
    //         if (low == high)
    //             return (low + 1) * step;
    //         current = (low + high) >>> 1;
    //     }

    // }
    resetValue() {
        this.setValue(0)
    }
    destroy() {
        this.obj = null;
    }
}
/**
 * 部件的出场时间,就是个范围,
 * 每个对象都有,优先判断
 */
class LottieVisibleTrack extends LottieBaseTrack {
    constructor(
        obj: Sprite,
        private inTime: number,
        private outTime: number
    ) {
        super(obj)
    }
    setValue(time: number) {
        this.obj.visible = this.inTime <= time && this.outTime >= time
    }
}
/**
 * 透明度的变化
 * 有k值的才有
 */
class LottieAlpha extends LottieBaseTrack {
    constructor(
        obj: Sprite,
        times: KeyAniData[],
        loop: LoopData
    ) {
        super(obj, times, loop)
    }
    setValue(time: number) {

    }
}

function loopOut(type: LoopType, duration: number, keyframes: KeyAniData[], currentFrame: number) {
    var lastKeyFrame = keyframes[keyframes.length - 1].t;
    if (currentFrame <= lastKeyFrame) return currentFrame;

    if (!duration || duration > keyframes.length - 1) {
        duration = keyframes.length - 1;
    }
    var firstKeyFrame = keyframes[keyframes.length - 1 - duration].t;
    var cycleDuration = lastKeyFrame - firstKeyFrame;

    // var i, len, ret;
    if (type === 'pingpong') {
        var iterations = Math.floor((currentFrame - firstKeyFrame) / cycleDuration);
        if (iterations % 2 !== 0) {
            return cycleDuration - (currentFrame - firstKeyFrame) % cycleDuration + firstKeyFrame;
        }
    }
    //其他的再说
    // else if(){

    // }
    return (currentFrame - firstKeyFrame) % cycleDuration + firstKeyFrame;
}


//给出时间就行,自行判断是否计算，根据
function loopIn(type: LoopType, duration: number, keyframes: KeyAniData[], currentFrame: number) {
    var firstKeyFrame = keyframes[0].t;
    if (currentFrame >= firstKeyFrame) return currentFrame;
    //0时取全部
    if (!duration || duration > keyframes.length - 1) {
        duration = keyframes.length - 1;
    }
    var lastKeyFrame = keyframes[duration].t;
    var cycleDuration = lastKeyFrame - firstKeyFrame;

    // var i, len, ret;
    if (type === LoopType.pingpong) {
        var iterations = Math.floor((firstKeyFrame - currentFrame) / cycleDuration);
        if (iterations % 2 === 0) {
            return (firstKeyFrame - currentFrame) % cycleDuration + firstKeyFrame;
        }
    }
    //其他的再说
    // else if(){

    // }
    return cycleDuration - (firstKeyFrame - currentFrame) % cycleDuration + firstKeyFrame;
}