import { removeTweens } from "../module/ctrls";
import { RES } from "../module/RES";

interface LottieData {
    "fr": number,//珍露  30  60等
    "ip": number,//开始帧
    "op": number,//结束帧
    "w": number,//宽度
    "h": number,//高度
    "nm": string,//名字
    "layers": LayerData[]
}
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: { "t": number, "s": number[] }[] | number[] | number, x: string
}

/**
 * 记录的Tween数据
 */
interface TweenData {
    /**
     * 显示对象
     */
    dis: FYGE.DisplayObject
    /**
     * 数据
     */
    ks: { frame: number, value: number[] }[]
}


/**
 * 用Tween拼，后续计算帧数据记录
 * 临时写的，乱得很，以后再说
 */
export class Lottie extends FYGE.Container {
    rawData: LottieData;
    totalTime: number;
    totalFrames: number;
    /**
     * 锁步的时间间隔，按fps定,毫秒
     */
    private timeInterval;
    /**
     * 按帧率计算，60为1，30为2，
     */
    private deltaFrame: number = 1;

    get videoWidth(): number {
        return this.rawData && this.rawData.w;
    };
    get videoHeight(): number {
        return this.rawData && this.rawData.h;
    };
    /**
     * 供循环用
     */
    private loops: number
    private callback: () => void

    // private

    constructor(data) {
        super()
        this._instanceType = "MovieClip";
        //初始化
        if (data) {
            this.init(data);
        } else {
            this.totalFrames = 0;
        }
    }
    init(data: LottieData) {
        if (!data) return
        this.rawData = data;
        this.timeInterval = 1000 / data.fr;
        this.totalFrames = data.op - data.ip
        //间隔帧数，
        this.deltaFrame = 60 / data.fr;
        this.name = data.nm;

        this.initChildren();
    }
    private initChildren() {
        const hash = {};
        //初始化内容吧，假设所有资源已经加载好额
        var layers = this.rawData.layers.slice();
        //先筛选出所有不带parents,说明是顶级容器
        for (var i = layers.length - 1; i >= 0; i--) {
            let layer = layers[i];
            if (!layer.parent) {
                let c = this.addChild(new FYGE.Container())
                c.addChild(new FYGE.Sprite(RES.getRes(layer.nm) || RES.getRes(layer.refId + ".png")));
                c.name = layer.nm;
                //记录一下数据
                c["layerData"] = layer;
                //计入hash
                hash[layer.ind] = c;
                //从数组移除
                layers.splice(i, 1);
            }
        }
        //剩下就找爹了
        while (layers.length) {
            for (var j = layers.length - 1; j >= 0; j--) {
                let layer = layers[j];
                if (hash[layer.parent]) {//这种方式有问题，谁先添加有bug
                    let c = hash[layer.parent].addChildAt(new FYGE.Sprite(RES.getRes(layer.nm) || RES.getRes(layer.refId + ".png")), layer["td"] || 999);
                    c.name = layer.nm;
                    //记录一下数据
                    c["layerData"] = layer;
                    //计入hash
                    hash[layer.ind] = c;
                    //从数组移除
                    layers.splice(j, 1);
                }
            }
        }
        this.initState()
    }
    private initState(con = this.children) {
        for (var i = 0; i < con.length; i++) {
            // @ts-ignore
            var c: FYGE.Sprite = con[i];
            if (c["layerData"]) {
                //取第一个数据
                let data: LayerData = c["layerData"];
                //@ts-ignore 透明度
                c.alpha = data.ks.o.k[0] ? data.ks.o.k[0].s[0]/100 : data.ks.o.k / 100;
                //@ts-ignore 选转
                c.rotation = data.ks.r.k[0] ? data.ks.r.k[0].s[0] : data.ks.r.k;
                //锚点，用贴图锚点
                var ad = typeof data.ks.a.k[0] == "number" ? data.ks.a.k : data.ks.a.k[0].s;
                c.anchor.set(ad[0], ad[1])
                //位置
                var ad = typeof data.ks.p.k[0] == "number" ? data.ks.p.k : data.ks.p.k[0].s;
                c.position.set(ad[0] - c.anchorX, ad[1] - c.anchorY)
                //缩放
                var ad = typeof data.ks.s.k[0] == "number" ? data.ks.s.k : data.ks.s.k[0].s;
                c.scale.set(ad[0] / 100, ad[1] / 100)

                //如果入场不在的
                if (data.ip != 0) c.visible = false
            }
            if (c.children.length) this.initState(c.children)
        }
    }
    /**
     * 只有一次或无数次
     */
    play(loop: number = 1, callback?: () => void) {
        this.initState();
        this.loops = loop;
        this.callback = callback;
        this.addTweens();
    }

    /**
     * 移除所有的Tween
     */
    stop() {
        removeTweens(this);
        this.initState();
    }

    private addTweens(con = this.children) {
        for (var i = 0; i < con.length; i++) {
            // @ts-ignore
            let c: FYGE.Sprite = con[i];
            if (c["layerData"]) {
                //取第一个数据
                let data: LayerData = c["layerData"];
                //@ts-ignore 透明度，如果k是数组，肯定有帧数据
                if (data.ks.o.k.length) this.addTween(c, "o");
                //@ts-ignore 旋转
                if (data.ks.r.k.length) this.addTween(c, "r");
                //位置，得是对象
                if (typeof data.ks.p.k[0] != "number") this.addTween(c, "p");
                //缩放
                if (typeof data.ks.s.k[0] != "number") this.addTween(c, "s");
            }
            if (c.children.length) this.addTweens(c.children)
        }
    }

    private addTween(dis: FYGE.DisplayObject, type: "r" | "o" | "s" | "p") {
        const data: { "t": number, "s": number[] }[] = dis["layerData"].ks[type].k
        let tween = FYGE.Tween.get(dis, { loop: true })
        let countTime = 0;
        //记录用过的obj
        var objArr: { obj: any, deltaTime: number }[] = []
        for (let i = 0; i < data.length; i++) {
            let d = data[i];
            let deltaTime = d.t * this.timeInterval - countTime;
            countTime += deltaTime;
            let obj;
            switch (type) {
                case "r":
                    obj = { rotation: d.s[0] }
                    break;
                case "o":
                    obj = { alpha: d.s[0]/100 }
                    break;
                case "s":
                    obj = { scaleX: d.s[0] / 100, scaleY: d.s[1] / 100 }
                    break;
                case "p":
                    obj = { x: d.s[0] - dis.anchorX, y: d.s[1] - dis.anchorY }
                    break;
            }
            //第一个不是0，加wait
            if (i == 0 && d.t != 0) {
                tween.wait(deltaTime)
                    .call(() => { dis.visible = true })
                continue
            } else if (i == 0 && d.t == 0) {//从0开始的，不进行缓动，但是要记录状态
                objArr.push({ obj, deltaTime })
                continue
            }

            tween.to(obj, deltaTime);
            objArr.push({ obj, deltaTime })
        }
        if (dis["layerData"].ks[type].x) {
            var xs = dis["layerData"].ks[type].x;
            if (xs.indexOf("loopOut") >= 0) {
                //如果是往复的，还有问题，没考虑第二个参数
                if (xs.indexOf("pingpong") >= 0 && data[data.length - 1].t < this.rawData.op) {
                    var round = Math.round(this.rawData.op / data[data.length - 1].t)
                    var dir = false;
                    while (--round) {
                        if (dir) {
                            for (var o = 0; o < objArr.length; o++) {
                                tween.to(objArr[o].obj, objArr[o].deltaTime);
                            }
                        } else {
                            for (var o = objArr.length - 1; o >= 1; o--) {
                                tween.to(objArr[o - 1].obj, objArr[o].deltaTime);
                            }
                        }
                        dir = !dir;

                    }

                }
                //如果是循环的，且没满一个循环的
                else if (xs.indexOf("cycle") >= 0 && data[data.length - 1].t < this.rawData.op) {
                    //循环的是往后哪几帧
                    var rr = xs.replace(/[^0-9]/ig, "");
                    var num = Math.round((this.rawData.op - data[data.length - 1 - rr].t) / (data[data.length - 1].t - data[data.length - 1 - rr].t));
                    //objArr只有一部分是进行循环的。
                    objArr = objArr.slice(-rr)
                    while (--num) {
                        //补满
                        for (var o = 0; o < objArr.length; o++) {
                            tween.to(objArr[o].obj, objArr[o].deltaTime);
                        }
                    }
                    //补满

                    // for (var o = 0; o < objArr.length; o++) {
                    //     tween.to(objArr[o].obj, objArr[o].deltaTime);
                    // }
                }
            }
        }
        //入场不是0
        if (dis["layerData"].ip != 0) {
            tween.call(() => {
                dis.visible = false;
            })
        }
        //不管x的
        if (!dis["layerData"].ks[type].x) {
            if (data[data.length - 1].t < this.rawData.op) {
                tween.wait(this.rawData.op * this.timeInterval - countTime)
            }
        }
        tween.call(() => {
            if (--this.loops == 0) {
                this.stop();
                this.callback && this.callback();
            }
        })
    }

    destroy() {
        removeTweens(this);
        super.destroy();
    }
}




