export class space_scene {
    #manager;
    #renderer;
    #camera;
    #scene;
    #working;
    #framerate;

    constructor(manager) {
        this.#manager = manager;

        const canvas = manager.canvas;
        const context = manager.context;

        this.#framerate = 60;
        this.#renderer = new THREE.WebGLRenderer({canvas, context: context});
        this.#camera = new THREE.PerspectiveCamera(75, 1);
        this.#scene = new THREE.Scene();
       
        this.set_room();
        this.update_size();
        this.manager.mouse.add_listener((move) => this.#camera_rotate(move));
    }

    get manager() {
        return this.#manager;
    }

    get #canvas() {
        return this.manager.canvas;
    }

    update_size(width, height) {
        this.#canvas.width = width;
        this.#canvas.height = height;
        this.#camera.aspect = width / height;

        this.#camera.updateProjectionMatrix();
        this.#renderer.setSize(width, height);
    }

    get scene() {
        return this.#scene;
    }

    start() {
        this.#working = true;

        setTimeout(() => { this.#rendering(); }, 1);
    }

    stop() {
        this.#working = false;
    }

    set_room() {
        const url = this.manager.loader.texture("example_room.jpg");
        
        const texture = new THREE.TextureLoader().load(url, () => {
            texture.mapping = THREE.EquirectangularReflectionMapping;
            texture.colorSpace = THREE.SRGBColorSpace;
            this.scene.background = texture;    
        });
    }

    get camera() {
        return this.#camera;
    }   

    #animate() {
    }

    get maximum_rotation() {
        return Math.PI / 3;
    }

    #camera_rotate(move) {
        this.camera.rotation.reorder("YXZ");

        this.camera.rotation.x -= move.y / 100;
        this.camera.rotation.y -= move.x / 100;
        
        if (this.camera.rotation.x > this.maximum_rotation) {
            this.camera.rotation.x = this.maximum_rotation;
        }

        if (this.camera.rotation.x < -this.maximum_rotation) {
            this.camera.rotation.x = -this.maximum_rotation;
        }
    }

    #rendering() {
        const before = performance.now();

        this.#animate();
        this.#renderer.render(this.#scene, this.#camera);
        
        if (!this.#working) {
            return;
        }

        const after = performance.now();
        const delta = after - before;
        const next = 1000 / this.#framerate - ((delta >= 0) ? delta : 0);

        setTimeout(() => {
            requestAnimationFrame(() => { this.#rendering(); });
        }, (next > 0) ? next : 1);
    }
}