import { MazeObject } from "./MazeObject";
import Utils from "#/app/Utils";
import { EventManager } from '@/lib/EventManager';

const params = {
    scale: 3,
    wallSize: 3 * 1.2,
    tubeSize: 3 * 1.2,
}

const imgParams = {
    type: 'ImageObject', 
    width: params.wallSize*0.033,
    height: params.wallSize*0.033,
    value: 'arrow.webp',
    path: '/static/meshes/quiz/', distance: params.wallSize*3
}

const textParams = {
    type: 'TextObject', maxWidth:0.44,
    fontPath:'/static/fonts/Montserrat-Regular.ttf', 
    fontSize:0.025, distance: params.wallSize*3
}

const defaults = {
    arrows:{
        r: len => ({ position:[-.5,.25,len+.9], rotation:[0,Math.PI, 0], ...imgParams }),
        l: len => ({ position:[.5,.25,len+.9], rotation:[0,Math.PI, Math.PI], ...imgParams }),
        f: len => ({ position:[0,.37,len+.96], rotation:[0,Math.PI, Math.PI/2], ...imgParams })
    },
    answers:{
        r: (len, text) => ({ ...textParams, text, position:[-.5,.3,len+.9], rotation:[0,Math.PI, 0] }),
        l: (len, text) => ({ ...textParams, text, position:[.5,.3,len+.9], rotation:[0,Math.PI, 0] }),
        f: (len, text) => ({ ...textParams, anchorY:'top', text, position:[0,.3,len+.9], rotation:[0,Math.PI, 0] })
    }
}

const tl = 4;

class MazeQuizGame extends EventManager {
    emits = ['finish', 'sceneSwitch', 'interaction']
    constructor(engine, data) {
        super();
        this.data = data;

        this.params = { ...params, mazeFile: data.style || 'quiz-s2.gltf', io: this }

        return new Promise(async (resolve, reject)=>{
            let questions = data.shuffle ? Utils.shuffleArray(data.questions) : data.questions;
            if (data.shuffle && questions.length > data.questionsCount){
                questions.length = data.questionsCount;
            }
            this.maxPoints = (data.points || 0) + (data.questionPoints||0) * questions.length;
            this.minPoints = this.maxPoints - (data.questionPenalty||0) * questions.length;
            let def = this.generate(questions);
            this.mazeObject = new MazeObject(engine, def, this.params)
            engine.addEventListener('collision', async e=>{
                let ud1 = engine.physics.world.getCollider(e.handle1)?.parent()?.userData,
                    ud2 = engine.physics.world.getCollider(e.handle2)?.parent()?.userData;
                let ud = {...ud1, ...ud2}
                //console.log('collision', ud)
                if (ud.finish){
                    if (e.started){
                        engine.dashboard.levelProgress.update(1)
                        engine.hero.animationsMap._idle = engine.hero.animationsMap.idle
                        if ( engine.hero.animationsMap?.win){
                            engine.hero.animationsMap.idle = engine.hero.animationsMap.win
                        }
                        // await Utils.wait(1000);
                        // engine.hero.cameraDelta = Math.PI;
                        // engine.hero.direction += Math.PI;
                        //engine.hero.model.rotation.y += Math.PI;
                        engine.motionQueue.add({
                            o: engine.hero,
                            a:{cameraDelta: k=>k*Math.PI*4 },
                            t: 12
                        });
                        this.dispatchEvent({type:'finish'})
                    }else{
                        engine.hero.animationsMap.idle = engine.hero.animationsMap._idle
                        engine.hero.cameraDelta = 0
                    }
                }
                if (ud.qid !== undefined && e.started){
                    //engine.dashboard.updateText(ud.question.q)
                    engine.dashboard.levelProgress.update(ud.qid / questions.length)
                    this.dispatchEvent({type:'interaction'});
                }
                if (ud.corner && e.started){
                    let q = ud.corner.question;
                    if (!q.pointsAdded){
                        let qid = data.questions.indexOf(q);
                        if (!ud.corner.penalty){
                            q.pointsAdded = true;
                            engine.dashboard.addPoints(data.questionPoints - !!q.applyPenalty * data.questionPenalty)
                            engine.tm?.post('answer', null, { question: qid, correct: true });
                        }else{
                            q.applyPenalty = true;
                            engine.tm?.post('answer', null, { question: qid, correct: false });
                        }
                    }
                }

                //console.log(e, ud, engine.hero?.animationsMap);
            })
            await this.mazeObject.load();
            this.object = this.mazeObject.object;
            resolve(this);
        })
    }

    generate(questions, qid = 0, len){
        let question = questions[qid]
        len = len || Math.round(Math.random()*tl) + 2;
        if (!question) return {
            len,
            userData: { finish: true },
            objects:[
                // {
                //     type: 'GltfObject',
                //     position:[0,.22,len + .52], scale: [0.33, 0.33, 0.33], rotation: [0, Math.PI/4, 0],
                //     value: 'trophy.glb', path: imgParams.path, distance: params.wallSize*2,
                //     motion: { a:{rotation: { y: k=>k*Math.PI*2 }}, r: true, t: 4 }
                // }
                {
                    type: 'SceneSwitcher', switchScene: this.data.switchScene, switchType: this.data.switchType,
                    position:[0,.22,len + .52], scale: [0.33, 0.33, 0.33], 
                    distance: this.params.wallSize*4
                }
            ]
        };

        let directions = Utils.shuffleArray( ['l', 'r', 'f'] )

        let mo = {
            len, userData: { question, qid },
            objects:[
                {
                    ...textParams, text: question.q, fontSize:0.033, maxWidth:0.55, position:[0,.55,len + .96], rotation:[0,Math.PI, 0]
                }
            ]
        }
        
        question.a.filter(a=>!!a).forEach((a, i)=>{
            let d = directions[i];
            mo.objects.push(
                defaults.arrows[d](len),
                defaults.answers[d](len, a)
            )
            let dd;
            if (d == 'f'){
                dd = Math.random() > 0.5 ? 'l' : 'r';
            }else {
                dd = d == 'l' ? 'r' : 'l'
            }
            if (i == 0){
                let next = this.generate(questions, qid + 1, 5)
                next.userData.corner = { question };
                mo[d] = {
                    len: 5,
                    [dd]: next
                }
            }else{
                mo[d] = {
                    userData: { question, qid, answer: i },
                    len: 5,
                    [dd]: {
                        userData: { corner: { question, penalty: true } },
                        len: 3,
                        objects:[
                            {
                                ...textParams, color:0xc71414, text: question.h, fontSize:0.033, maxWidth:0.66, position:[0,.44,3+.96], rotation:[0,Math.PI, 0]
                            },{
                                ...imgParams, value:'x.webp', position:[0,.33,3+.96], rotation:[0,Math.PI, 0]
                            }
                        ]
                    }
                }
            }
            if (d == 'f'){
                mo[d].len = 2;
                if (i == 0){
                    let path = mo[d][dd];
                    mo[d][dd] = {
                        len: 1,
                        [dd == 'r' ? 'l' : 'r']: path
                    }
                }
            }
        })
        return mo;
    }

}
export { MazeQuizGame }