import { Octree } from './octree';
import { EventBus } from '../event-bus';
import { Vec3 } from './vec3';
import { AABB } from './aabb';
export class World extends EventBus {
    constructor(dimensions, octreeOptions) {
        super();
        if (!octreeOptions) {
            this.octreeOptions = {
                position: new Vec3({ x: 0, y: 0, z: 0 }),
                dimensions: new Vec3(this.dimensions),
                maxLevels: 50,
                maxObjects: 50
            };
        }
        else {
            this.octreeOptions = octreeOptions;
        }
        this.dimensions = dimensions;
        this.objects = [];
    }
    setGravity(grav) {
        this.gravity = grav;
    }
    addObject(obj) {
        this.objects.push(obj);
    }
    removeObject(obj) {
        this.objects = this.objects.filter((val) => val !== obj);
    }
    step(dt) {
        const octree = new Octree(this.octreeOptions.dimensions, this.octreeOptions.maxObjects, this.octreeOptions.maxLevels);
        this.objects.forEach((obj) => octree.insert(obj));
        this.objects.forEach((obj) => {
            let velocity = obj.velocity.clone();
            velocity.multiply(new Vec3({ x: dt, y: dt, z: dt }));
            let gravity = this.gravity.clone();
            gravity.multiply(new Vec3({ x: dt, y: dt, z: dt }));
            obj.position.add(velocity);
            if (obj.affectedByGravity) {
                obj.velocity.add(gravity);
            }
            this.checkCollisions(obj, octree);
        });
    }
    checkCollisions(obj, octree) {
        const potentialCandidates = octree.find(obj.position, obj.dimensions);
        potentialCandidates.forEach((candidate) => {
            if (AABB(obj, candidate)) {
                this.emit('collision', [obj, candidate]);
            }
        });
    }
}
