import { Group, RGBAFormat } from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { MotionEngine } from '../../lib/MotionEngine';

var PuzzleGame4 = function(context, gltf, w, h){
    this.object = new Group();
    const aq = new MotionEngine();
    const pr = [];
    let d = .51, c = w * h / 2, tc = w * h, m0=1, r0=.2;
    let lastClicked;

    function setMaterial(m, v){
        if (v){
            m.metalness = .5;
            m.roughness = .383;
        }else{
            m.metalness = m0;
            m.roughness = r0;
            m.transparent = true;
            m.format = RGBAFormat;
        }
    }

    new GLTFLoader().load(gltf, gltf=>{
        for (let i = 0; i<c; i++){
            let o = gltf.scene.getObjectByName('c'+(i+1));
            let ref = [];
            for (let j = 0; j<2; j++){
                let position;
                do {
                    position = Math.floor(Math.random() * tc);
                }while (pr[position]);
                ref[j] = o.clone();
                ref[j].material = o.material.clone();
                setMaterial(ref[j].material, 0);
                pr[position] = ref[j];
            }
            ref[0].$ref = ref[1];
            ref[1].$ref = ref[0];
        }
        pr.forEach((c, i)=>{
            c.position.set((i % w)*d , (~~(i / w))*d);
            c.rotation.set(0, Math.PI, 0);
            this.object.add(c);
            context.clickable.add(c, clickFn);
        })

        // this.object.children[0].onBeforeRender = ()=>{
        //     this.update();
        // }
        engine.addEventListener('beforeRender', this.update)
    });

    var check = ()=>{
        if (!this.object.children.length) return false;
        return pr.filter(c=>c.$active === false).length == tc;
    }

    let clickFn = (i)=>{
        let clicked = i.object;
        if (this.done && clicked){
            aq.add({
                o: clicked,
                a: {rotation:{y: Math.PI}},
                t: 1,
                m: 'offset'
            });
        }
        if (!clicked || clicked.$active === false || aq.isActive(clicked)) return;
        setMaterial(clicked.material, 1);
        let f;
        if (lastClicked && lastClicked.$ref == clicked){
            clicked.$active = lastClicked.$active = false;
            [clicked, lastClicked].forEach(c => {
                aq.add({
                    o: c,
                    a: {material:{opacity:0}},
                    t: 1,
                    d:1
                });
            });
            lastClicked = null;
        }else if(!lastClicked){
            lastClicked = clicked;
        }else{
            f = ()=>{
                setTimeout(()=>{
                    [clicked, lastClicked].filter(c=>c).forEach(c=>{
                        aq.add({
                            o: c,
                            a: {rotation:{y: Math.PI}, material:{metalness:m0, roughness:r0}},
                            t: 1
                        });
                    });
                    lastClicked = null;
                }, 500);
            }
        }
        aq.add({
            o: clicked,
            a: {rotation:{y: 0}},
            t: .5,
            f
        });
    }

    this.update = ()=>{
        aq.update();
        if (!this.done && check()){
            this.done = true;
            this.object.children.forEach((c, i)=>{
                aq.add({
                    o: c,
                    a: {material:{opacity:1}},
                    t: 1,
                    d:1+0.1*i
                })
            })
            this.dispatchEvent({type:'finish'})
        }
    }
}

export { PuzzleGame4 }