"use strict";

class MainController {
    // Change this value (in MS) to start the demo at a different position
    _demoStartTimeMS = 0;

    onLoading;
    onLoaded;

    _canvas;
    _camera;
    _cube;
    _renderer;
    _scene;
    _sceneManager;
    _spriteManager;
    _musicManager;
    _shaderManager;
    _karaokeManager;
    _textManager;
    _loadingPromises = [];
    _resolvedPromises = 0;
    _time; 

    constructor(canvas) {
        this._canvas = canvas;
        this._textManager = new TextManager(canvas);

        this._initializeDebugMode();
        this._initializeCanvas();   

        this._spriteManager = new SpriteManager(this._renderer.GL);
        this._shaderManager = new ShaderManager(this._renderer.GL);
        this._karaokeManager = new KaraokeManager();

        this._initializeScenes();
        this._initializeMusic();

        for (const promise of this._loadingPromises) {
            promise.then(() => { 
                this._resolvedPromises++;
                if (this.onLoading) {
                    this.onLoading(this._resolvedPromises / this._loadingPromises.length);
                }
            });
        }

        Promise.all(this._loadingPromises).then(() => {
            if (this.onLoaded)
                this.onLoaded();
        });
    }

    run() {
        console.log("Waiting for all resources to load");
        Promise.all(this._loadingPromises).then(() => {
            
            this._musicManager.play(this._demoStartTimeMS);

            this._render();
        });
    }

    // private

    _render() {

        requestAnimationFrame(this._render.bind(this));

        this._time = this._musicManager.currentTime; 

        const renderContext = new RenderContext(
            this._spriteManager, 
            this._shaderManager, 
            this._textManager,
            this._karaokeManager);
        this._sceneManager.updateScenes(renderContext, this._time);
        this._renderer.render(renderContext.renderQueue, this._time);

        if (renderContext.text)
            this._textManager.showText(renderContext.text);
    }

    _initializeCanvas() {
        window.addEventListener("resize", () => {
            this._updateCanvasSize();
        });
        this._updateCanvasSize();

        this._renderer = new Engine.Renderer(this._canvas);
    }

    _updateCanvasSize() {
        console.log("Update canvas size");
        const canvas = this._canvas;

        const ratio = 16 / 9;
        const canvasParent = canvas.parentElement;
        const parentWidth = canvasParent.clientWidth;
        const parentHeight = canvasParent.clientHeight;
        const parentRatio = parentWidth / parentHeight;
        let width = parentWidth;
        let height = parentHeight;
        if (parentRatio > ratio)
            width = height * ratio;
        else
            height = width / ratio;

        canvas.width = width;
        canvas.height = height;

        if (this._textManager)
            this._textManager.setScale(width / 1920);
    }

    _initializeScenes() {
        const context = new SceneContext();
        context.spriteManager = this._spriteManager;

        const sceneManager = new SceneManager(this._scene, this._camera, context);
        
        // Dark side
        sceneManager.registerScene(TitleScene, 0, 22);
        sceneManager.registerScene(CreditsScene, 22, 39.2);
        sceneManager.registerScene(BonyScene, 39.2, 46.8);
        sceneManager.registerScene(AnimalDramaScene, 46.8, 53.8);

        // Bright side
        sceneManager.registerScene(MeadowScene, 53.8, 122.5);
        sceneManager.registerScene(RainbowGreetsScene, 122.5,160);
        sceneManager.registerScene(ComeBackScene, 160,172);
        sceneManager.registerScene(EndScene, 172, 190);
        
        // Postprocessing
        sceneManager.registerScene(DarkSmokyPartScene, 0, 20);
        sceneManager.registerScene(DarkPartScene, 20, 53.8);
        sceneManager.registerScene(LightPartScene, 53.8, 122.5);
        sceneManager.registerScene(FlowersPartScene,122.5,160)
        sceneManager.registerScene(LightPartScene, 160,10000);

        // Order is important: needs to be registered last so the text ends up top        
        sceneManager.registerScene(PersistentScene, 0, 100000);


        const loadingContext = new LoadingContext(this._loadingPromises, this._spriteManager, this._shaderManager);
        loadingContext.loadShader("sprite", "sprite.vert", "sprite.frag"); // Default shader
        sceneManager.loadScenes(loadingContext);

        this._sceneManager = sceneManager;
    }


    _initializeMusic() {
        var musicManager = new MusicManager(this._camera);
        var promise = musicManager.load("./music/bmaf.mp3");
        this._loadingPromises.push(promise);
        this._musicManager = musicManager;
    }

    _initializeDebugMode() {
        this._debugEl = window.document.getElementById("debugInfo");
        var me = this;
        document.addEventListener('keydown', function (event) {
            if (event.code === 32) {
                me._paused = !me._paused;
                if (me._paused)
                    me._musicManager.pause();
                else
                    me._musicManager.play();
            }
        });
    }

    _showDebugInfo() {
         if (!this._debugEl)
             return;
         this._debugEl.innerHTML = Math.round(this._time);
    }

}