import { MyCocosSceneComponent } from "../script/MyCocosSceneComponent";
import Attributes from "../script/Attributes";
// @ts-ignore 
import { assign, createMachine, interpret, actions, forwardTo, matchesState } from "../script/xstate";
const { pure, send, raise, sendParent } = actions;


const { ccclass, property } = cc._decorator;

@ccclass
export default class SceneComponent extends MyCocosSceneComponent {

    @property(cc.Node)
    loading: cc.Node = null;
    
    @property(cc.Node)
    UnitView: cc.Node = null;
    @property(cc.PageView)
    UnitViewPager: cc.PageView = null;
    @property(cc.AudioClip)
    bgMusic1: cc.AudioClip = null;
    @property(cc.AudioClip)
    bgMusic2: cc.AudioClip = null;

    



   

    

    @property(cc.Node)
    BackDoorNode: cc.Node = null;



    tws: any[] = [];
    gameMachineService: any = null;
    LoadingCount: number = 1;
	_mapScaleMin: number = 1;
	_mapScaleMax: number = 1;
	_cocosScale: number = 1;
    BASE_URL: string = null;
    ROOT_PID: number = null;
    MACHINE_INITED: boolean = false;
    mute: boolean = true;
    UnitsListNode: cc.Node = null;
    UnitPageViewBgNode: cc.Node = null;
    rootAttrTree: Attributes = null;


    onLoad(){
        this.tws = [];
        this.LoadingCount = 0;
        this.initSize();
        cc.debug.setDisplayStats(false);
    }
    initialized() {
        if(this.BASE_URL && this.gameMachineService) {
            this.gameMachineService.start();
            this.restore();
        }
    }
    callOcMethod(method, param) {
        const paramStr = JSON.stringify(param);
        if (cc.sys.isNative && cc.sys.os == cc.sys.OS_IOS) {
          return jsb.reflection.callStaticMethod('RootViewController', `${method}:`, paramStr);
        } else if (cc.sys.isNative && cc.sys.os == cc.sys.OS_ANDROID) {
          return jsb.reflection.callStaticMethod('com/iplayabc/cocos/AppActivity', method, '(Ljava/lang/String;)Ljava/lang/String;', paramStr);
        } else if (cc.sys.isNative && cc.sys.os == cc.sys.OS_WINDOWS) {
          console.log('汪汪汪')
        } else {
            console.warn('非源生环境');
        }
    }
    initSize() {
		// 注意cc.winSize只有在适配后(修改fitHeight/fitWidth后)才能获取到正确的值,因此使用cc.getFrameSize()来获取初始的屏幕大小
		let screen_size = cc.view.getFrameSize().width / cc.view.getFrameSize().height
		let design_size = cc.Canvas.instance.designResolution.width / cc.Canvas.instance.designResolution.height
		let f = screen_size >= design_size
		cc.Canvas.instance.fitHeight = f
		cc.Canvas.instance.fitWidth = !f

		const frameSize = cc.view.getFrameSize();
		this._frameSize = frameSize;

		this._designSize = cc.view.getDesignResolutionSize();

		let sx = cc.winSize.width / frameSize.width;
		let sy = cc.winSize.height / frameSize.height;
		this._cocosScale = Math.min(sx, sy);

		sx = frameSize.width / this._designSize.width;
		sy = frameSize.height / this._designSize.height;
		this._mapScaleMin = Math.min(sx, sy) * this._cocosScale;
		this._mapScaleMax = Math.max(sx, sy) * this._cocosScale;
	}
    start() {
        this.rootAttrTree = this.getComponent('Attributes');
        this.initBg();
        this.initUnitViewPager();
        this.createFiniteStateMachines();
        
       
        const ferrisEntries = this.rootAttrTree.querySelectorAll('.ferris-entry');
        const BackViewButtons = this.rootAttrTree.querySelectorAll('.back-view');
        BackViewButtons.forEach(b => {
            b.on(cc.Node.EventType.TOUCH_START, function () {
                this.gameMachineService.send('BACK');
                // this.node.emit('BACK');
            }, this, true);
        });
        for (let bs of [ferrisEntries/*, this.SubmarineViewButtons, this.LetterViewButtons, this.StoryViewButtons, this.ReviewViewButtons*/]) {
            bs.forEach(b => {
                // const env = this;
                b.on(cc.Node.EventType.TOUCH_START, function () {
                    console.log('entry btn click');

                    const attrs: Attributes = b.getComponent('Attributes');
                    const viewName = attrs.attrMap['view']
                    if (!viewName) {
                        throw new Error("can not found attr `viewName`");
                    }
                    const dataIndex = attrs.attrMap['dataIndex']
                    if (!dataIndex) {
                        throw new Error("can not found attr `dataIndex`");
                    }
                    const nextView = attrs.attrMap['nextView']
                    if (!nextView) {
                        throw new Error("can not found attr `nextView`");
                    }
                    // const [buttonName, state, index] = b.name.split('@');


                    // console.log(buttonName, state, index);
                    // let stateName = b.parent.name;
                    // if (stateName.includes('@')) {
                    //     let [_, sn] = stateName.split('@')
                    //     stateName = sn;
                    // }
                    // console.log(stateName);
                    
                    const currentDataset = this.gameMachineService.machine.config.context[viewName + 'Data'];
                    if (!currentDataset || !currentDataset[dataIndex]) {
                        return;
                    }
                    // const linkFlag = stateName === 'LetterView';
                    // globalThis.PREV_STATE = globalThis.CURRENT_STATE ? JSON.parse(JSON.stringify(globalThis.CURRENT_STATE)) : null;
                    const param = JSON.parse(JSON.stringify(currentDataset[dataIndex]));
                    globalThis.CURRENT_STATE = {
                        viewName: nextView,
                        nextView: null,
                        data: { ...param }
                    }
                    // console.log(globalThis.PREV_STATE, globalThis.CURRENT_STATE);
                    // globalThis.CURRENT_PID = param.pid;
                    // globalThis.CURRENT_ID = param.id;
                    this.gameMachineService.send(nextView, { ...param});
                }, this, true);
            });
        }

        globalThis.aaa = this;
        const that = this;
        // @ts-ignores
        window.air = window.air || {};
        // @ts-ignores
        window.air.getEngineInfoCallback = function({isDev} ) {
            console.log('isDev ' +(+isDev));
            if (+isDev) {
                // that.ROOT_PID = 21203;
                that.BASE_URL = 'https://staging-teach.ireadabc.com';
            } else {
                // that.ROOT_PID = 21203;
                that.BASE_URL = 'https://openapi.iteachabc.com';
            }
            that.initialized();
        }
        // @ts-ignores
        if (!cc.sys.isNative) {
            // @ts-ignores
            window.air.getEngineInfoCallback({isDev: 1})
        }
    }
    initUnitViewPager() {
        const pages = this.UnitViewPager.getPages();
        let pIndex = pages.length - 1;
        // if (typeof globalThis.CURRENT_PAGE_INDEX != 'undefined' && typeof globalThis.CURRENT_PAGE_INDEX == 'number') {
        //     pIndex = globalThis.CURRENT_PAGE_INDEX;
        // }
        this.UnitViewPager.scrollToPage(pIndex, 0.001);
        this.UnitViewPager.node.on('scrolling', this.moveUnitViewBackground, this);
        this.UnitView.active = false;
        const attr: Attributes = this.UnitViewPager.getComponent('Attributes');
        this.UnitPageViewBgNode = attr.querySelector('#UnitPageViewBg');
        this.UnitsListNode = attr.querySelector('#UnitsList');
        const lessonButtons = attr.querySelectorAll('.lesson-button');
        // console.log(unitButtons);
        lessonButtons.forEach((n) => {
            n.off(cc.Node.EventType.TOUCH_END);
            n.on(cc.Node.EventType.TOUCH_END, function (e) {
                const na:Attributes = e.currentTarget.getComponent('Attributes');
                const dataIndex = na.attrMap['index']
                console.log(dataIndex, globalThis.CURRENT_STATE);
                const currentDataset = this.gameMachineService.machine.config.context[globalThis.CURRENT_STATE.viewName + 'Data'];
                if (!currentDataset || !currentDataset[dataIndex]) {
                    return;
                }
                globalThis.CURRENT_PAGE_INDEX = this.UnitViewPager.getCurrentPageIndex();
                globalThis.PREV_STATE = JSON.parse(JSON.stringify(globalThis.CURRENT_STATE));
                const param = JSON.parse(JSON.stringify(currentDataset[dataIndex]));
                // globalThis.CURRENT_PID = param.pid;
                // globalThis.CURRENT_ID = param.id;
                
                this.gameMachineService.send('PLAY', {...param});
            }, this, true)
        });
    }

    moveUnitViewBackground() {
        //获取滚动视图相对于左上角原点的当前滚动偏移
        let scrollOffset: cc.Vec2 = this.UnitViewPager.getScrollOffset();
        // console.log(scrollOffset.y);
        this.UnitsListNode.y = (scrollOffset.y * 8/9 ) + 600;
        this.UnitPageViewBgNode.y = (scrollOffset.y * .81 ) + 600;
    }
    initBg() {
        this.rootAttrTree.querySelectorAll('.page-holder').forEach(p => {
            p.opacity = 0;
        })
        // const bgNode = cc.find('Canvas/MainScene/SpaceView/bg');
        const fullPageNode = this.rootAttrTree.querySelectorAll('.full-bg');
        console.log(fullPageNode);
        fullPageNode.forEach(n => {
            n.scale = this._mapScaleMax;
        });
        // console.log(cc.view.getFrameSize().height);
        // bg_front.y = -(cc.view.getFrameSize().height / 2 ) * cc.view.getDevicePixelRatio();
        

    }
    addPreloadImage() {
        // TODO 根据自己的配置预加载图片资源
        this._imageResList.push({ url: this.data.pic_url });
        this._imageResList.push({ url: this.data.pic_url_2 });
    }

    addPreloadAudio() {
        // TODO 根据自己的配置预加载音频资源
        this._audioResList.push({ url: this.data.audio_url });
    }

    addPreloadAnima() {

    }


    playBgMusic(audio) {
        if (this.mute) {
            return;
        }
        cc.audioEngine.stopMusic();
        cc.audioEngine.playMusic(audio, true);
    }
    createFiniteStateMachines() {

        const operationState = {
            id: 'operation',
            initial: 'FerrisView',
            context: {
                FerrisViewData: null,
                UnitViewData: null,
                currentDataset: null,
            },
            states: {

                FerrisView: {
                    entry: (ctx, event) => {
                        this.UnitView.active = false;
                        this.playBgMusic(this.bgMusic1);

                        // event.type !== 'BACK' 
                        this.callNetworkApiGet(this.BASE_URL + '/api/oxford/syllabus/v1/root/index/'+1+'?orgid=507', (resp: any) => {
                            resp = JSON.parse(resp);
                            if (resp.msg == 'success') {
                                let { rows } = resp
                                rows = rows.filter(r => !r.has_courseware);
                                console.log('FerrisView111', rows)
                                ctx.FerrisViewData = rows;
                                ctx.currentDataset = rows;
                            }
                        });


                    },
                    exit: () => {
                        console.log('exit FerrisView stage');
                        this.playBgMusic(this.bgMusic2);
                    },
                    on: {
                        UnitView: 'UnitView',
                    },

                },


                UnitView: {
                    entry: (ctx, event) => {
                        console.log('entry UnitView stage');
                        this.UnitView.active = true;

                    },
                    exit: () => {
                        // console.log('exit UnitView stage');
                    },
                    invoke: {
                        src: (ctx, event) => {
                            console.log(111, event)
                            const lessonsBtn = this.rootAttrTree.querySelectorAll('.lesson-button');
                            lessonsBtn.forEach(b => {
                                const attr: Attributes = b.getComponent('Attributes');
                                const  lock = cc.find('icon_key', b);
                                lock.active = true;
                                const titleNode = attr.querySelector('.title');
                                titleNode.getComponent(cc.RichText).string = `<outline align=top
                                width=4></outline>`;
                            });

                            this.callNetworkApiGet(this.BASE_URL + '/api/syllabus/v1/tree?orgid=507&pid=' + event.id, (resp: any) => {
                                resp = JSON.parse(resp);
                                if (resp.msg == 'success') {
                                    let { rows } = resp;
                                    const list = rows.reduce((result, next)=> {
                                        const { children } = next;
                                        // has_courseware true  是文件夹
                                        let childrenList = children.filter(r => r.has_courseware)
                                        if (childrenList.length > 3) {
                                            childrenList.length = 3
                                        }
                                        result = [...result, ...childrenList]
                                        return result
                                    }, []);
                                    // rows = rows.filter(r => !r.has_courseware)
                                    console.log('UnitView', list);
                                    
                                    lessonsBtn.forEach(b => {
                                        const attr: Attributes = b.getComponent('Attributes');
                                        
                                        const index = attr.attrMap['index'];
                                        const lesson = list[index];
                                        const  lock = cc.find('icon_key', b);
                                        lock.active = true;
                                        const titleNode = attr.querySelector('.title');
                                        // titleNode.getComponent(cc.RichText).string = `<outline align=top
                                        // width=4></outline>`;
                                        if (!lesson) {
                                            return;
                                        }
                                        lock.active = false;
                                        const {parent} = b;
                                        const pa = parent.getComponent('Attributes');
                                        const {outline} = pa.attrMap;
                                        titleNode.getComponent(cc.RichText).string = `<outline align=top color=${outline}
                                        width=4>${lesson.name}</outline>`;

                                    });
                                    ctx.UnitViewData = list;
                                    ctx.currentDataset = list;
                                }
                            });

                        }
                    },
                    on: {
                        PLAY: {
                            target: 'PlayView',
                            // actions: (ctx, event) => {
                            //     console.log('PlayView LOAD', ctx, event);
                            // }
                        },
                        BACK: {
                            target: 'FerrisView',
                            actions: (ctx, event) => {
                                console.log('back', ctx, event);
                            }
                        }
                    },
                },

                PlayView: {
                    on: {

                    },
                    invoke: {
                        src: (ctx, event) => {
                            this.showWaitingLetters();
                        }
                    },
                    entry: (ctx, event) => {
                        console.log('entry PlayView stage');
                        this.showWaitingLetters();
                        cc.audioEngine.stopMusic();
                        const configData = globalThis.configData;
                        console.log('PlayView this', this);
                        console.log('PlayView event', event);
                        console.log('PlayView configData', configData);
                        let isDebug = false;
                        if (this.BackDoorNode) {
                            const bd = this.BackDoorNode.getComponent('BackDoor');
                            if (bd && bd.isDebug()) {
                                isDebug = true;
                            }
                        }
                        cc.assetManager.loadBundle(configData.bondleUrl, { version: configData.version }, async (err, bundle) => {
                            if (err) {
                                return console.log(err);
                            }
                            bundle.loadScene(configData.sceneName, null, null, (err, scene) => {
                                cc.director.runScene(scene, null, () => {
                                    try {
                                        const middleLayer = cc.find('middleLayer').getComponent('middleLayer');
                                        if (!isDebug) {
                                            middleLayer.loadOnlineCourseWare(event.id, event.linkFlag);
                                        }
                                        
                                    } catch (e) {
                                        console.error(e);
                                    }

                                });
                            });
                        });
                    },
                    exit: () => {
                        this.hideWaitingLetters();
                        console.log('exit PlayView stage');
                    },
                },
            }
        };

        const operationMachine = createMachine(operationState);

        this.gameMachineService = interpret(operationMachine).onTransition((state) => {
            console.log(1, state);
        });
        
    }
    restore() {
        console.log('restore', globalThis.PREV_STATE);
        if (globalThis.PREV_STATE) {
            // globalThis.CURRENT_ID = globalThis.PREV_STATE.data.id
            // globalThis.CURRENT_PID = globalThis.PREV_STATE.data.pid
            this.gameMachineService.send(globalThis.PREV_STATE.viewName, { ...globalThis.PREV_STATE.data});
            globalThis.CURRENT_STATE = JSON.parse(JSON.stringify(globalThis.PREV_STATE));
            globalThis.PREV_STATE = null;
        }
    }
    setStateContextData({ rows, buttonsKey }) {
        const buttons = buttonsKey;
        buttons.forEach((b: any) => {
            b.getComponent(cc.Button).interactable = false;
        });
        rows.forEach((item, idx) => {
            if (!buttons[idx]) {
                return;
            }
            (buttons[idx] as any).getComponent(cc.Button).interactable = true;
            (buttons[idx] as any).getComponent(cc.Button).dataIndex = idx;
            (buttons[idx] as any).getComponent(cc.Button).dataMeta = item;
            const [_, action, index] = (buttons[idx] as any).name.split('@');
            (buttons[idx] as any).off(cc.Node.EventType.TOUCH_START);
            (buttons[idx] as any).on(cc.Node.EventType.TOUCH_START, function () {
                this.gameMachineService.send(action, item)
            }, this, true)
        });
    }
    callNetworkApiGet(uri, successCallBack: (resp: string) => void, errorCallback?: (any) => void) {
        this.showWaitingLetters()

        const xhr = new XMLHttpRequest();
        xhr.onreadystatechange = () => {
            if (xhr.readyState == 4) {
                this.hideWaitingLetters()
                if ((xhr.status >= 200 && xhr.status < 400)) {
                    successCallBack && successCallBack(xhr.responseText);
                } else {
                    errorCallback && errorCallback(xhr)
                }
            }

        };
        console.log('url = ' + uri);
        xhr.open('GET', uri, true);
        xhr.send();
    }
    hideWaitingLetters() {
        this.LoadingCount--;
        if (this.LoadingCount <= 0) {
            this.LoadingCount = 0;
            setTimeout(() => {
                if (this.tws){
                    for (const tw of this.tws) {
                        tw.node.y = 0;
                        tw.tw.stop();
                    }
                } 
                this.loading.active = false;
            });
        }
    }
    showWaitingLetters() {
        this.LoadingCount += 1;
        if (this.loading.active) {
            return;
        }
        const colorList = this.getRainbowColorList();
        const text = this.loading.getChildByName('text')
        text.children.forEach((node, idx) => {
            node.color = colorList[idx];
            const tw = cc.tween(node)
            .delay(idx / 4)
            .to(0.3, { y: 50 }, { easing: 'sineOut' })
            .to(0.3, { y: -50 }, { easing: 'sineIn' })
            .delay((text.children.length - idx) / 4)
            .union()
            .repeatForever()
            .start();
            this.tws.push({
                tw,
                node
            });
        });
        this.loading.active = true;
    }
    getRainbowColorList() {
        return [
            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),
            cc.color(255, 0, 255),
            cc.color(255, 0, 128),

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

}
