import {AdvancedDynamicTexture, Control, StackPanel, TextBlock} from "@babylonjs/gui";
import {DefaultScene} from "./defaultScene";
import {
    Angle,
    MeshBuilder,
    Observable, StandardMaterial,
    Vector3,
} from "@babylonjs/core";
export type ScoreEvent = {
    score: number,
    message: string,
    remaining: number,
    timeRemaining? : number
}
export class Scoreboard {
    private _score: number = 0;
    private _remaining: number = 0;
    private _timeRemaining: number = 61;
    private _lastMessage: string = null;
    private _active = false;
    private _done = false;
    public readonly onScoreObservable: Observable<ScoreEvent> = new Observable<ScoreEvent>();
    constructor() {
        DefaultScene.MainScene.onNewMeshAddedObservable.add((mesh) => {
           if (mesh.id == 'RightUpperDisplay') {
               this.initialize();
           }
        });
    }
    public get done() {
        return this._done;
    }
    public set done(value: boolean) {
        this._done = value;
    }
    private initialize() {
        const scene = DefaultScene.MainScene;

        const parent = scene.getMeshById('RightUpperDisplay');
        const scoreboard = MeshBuilder.CreatePlane("scoreboard", {width: 1, height: 1}, scene);
        const material = new StandardMaterial("scoreboard", scene);

        scoreboard.parent =parent;
        scoreboard.position.x = -.76;
        scoreboard.position.y = 4.19;
        scoreboard.position.z = .53;
        scoreboard.rotation.x = Angle.FromDegrees(104).radians();
        scoreboard.rotation.z = Math.PI;
        scoreboard.scaling = new Vector3(.3, .3, .3);

        const advancedTexture = AdvancedDynamicTexture.CreateForMesh(scoreboard, 512, 512);
        advancedTexture.background = "black";
        advancedTexture.hasAlpha = false;
        const scoreText = this.createText();

        const fpsText = this.createText();
        fpsText.text = "FPS: 60";

        const hullText = this.createText();
        hullText.text = 'Hull: 100%';

        const remainingText = this.createText();
        remainingText.text = 'Remaining: 0';

        const timeRemainingText = this.createText();
        timeRemainingText.text = 'Time: 2:00';

        const panel = new StackPanel();
        panel.isVertical = true;
        panel.height = 1;
        panel.isVertical = true;
        panel.addControl(scoreText);
        panel.addControl(remainingText);
        panel.addControl(fpsText);
        panel.addControl(hullText);
        panel.addControl(timeRemainingText);

        advancedTexture.addControl(panel);

        let i = 0;
        let lastSecond: number = Date.now();
        const afterRender = scene.onAfterRenderObservable.add(() => {
            scoreText.text = `Score: ${this.calculateScore()}`;
            remainingText.text = `Remaining: ${this._remaining}`;
            const now = Date.now();
            if (this._active && (Math.floor(lastSecond / 1000) < Math.floor(now/1000))) {
                this._timeRemaining--;
                if (this._timeRemaining <= 0) {
                    scene.onAfterRenderObservable.remove(afterRender);
                }
                lastSecond = now;
                timeRemainingText.text = `Time: ${Math.floor(this._timeRemaining/60).toString().padStart(2,"0")}:${(this._timeRemaining%60).toString().padStart(2,"0")}`;
            }
            if (i++%60 == 0) {
                fpsText.text = `FPS: ${Math.floor(scene.getEngine().getFps())}`;
            }
        });

        this.onScoreObservable.add((score: ScoreEvent) => {
            this._score += score.score * this._timeRemaining;
            this._remaining += score.remaining;
            this._lastMessage = score.message;
            if (score.timeRemaining) {
                this._timeRemaining = score.timeRemaining;
            }
        });
        this._active = true;
    }
    private createText(): TextBlock {
        const text1 = new TextBlock();
        text1.color = "white";
        text1.fontSize = "60px";
        text1.height = "80px";
        text1.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
        text1.textVerticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
        return text1;
    }
    private calculateScore() {
        return Math.floor(this._score);
    }
}