// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

const {ccclass, property} = cc._decorator;
import user from "./model/user";
import dress from "./model/dress";
import pg from "./pg";
@ccclass
export default class PengPeng extends cc.Component {
    // LIFE-CYCLE CALLBACKS:
    @property({ type: cc.SpriteFrame })
    defaultCover: cc.SpriteFrame | null = null

    // onLoad () {}

    start () {
        console.log('pengpeng start')
        user.setDataReadyCallback(this.dataReady);
        const walkNode = pg.view.find(this.node, "walk")
        const eatNode = pg.view.find(this.node, "eat");
        window.walk = walkNode
        window.eat = eatNode
        window.pp = this;
        pg.view.touchOn(walkNode, this.onTouchElephent, this);
        const btnClose = pg.view.find(this.node, "panel_info/btn_close");
        pg.view.touchOn(btnClose, this.onTouchPanel, this);

        // cache 
        const walkDragonDisplay = walkNode.getComponent(dragonBones.ArmatureDisplay);
        const eatDragonDisplay = eatNode.getComponent(dragonBones.ArmatureDisplay);
        const walkAtlasAsset = walkDragonDisplay.dragonAtlasAsset;
        const walkAsset = walkDragonDisplay.dragonAsset;
        const walkArmatureName = walkDragonDisplay.armatureName;

        const eatAtlasAsset = eatDragonDisplay.dragonAtlasAsset;
        const eatAsset = eatDragonDisplay.dragonAsset;
        const eatArmatureName = eatDragonDisplay.armatureName;

        walkAtlasAsset.addRef();
        walkAsset.addRef();
        eatAtlasAsset.addRef();
        eatAsset.addRef();

        
        console.log('this.defaultCover.getTexture()', this.defaultCover.getTexture())
        dress.defaultSkin.cover = this.defaultCover.getTexture();
        dress.defaultSkin.meta_value.nodes.walk.tex_png = null;
        dress.defaultSkin.meta_value.nodes.walk.ske_json = walkAsset
        dress.defaultSkin.meta_value.nodes.walk.tex_json = walkAtlasAsset
        dress.defaultSkin.meta_value.nodes.walk.armature = walkArmatureName



        dress.defaultSkin.meta_value.nodes.eat.tex_png = null;
        dress.defaultSkin.meta_value.nodes.eat.ske_json = eatAsset
        dress.defaultSkin.meta_value.nodes.eat.tex_json = eatAtlasAsset
        dress.defaultSkin.meta_value.nodes.eat.armature = eatArmatureName
    }
    dataReady = () => {
        console.log('pengpeng dataReady');
        const item = dress.list.find(item => item.current)
        this.changeDress(item);
    }
    //打开提示面板
    onTouchElephent() {
        let panel_info = pg.view.find(this.node, "panel_info");
        if (panel_info.active) {
            this.onTouchPanel();
            return;
        }
        this.elephentState(user.mood == 0 ? 1 : 2);
        panel_info.active = true;
        //刷新内容
        let label_name = pg.view.find(panel_info, "label_name");
        pg.view.setString(label_name, user.name);
        let label_level = pg.view.find(panel_info, "label_level");
        pg.view.setString(label_level, `LV.${user.level ? user.level : 0 }`);

        let icon_happy = pg.view.find(panel_info, "icon_happy");
        let icon_hungry = pg.view.find(panel_info, "icon_hungry");
        icon_happy.active = user.mood == 0;
        icon_hungry.active = user.mood == 1;

        let percent = user.growth / user.growthLevel;
        let progress = pg.view.find(panel_info, "progress");
        progress.getComponent(cc.ProgressBar).progress = percent;
    }
    //关闭提示面板
    onTouchPanel() {
        let panel_info = pg.view.find(this.node, "panel_info");
        panel_info.active = false;
        this.elephentState(0);
    }
    //小象的动作管理。
    // private elephant: cc.Node;
    private _timer: number;
    elephentState(state) {
        switch (state) {
            case 0:
                this.elephantWalk();
                break;
            case 1:
                this.elephantHappy();
                break;
            case 2:
                this.elephantHungry();
                break;
            case 3:
                this.elephantEating();
                break;
        }
    }
    elephantWalk() {
        let walkAni = pg.view.find(this.node, "walk");
        const oriScaleX = walkAni.scaleX;
        let eatAni = pg.view.find(this.node, "eat");
        walkAni.active = true;
        eatAni.active = false;
        let db = pg.view.playDBAnimation(walkAni, "walking", 0);
        this.removeHungryAudio(db);
        cc.Tween.stopAllByTarget(this.node);
        walkAni.scaleX = oriScaleX;
        let moveX = 400;
        let moveY = 0;
        let winSize = cc.winSize;
        if (winSize.width / winSize.height < 16 / 9) {
            moveY = -(16 / 9 - winSize.width / winSize.height) * 750 / 2;
        }
        if (!this.node.active) {
            this.node.active = true;
            this.node.x = 0;
            this.node.y = moveY + Math.random() * 100;
        }
        cc.tween(this.node)
            .to(4, { x: moveX, y: moveY + Math.random() * 100 })
            .call(() => {
                walkAni.scaleX = -oriScaleX;
            })
            .to(4, { x: 0, y: moveY + Math.random() * 100 })
            .to(4, { x: -moveX, y: moveY + Math.random() * 100 })
            .call(() => {
                walkAni.scaleX = oriScaleX;
            })
            .to(4, { x: 0, y: moveY + Math.random() * 100 })
            .call(() => {
                this.elephentState(0);
            })
            .start();
    }
    elephantHappy() {
        let walkAni = pg.view.find(this.node, "walk");
        let eatAni = pg.view.find(this.node, "eat");
        walkAni.active = true;
        eatAni.active = false;
        let db = pg.view.playDBAnimation(walkAni, "happy", 0);
        this.removeHungryAudio(db);
        cc.Tween.stopAllByTarget(this.node);
        // walkAni.scaleX = 1;
    }
    elephantHungry() {
        let walkAni = pg.view.find(this.node, "walk");
        let eatAni = pg.view.find(this.node, "eat");
        walkAni.active = true;
        eatAni.active = false;
        this.playLocalAudio("hungry");
        let db: dragonBones.ArmatureDisplay = pg.view.playDBAnimation(walkAni, "hungry", 0);
        this.removeHungryAudio(db);
        this.addHungryAudio(db);
        cc.Tween.stopAllByTarget(this.node);
        // walkAni.scaleX = 1;
    }
    elephantEating() {
        let walkAni = pg.view.find(this.node, "walk");
        let eatAni = pg.view.find(this.node, "eat");
        walkAni.active = false;
        eatAni.active = true;
        cc.Tween.stopAllByTarget(this.node);
        pg.view.playDBAnimation(eatAni, "eating", 0);
        this.playLocalAudio("eating");
        setTimeout(() => {
            this.elephentState(0);
        }, 3500);
    }

    addHungryAudio(db: dragonBones.ArmatureDisplay) {
        db.addEventListener(dragonBones.EventObject.LOOP_COMPLETE, this.playHungryAudio, this)
    }
    removeHungryAudio(db: dragonBones.ArmatureDisplay) {
        db.removeEventListener(dragonBones.EventObject.LOOP_COMPLETE, this.playHungryAudio, this)
    }
    playHungryAudio() {
        this.playLocalAudio("hungry");
    }
    playLocalAudio(audioName) {
        const audio = cc.find(`Canvas/res/audio/${audioName}`).getComponent(cc.AudioSource);
        return new Promise((resolve, reject) => {
            const id = cc.audioEngine.playEffect(audio.clip, false);
            cc.audioEngine.setFinishCallback(id, () => {
                resolve(id);
            });
        })
    }
    changeDress(data) {
        
        console.log('changeDress1', dress)
        console.log('changeDress2', data)
        if (!data)  {
            return;
        }
        const promiseArray = [];
        const bundleUrl = data.meta_value.bundle;
        const version = data.meta_value.version;
        let bundleOption = null
        if (version) {
          bundleOption = {version}
        }
        return new Promise((resolve, reject) => {
            let fn = cc.assetManager.loadBundle.bind(cc.assetManager)
            if (!bundleUrl) {
                fn = (bundleUrl, option, cb) => {
                    if (!bundleUrl) {
                        cb(null, null)
                    }
                }
            }
          fn(bundleUrl, bundleOption, (err, bundle) => {
            const nodeNames = Object.keys(data.meta_value.nodes);
            for(let i = 0; i < nodeNames.length; i++) {
              const nodeName = nodeNames[i];
              const node = cc.find(nodeName, this.node)
              node.stopAllActions();
              if (node) {
                const meta = data.meta_value.nodes[nodeName];
                const dragonDisplay = node.getComponent(dragonBones.ArmatureDisplay);
                // const imageUrl = meta['tex_png'];
                const skeUrl = meta['ske_json'];
                const atlasUrl = meta['tex_json'];
                const armatureName = meta['armature'];
                const animationName = meta['animation'];
                const properties = meta['node'];
                const offset = meta['offset'];
                // console.log(nodeName, armatureName,  node)
      
                dragonDisplay.dragonAsset = null;
                dragonDisplay.dragonAtlasAsset = null;
                dragonDisplay.armatureName = "";
                const proc = new Promise((resolve1, reject1) => {
                  pg.load.loadFromBundle(bundle, [
                    [atlasUrl, dragonBones.DragonBonesAtlasAsset],
                    [skeUrl, dragonBones.DragonBonesAsset]
                  ]).then(([atlas, asset]) => {
                    dragonDisplay.dragonAtlasAsset = atlas;
                    // console.log(8)
                    dragonDisplay.dragonAsset = asset;
                    // console.log(9)
                    dragonDisplay.armatureName = armatureName;
                    // console.log(10)
                    const armature = dragonDisplay.armature()
                    // armature.animation.animationNames
                    console.log('animationName',node.name, armatureName, animationName, armature ? armature.animation.animationNames : [])
                    if (animationName) {
                      dragonDisplay.playAnimation(animationName, 0);
                    }
                    node.scaleX = 1;
                    node.scaleY = 1;
                    if (properties) {
                      Object.keys(properties).forEach(key => {
                        node[key] = properties[key];
                      })
                    }
                    if (offset) {
                      Object.keys(offset).forEach(key => {
                        node[key] += +offset[key];
                      })
                    }
                    resolve1()
                  })
                })
                promiseArray.push(proc)
              }
            }
          })
      
          Promise.all(promiseArray).then(() => {
            resolve()
          })
        })
      }

    changeDress____123123(data) {
        console.log('changeDress1', dress)
        console.log('changeDress2', data)
        const promiseArray = [];
        const nodeNames = Object.keys(data.meta_value);
        for(let i = 0; i < nodeNames.length; i++) {
            const nodeName = nodeNames[i];
            const node = cc.find(nodeName, this.node)
            node.stopAllActions();
            window[nodeName] = node;
            if (node) {
                const proc = new Promise((resolve, reject) => {
                    const meta = data.meta_value[nodeName]
                    const dragonDisplay = node.getComponent(dragonBones.ArmatureDisplay);
                    const imageUrl = meta['tex_png'];
                    const skeUrl = meta['ske_json'];
                    const atlasUrl = meta['tex_json'];
                    const armatureName = meta['armature'];
                    const animationName = meta['animation'];
                    const properties = meta['node'];
                    const offset = meta['offset'];

                    console.log(nodeName, armatureName,  node)

                    pg.load.loadAssets([
                        [imageUrl,{ext: '.png', type: cc.Texture2D}],
                        [atlasUrl, {ext: '.txt', type: dragonBones.DragonBonesAtlasAsset}], 
                        [skeUrl, {ext: '.txt', type: dragonBones.DragonBonesAsset}]
                    ]).then((assets: any[]) => {

                        const u1 = dragonDisplay.dragonAtlasAsset._uuid;
                        const u2 = dragonDisplay.dragonAsset._uuid;
                        

                        // dragonDisplay.dragonAtlasAsset.destroy();
                        // dragonDisplay.dragonAsset.destroy();
                        let c1 = false;
                        let c2 = false;
                        if (u1 && typeof u1 == 'string' && u1.startsWith('http')) {
                            console.log('release1', u1)
                            dragonDisplay.dragonAtlasAsset.destroy();
                            cc.assetManager.releaseAsset(dragonDisplay.dragonAtlasAsset.texture);
                            cc.assetManager.releaseAsset(u1);
                            c1 = true;
                        }
                        if (u2 && typeof u2 == 'string' && u2.startsWith('http')) {
                            console.log('release1', u2)
                            dragonDisplay.dragonAsset.destroy();
                            cc.assetManager.releaseAsset(u2);
                            c2 = true;
                        }

                        if (c1 && c2) {
                            const currentArmature = dragonDisplay.armature()
                            if (currentArmature) {
                                currentArmature.dispose()
                            }
                        }

                        dragonDisplay.dragonAsset = null;
                        dragonDisplay.dragonAtlasAsset = null;
                        dragonDisplay.armatureName = "";

                        // dragonDisplay.playAnimation(null);


                        const [texture, atlasJson, dragonBonesJson ] = assets;
                        // console.log(texture ? JSON.stringify(texture) : texture, atlasJson ? JSON.stringify(atlasJson) : atlasJson, dragonBonesJson? JSON.stringify(dragonBonesJson): dragonBonesJson)
                        if  (texture) {
                            // texture.setPremultiplyAlpha(true);
                            // dragonDisplay.premultipliedAlpha = false;
                        }
                        console.log(texture ? `${texture.constructor.name}` : texture, atlasJson ? atlasJson.constructor.name : atlasJson, dragonBonesJson? dragonBonesJson.constructor.name: dragonBonesJson)
                        console.log(1)
                        console.log(`[atlasJson]1 ${cc.js.isChildClassOf(atlasJson, cc.TextAsset)}`)
                        console.log(`[atlasJson]2 ${cc.js.isChildClassOf(atlasJson, dragonBones.DragonBonesAtlasAsset)}`)
                        console.log(`[atlasJson]3 ${cc.js.isChildClassOf(atlasJson, dragonBones.DragonBonesAsset)}`)
                        try{
                            console.log(`[atlasJson]4 ${atlasJson.name}`)
                            console.log(`[atlasJson]5 ${atlasJson.__proto__.__classname__}`)
                        } catch(e) {
                            console.log(e)
                        }
                        console.log(`[dragonBonesJson]1 ${cc.js.isChildClassOf(dragonBonesJson, cc.TextAsset)}`)
                        console.log(`[dragonBonesJson]2 ${cc.js.isChildClassOf(dragonBonesJson, dragonBones.DragonBonesAtlasAsset)}`)
                        console.log(`[dragonBonesJson]3 ${cc.js.isChildClassOf(dragonBonesJson, dragonBones.TexDragonBonesAssettAsset)}`)
                        try{
                            console.log(`[atlasJson]4 ${dragonBonesJson.name}`)
                            console.log(`[atlasJson]5 ${dragonBonesJson.__proto__.__classname__}`)
                        } catch(e) {
                            console.log(e)
                        }

                        let atlas = atlasJson
                        if (atlasJson.__proto__.__classname__ == 'cc.TextAsset' || atlasJson.constructor.name == 'cc_TextAsset') {
                            console.log(2)
                            atlas = new dragonBones.DragonBonesAtlasAsset();
                            atlas._uuid = atlasUrl;
                            let atlasJsonStr = atlasJson.text;
                            console.log(3)
                            atlas.atlasJson = atlasJsonStr
                            console.log(4)
                            atlas.texture = texture;
                            console.log(5)
                        }
                        let asset = dragonBonesJson;
                        if (dragonBonesJson.__proto__.__classname__ == 'cc.TextAsset' || dragonBonesJson.constructor.name == 'cc_TextAsset') {
                            console.log(6)
                            asset = new dragonBones.DragonBonesAsset();
                            asset._uuid = skeUrl;
                            asset.dragonBonesJson = dragonBonesJson.text;
                            console.log(7)
                        }

                        dragonDisplay.dragonAtlasAsset = atlas;
                        console.log(8)
                        dragonDisplay.dragonAsset = asset;
                        console.log(9)
                        dragonDisplay.armatureName = armatureName;
                        console.log(10)
                        const armature = dragonDisplay.armature()
                        // armature.animation.animationNames
                        console.log('animationName',node.name, armatureName, animationName, armature ? armature.animation.animationNames : [])
                        if (animationName) {
                            dragonDisplay.playAnimation(animationName, 0);
                        }
                        node.scaleX = 1;
                        node.scaleY = 1;
                        if (properties) {
                            Object.keys(properties).forEach(key => {
                                node[key] = properties[key];
                            })
                        }
                        if (offset) {
                            Object.keys(offset).forEach(key => {
                                node[key] += +offset[key];
                            })
                        }
                        resolve()

                    });
                    // cc.assetManager.loadRemote(imageUrl, (err: Error, texture: cc.Texture2D) => {
                    //     cc.assetManager.loadRemote(atlasUrl,{ext: '.txt'}, (error: Error, atlasJson: cc.TextAsset) => {
                    //         cc.assetManager.loadRemote(skeUrl, {ext: '.txt'},(error: Error, dragonBonesJson:cc.JsonAsset) => {
                    //             // console.log('texture', texture)
                    //             // console.log('atlasJson', atlasJson)
                    //             // console.log('dragonBonesJson', dragonBonesJson)
                    //             var atlas:any = new dragonBones.DragonBonesAtlasAsset();
                    //             atlas._uuid = atlasUrl;
                    //             atlas.atlasJson = atlasJson.text;
                    //             atlas.texture = texture;

                    //             var asset:any = new dragonBones.DragonBonesAsset();
                    //             asset._uuid = skeUrl;
                    //             asset.dragonBonesJson = dragonBonesJson;

                    //             console.log('set armatureName: ', armatureName)
                    //             dragonDisplay.armatureName = armatureName;
                    //             dragonDisplay.dragonAtlasAsset = atlas;
                    //             dragonDisplay.dragonAsset = asset;
                    //             // dragonDisplay.playAnimation('happy', 0);
                    //             resolve()
                    //         });
                    //     });
                    // });
                })
                promiseArray.push(proc);
            }
        }
        return Promise.all(promiseArray)
    }
    // update (dt) {}
}
