cc.Class({
    extends: cc.Component,
    properties: {},

    getData(callBack) {
        const uri = 'courseware/v1/getdata';

        let syllabus_id;
        if (this.bundleType == 'StoryBox') {
            syllabus_id = this.syllabus_id;
        } else if (this.bundleType == 'WW') {
            syllabus_id = this.bundleInfoList[this.currentBundleIndex].syllabus_id;
        }
        const data = {
            courseid: syllabus_id
        };
        this.callNetworkApiGet(uri, data, (data) => {
            cc.debug.setDisplayStats(false);
            callBack(JSON.parse(data.data));
        });
    },

    onHomeworkFinish(callBack) {
        if (this.role == 'teacher') {
            return;
        }
        const uri = 'app_source/v1/student/homework/finished';
        const data = {
            syllabus_id: this.syllabus_id,
            homework_id: this.homework_id,
            token: this.token,
            score: 100
        };
        console.log('data = ' + JSON.stringify(data));
        this.callNetworkApiPost(uri, data, callBack);
    },

    callNetworkApiGet(uri, data, callBack) {
        let queryStr = '';
        for (const key in data) {
            if (Object.hasOwnProperty.call(data, key)) {
                const value = data[key];
                if (queryStr == '') {
                    queryStr += '?';
                }
                if (queryStr != '?') {
                    queryStr += '&';
                }
                queryStr += `${key}=${value}`;
            }
        }
        const xhr = new XMLHttpRequest();
        xhr.onreadystatechange = () => {
            if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status < 400)) {
                const responseData = JSON.parse(xhr.responseText);
                callBack(responseData);
            }
        };
        const url = `${this.baseUrl}${uri}${queryStr}`;
        console.log('url = ' + url);
        xhr.open('GET', url, true);
        xhr.send();
    },

    callNetworkApiPost(uri, data, callBack) {
        const xhr = new XMLHttpRequest();
        const url = `${this.baseUrl}${uri}`;
        xhr.open("POST", url, true);
        xhr.setRequestHeader('content-type', 'application/json');
        xhr.onreadystatechange = () => {
            if (xhr.readyState == 4) {
                callBack(JSON.parse(xhr.responseText));
            }
        }
        xhr.send(JSON.stringify(data));
    },

    start() {

        this.node.zIndex = 9999;
        this.showWaitingLetters();

        cc.game.addPersistRootNode(this.node);

        this.initListener();

        this.getBundleInfoList();

        // this.baseUrl = 'http://staging-teach.ireadabc.com/api/';
        // this.initStoryBoxView({
        //     // coursewareId: 18307
        //     // coursewareId: 18582
        //     coursewareId: 25687
        // });
        // this.bundleType = 'StoryBox';

        this.log('汪汪汪');
    },

    asyncDelayLog(str) {
        console.log(str);
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve();
            }, 1);
        });
    },

    getBundleInfoList() {
        const jsonStr = this.callNativeFunction({ name: 'loadSceneList', value: '' });

        if (!jsonStr) {
            console.error('没有jsonStr!!')
            return;
        }

        const { bundleInfoList, defaultBundleIdx, bundleType, bundleInfo } = JSON.parse(jsonStr);

        if (bundleType == 'PetRoom') {
            this.bundleType = 'PetRoom';
            this.baseUrl = bundleInfo.baseUrl;
            this.token = bundleInfo.token;
            this.homework_id = bundleInfo.homework_id;
            this.syllabus_id = bundleInfo.syllabus_id;
            this.role = bundleInfo.role;

            this.initPetRoomView(bundleInfo);

        } else if (bundleType == "StoryBox") {
            this.bundleType = 'StoryBox';
            const descLabel = cc.find('middleLayer/storyBox/menu/menuBase/title/name');
            descLabel.getComponent(cc.Label).string = bundleInfo.coursewareDescription;

            const nameLabel = cc.find('middleLayer/storyBox/menu/menuBase/title/Lession');
            nameLabel.getComponent(cc.Label).string = bundleInfo.coursewareName;

            this.baseUrl = bundleInfo.baseUrl;
            this.initStoryBoxView(bundleInfo);
        } else {
            this.bundleType = 'WW';
            // WW模板
            this.bundleInfoList = bundleInfoList;
            this.jumpToBundleByIndex(defaultBundleIdx);
        }
    },

    initPetRoomView(bundleInfo) {
        this.hideWWView();
        this.loadBundle(bundleInfo);
    },

    initStoryBoxView(bundleInfo) {
        this.hideWWView();

        // this.showLog(bundleInfo.coursewareId);
        this.callNetworkApiGet('syllabus/v1/tree', { orgid: 483, pid: bundleInfo.coursewareId }, (data) => {
            console.log(data);
            const defaultBondle = data.rows.find(row => row.name == '默认');
            if (!defaultBondle) {
                cc.find('middleLayer/storyBox/bg').active = true;
                console.error('没有默认课件!');
                return;
            }
            cc.find('middleLayer/storyBox/bg').active = false;

            this.syllabus_id = defaultBondle.children[0].id;
            this.loadBundleByConf(defaultBondle.children[0].conf, () => {
                const ExitBtn = cc.find('middleLayer/storyBox/ExitBtn');
                ExitBtn.active = true;
            });

            this.menuItemNodeList = [];

            data.rows.filter((row) => {
                return row.name != '默认';
            }).forEach((data, idx, arr) => {
                console.log(data.name, idx);

                const node = cc.instantiate(cc.find('middleLayer/menuItem'));
                node.name = 'menuItem_' + idx;
                node.parent = cc.find('middleLayer/storyBox/menu/menuBase');
                node.active = true;
                node.x = 0;
                node.y = 50 + (arr.length - 1 - idx) * 100;

                this.menuItemNodeList.push(node);

                const menuBase = cc.find('bubbleBase', node);

                const label = cc.find('label', node);
                label.getComponent(cc.Label).string = data.name;
                label.active = true;
                const labelSelected = cc.find('labelSelected', node);
                labelSelected.getComponent(cc.Label).string = data.name;
                labelSelected.active = false;

                const btn = cc.find('btn', node);
                const btnLight = cc.find('btnHightLight', node);
                const btnSelected = cc.find('btnSelected', node);
                btn.active = true;
                btnLight.active = false;
                btnSelected.active = false;

                btn.addComponent(cc.Button);
                btn.on('click', () => {
                    console.log(data);
                    cc.tween(btn)
                        .to(0.1, { scale: 1.1 })
                        .to(0.1, { scale: 1.0 })
                        .call(() => {
                            if (data.has_child == '0') {
                                this.hideAllSubmenu();
                                this.resetAllMenu();
                                this.hideMenu();
                                btn.active = false;
                                btnSelected.active = true;
                                label.active = false;
                                labelSelected.active = true;

                                if (!data.children[0]) {
                                    cc.find('middleLayer/storyBox/bg').active = true;
                                    console.error('沒有課件!');
                                    return;
                                }
                                cc.find('middleLayer/storyBox/bg').active = false;

                                this.syllabus_id = data.children[0].id;
                                this.loadBundleByConf(data.children[0].conf);
                            } else {
                                this.hideAllSubmenu();
                                menuBase.active = true;

                                btn.active = false;
                                btnLight.active = true;
                            }
                        })
                        .start();
                    cc.tween(label)
                        .to(0.1, { scale: 1.1 })
                        .to(0.1, { scale: 1.0 })
                        .start();
                });

                btnLight.addComponent(cc.Button)
                btnLight.on('click', () => {
                    cc.tween(btnLight)
                        .to(0.1, { scale: 1.1 })
                        .to(0.1, { scale: 1.0 })
                        .call(() => {
                            menuBase.active = false;

                            btn.active = true;
                            btnLight.active = false;
                        })
                        .start();
                    cc.tween(label)
                        .to(0.1, { scale: 1.1 })
                        .to(0.1, { scale: 1.0 })
                        .start();
                });

                btnSelected.addComponent(cc.Button)
                btnSelected.on('click', () => {
                    this.hideMenu();
                });

                if (data.has_child == '1') {
                    for (let i = 0; i < 10; i++) {
                        const optionNode = cc.find(`bubbleBase/bubbleBg/option_${i}`, node);
                        console.log("optionNode = " + optionNode);
                        optionNode.active = false;
                    }
                    data.children.forEach((menuData, idx) => {
                        const optionNode = cc.find(`bubbleBase/bubbleBg/option_${idx}`, node);
                        optionNode.active = true;
                        const label = cc.find('label', optionNode);
                        label.getComponent(cc.Label).string = menuData.name;

                        optionNode.on('click', () => {
                            cc.tween(optionNode)
                                .to(0.1, { scale: 1.05 })
                                .to(0.1, { scale: 1.00 })
                                .call(() => {
                                    this.hideMenu();
                                    this.syllabus_id = menuData.children[0].id;
                                    this.loadBundleByConf(menuData.children[0].conf);
                                })
                                .start();
                        });
                    });
                }
            });

            this.storyBoxMenuLength = this.menuItemNodeList.filter(node => node.active).length;

            const titleNode = cc.find('middleLayer/storyBox/menu/menuBase/title');
            titleNode.y = 30 + this.storyBoxMenuLength * 100;


            const storyBox = cc.find('middleLayer/storyBox');
            storyBox.active = true;
            this.initStoryBoxListener();
        });
    },

    hideAllSubmenu() {
        this.menuItemNodeList.forEach(node => {
            const menuBase = cc.find('bubbleBase', node);
            menuBase.active = false;
        });
    },

    resetAllMenu() {
        this.menuItemNodeList.forEach(node => {
            const btn = cc.find('btn', node);
            const btnLight = cc.find('btnHightLight', node);
            const btnSelected = cc.find('btnSelected', node);

            btn.active = true;
            btnLight.active = false;
            btnSelected.active = false;

            const label = cc.find('label', node);
            const labelSelected = cc.find('labelSelected', node);
            label.active = true;
            labelSelected.active = false;
        });
    },

    initStoryBoxListener() {
        const ExitBtn = cc.find('middleLayer/storyBox/ExitBtn');
        ExitBtn.on('click', () => {
            cc.tween(ExitBtn)
                .to(0.1, { scaleX: 0.9, scaleY: 1.1 })
                .to(0.1, { scaleX: 1.1, scaleY: 0.9 })
                .to(0.1, { scaleX: 1, scaleY: 1 })
                .call(() => {
                    this.exit();
                })
                .start();
        });

        const lineBtnShow = cc.find('middleLayer/storyBox/menu/menuBase/lineBtnShow');
        lineBtnShow.on('click', () => {
            cc.tween(lineBtnShow)
                .to(0.1, { scale: 1.1 })
                .to(0.1, { scale: 1.0 })
                .call(() => {
                    this.showMenu();
                })
                .start();
        });

        const lineBtnHide = cc.find('middleLayer/storyBox/menu/menuBase/lineBtnHide')
        lineBtnHide.on('click', () => {
            cc.tween(lineBtnHide)
                .to(0.1, { scale: 1.1 })
                .to(0.1, { scale: 1.0 })
                .call(() => {
                    this.hideMenu();
                })
                .start();
        });
    },

    showMenu() {
        const lineBtnShow = cc.find('middleLayer/storyBox/menu/menuBase/lineBtnShow');
        const lineBtnHide = cc.find('middleLayer/storyBox/menu/menuBase/lineBtnHide')

        lineBtnHide.active = true;
        lineBtnShow.active = false;

        const canvas = cc.find('Canvas');
        console.log('canvas.width = ' + canvas.width);
        console.log('canvas.height = ' + canvas.height);

        const menuBase = cc.find('middleLayer/storyBox/menu/menuBase');
        cc.tween(menuBase)
            .to(1, { y: this.storyBoxMenuLength * -100 - 80 }, { easing: 'bounceOut' })
            .start();
    },

    hideMenu() {
        this.hideAllSubmenu();
        this.resetAllMenu();

        const lineBtnShow = cc.find('middleLayer/storyBox/menu/menuBase/lineBtnShow');
        const lineBtnHide = cc.find('middleLayer/storyBox/menu/menuBase/lineBtnHide')

        lineBtnShow.active = true;
        lineBtnHide.active = false;

        const menuBase = cc.find('middleLayer/storyBox/menu/menuBase');
        cc.tween(menuBase)
            .to(1, { y: 0 }, { easing: 'cubicInOut' })
            .start();
    },

    hideWWView() {
        const exitBtn = cc.find('middleLayer/ExitBtn');
        exitBtn.active = false;
        const BtnLeft = cc.find('middleLayer/BtnLeft');
        BtnLeft.active = false;
        const BtnRight = cc.find('middleLayer/BtnRight');
        BtnRight.active = false;
    },

    jumpToBundleByIndex(index) {
        this.currentBundleIndex = index;
        const currentBundleInfo = this.bundleInfoList[this.currentBundleIndex];

        const btnLeft = this.node.getChildByName('BtnLeft');
        const btnRight = this.node.getChildByName('BtnRight');
        btnLeft.active = true;
        btnRight.active = true;

        if (this.currentBundleIndex == 0) {

            btnLeft.active = false;
        }
        if (this.currentBundleIndex == this.bundleInfoList.length - 1) {

            btnRight.active = false;
        }

        this.baseUrl = currentBundleInfo.baseUrl;
        this.token = currentBundleInfo.token;
        this.homework_id = currentBundleInfo.homework_id;
        this.syllabus_id = currentBundleInfo.syllabus_id;
        this.role = currentBundleInfo.role;

        this.loadBundle(currentBundleInfo);
    },

    loadDefaultBundle() {


        const jsonStr = this.callNativeFunction({ name: 'loadScene', value: '' });

        const {
            sceneName,
            version,
            bondleUrl,
            token,
            baseUrl,
            homework_id,
            syllabus_id,
            role
        } = JSON.parse(jsonStr);


        this.baseUrl = baseUrl;
        this.token = token;
        this.homework_id = homework_id;
        this.syllabus_id = syllabus_id;
        this.role = role;

        this.loadBundle({ bondleUrl, version, sceneName });
    },

    initListener() {
        const exitBtn = this.node.getChildByName('ExitBtn');
        exitBtn.on('click', () => {
            cc.tween(exitBtn)
                .to(0.1, { scaleX: 0.9, scaleY: 1.1 })
                .to(0.1, { scaleX: 1.1, scaleY: 0.9 })
                .to(0.1, { scaleX: 1, scaleY: 1 })
                .call(() => {
                    this.exit();
                })
                .start();
        });

        const btnLeft = this.node.getChildByName('BtnLeft');
        btnLeft.on('click', () => {
            if (this.currentBundleIndex - 1 < 0) {
                return;
            }
            this.jumpToBundleByIndex(this.currentBundleIndex - 1);
        });

        const btnRight = this.node.getChildByName('BtnRight');
        btnRight.on('click', () => {
            if (this.currentBundleIndex + 1 >= this.bundleInfoList.length) {
                return;
            }
            this.jumpToBundleByIndex(this.currentBundleIndex + 1);
        });

        const btnClose = cc.find('middleLayer/ConsoleNode/BtnClose');
        const btnOpen = cc.find('middleLayer/ConsoleNode/BtnOpen');
        const consoleNode = cc.find('middleLayer/ConsoleNode/Console');
        const consoleBg = cc.find('middleLayer/ConsoleNode/bg');
        btnOpen.on('click', () => {
            btnClose.active = true;
            btnOpen.active = false;
            consoleNode.active = true;
            consoleBg.active = true;
        });

        btnClose.on('click', () => {
            btnClose.active = false;
            btnOpen.active = true;
            consoleNode.active = false;
            consoleBg.active = false;
        });
    },

    log(str) {
        const logStr = `${new Date().toLocaleString()}: ${str}`;
        console.log(logStr);
        const content = cc.instantiate(cc.find('middleLayer/ConsoleNode/content'));
        content.active = true;
        const label = content.getChildByName('label');
        label.getComponent(cc.Label).string = logStr;
        const consoleContent = cc.find('middleLayer/ConsoleNode/Console/content');
        consoleContent.addChild(content);
        consoleContent.getComponent(cc.Layout).updateLayout();
    },

    callNativeFunction(param) {
        const paramStr = JSON.stringify(param);
        if (cc.sys.isNative && cc.sys.os == cc.sys.OS_IOS) {
            return jsb.reflection.callStaticMethod('CocosMng', 'cocosWithNativeProtocol:', paramStr);
        } else if (cc.sys.isNative && cc.sys.os == cc.sys.OS_ANDROID) {
            return jsb.reflection.callStaticMethod('com/iplayabc/cocos/AppActivity', 'cocosWithNativeProtocol', '(Ljava/lang/String;)Ljava/lang/String;', paramStr);
        } else {
            console.error('非源生环境');
        }
    },

    showWaitingLetters() {
        const waitingLayer = cc.find('middleLayer/waitingLayer');
        waitingLayer.active = true;
        const colorList = this.getRainbowColorList();
        const layout = cc.find('middleLayer/layout');
        layout.removeAllChildren();
        layout.active = true;
        const str = 'Now Loading...';
        str.split('').forEach((word, idx) => {
            const node = new cc.Node();
            const label = node.addComponent(cc.Label);
            label.string = word;
            node.parent = layout;
            node.color = colorList[idx];
            cc.tween(node)
                .delay(idx / 4)
                .by(0.3, { y: 50 }, { easing: 'sineOut' })
                .by(0.3, { y: -50 }, { easing: 'sineIn' })
                .delay((str.length - idx) / 4)
                .union()
                .repeatForever()
                .start();
        });
        const totalWidth = layout.children.reduce((width, node, idx) => {
            return width + node.width;
        }, 0);
        layout.width = totalWidth;
    },

    hideWaitingLetters() {
        const layout = cc.find('middleLayer/layout');
        layout.active = false;
        const waitingLayer = cc.find('middleLayer/waitingLayer');
        waitingLayer.active = false;
    },

    showLog(str) {
        if (!this.logList) {
            this.logList = [];
        }
        this.logList.push(str);
        console.log(str);

        if (this.logList.length == 1) {
            this.showOneLog();
        }
    },

    showOneLog() {
        const str = this.logList[0];
        if (str === undefined) {
            return;
        }
        const node = new cc.Node();
        node.anchorX = 0.5;
        const label = node.addComponent(cc.RichText);
        label.string = `<outline color=black width=3>${str}</outline>`;
        label.maxWidth = this.node.width / 2;
        node.x = this.node.width / 4;
        node.y = -this.node.height / 2;
        node.parent = this.node;
        cc.tween(node)
            .to(5, { y: this.node.height })
            .removeSelf()
            .start();
        setTimeout(() => {
            this.logList.shift();
            this.showOneLog();
        }, 1000);
    },

    loadBundle(conf, callback) {
        this.showWaitingLetters();
        cc.assetManager.loadBundle(conf.bondleUrl, { version: conf.version }, async (err, bundle) => {
            if (err) {
                return this.asyncDelayLog(err);
            }
            bundle.loadScene(conf.sceneName, (err, scene) => {
                if (err) {
                    this.asyncDelayLog('err: ', err);
                }
                cc.audioEngine.stopAll();
                cc.director.runScene(scene, null, () => {
                    console.log('sceneName = ' + conf.sceneName);
                    const canvas = cc.find('Canvas');
                    const middleLayer = cc.find('middleLayer');
                    this.hideWaitingLetters();
                    callback && callback();
                    if (this.bundleType == 'StoryBox') {
                        canvas.getComponent(cc.Widget).updateAlignment();
                        middleLayer.getComponent(cc.Widget).updateAlignment();
                        const frameSize = cc.view.getFrameSize();
                        console.log(`Canvas.size = ${canvas.width}, ${canvas.height}`);
                        console.log(`frameSize.size = ${frameSize.width}, ${frameSize.height}`);
                        console.log(`middleLayer.size = ${middleLayer.width}, ${middleLayer.height}`);
                        const scale = (middleLayer.width / frameSize.width);
                        console.log('scale = ' + scale);
                        const middleLayerWidget = middleLayer.getComponent(cc.Widget);

                        middleLayerWidget.isAlignHorizontalCenter = true; // Boolean 是否水平方向对齐中点，开启此选项会将水平方向其他对齐选项取消。
                        middleLayerWidget.isAlignVerticalCenter = true; // Boolean 是否垂直方向对齐中点，开启此项会将垂直方向其他对齐选项取消。

                        // middleLayer.removeComponent(cc.Widget);
                        middleLayer.width = frameSize.width * scale;
                        middleLayer.height = frameSize.height * scale;
                    }
                });
            });
        });
    },

    loadBundleByConf(conf, callback) {
        if (cc.sys.isNative && cc.sys.os == cc.sys.OS_IOS) {
            this.loadBundle(conf.ios, callback);
        } else if (cc.sys.isNative && cc.sys.os == cc.sys.OS_ANDROID) {
            this.loadBundle(conf.android, callback);
        } else {
            this.loadBundle(conf.web_desktop, callback);
            console.error('非源生环境');
        }
    },

    exit() {
        cc.game.removePersistRootNode(this.node);
        cc.director.loadScene("emptyScene", () => {
            this.callNativeFunction({ name: 'exit', value: '' });
        });
    },

    getRainbowColorList() {
        return [
            cc.color(128, 0, 255),
            cc.color(255, 0, 255),
            cc.color(255, 0, 128),

            cc.color(0, 0, 0),

            cc.color(255, 0, 0),
            cc.color(255, 128, 0),
            cc.color(255, 255, 0),
            cc.color(128, 255, 0),
            cc.color(0, 255, 0),
            cc.color(0, 255, 128),
            cc.color(0, 255, 255),

            cc.color(0, 128, 255),
            cc.color(0, 0, 255),
            cc.color(128, 0, 255),
        ];
    }
});
