import { Raycaster, Vector3 } from "three"

class Clickable {
    constructor(engine, defaultDistance) {
        const objects = [];
        const raycaster = new Raycaster();
        let v = new Vector3(), cv = new Vector3();

        this.add = function (object, fn, distance) {
            objects.push(object);
            object._clickable = { fn, distance: (distance || defaultDistance) * engine.scale };
        };

        this.remove = function (object) {
            objects.splice(objects.indexOf(object), 1);
            delete object._clickable;
        };

        this.removeAll = function(){
            objects.forEach(o=>delete o._clickable)
            objects.splice(0, objects.length);
        }

        this.handleController = function(controller){
            raycaster.setFromXRController(controller);
            this.handle();
        }

        this.handleMouse = function (mouse, event) {
            raycaster.setFromCamera(mouse, engine.camera);
            this.handle();
        };

        this.handle = function(){
            let forExecute = [];
            let target = engine.hero?.model || engine.cameraWorld;
            target.getWorldPosition(cv);
            objects.filter(o=>{
                do {
                    if (o.__active === false || o.visible === false) return false;
                    o = o.parent;
                } while (o);
                return true;
            }).forEach(o => {
                o.getWorldPosition(v);
                if (cv.distanceTo(v) <= o._clickable.distance) {
                    const intersects = raycaster.intersectObject(o);
                    if (intersects[0]) {
                        forExecute.push({ o, i: intersects[0] });
                    }
                }
            });
            if (forExecute[0]) {
                let sorted = forExecute.sort((a, b) => a.i.distance - b.i.distance);
                sorted[0].o._clickable.fn(sorted[0].i);
            }
        }

        this.trigger = function(o){
            o._clickable.fn();
        }
    }
}

export { Clickable }