import { getHighScore, updateHighScore } from '../../utils/high-score-store';
import { Player } from '../entities/Player';
import { EventBus } from '../EventBus';

interface Exit {
    rect: Phaser.Geom.Rectangle,
    startX: number,
    startY: number,
    facing: string,
    scene: string
    level: number
}

class Level extends Phaser.Scene {

    gamepaused: Phaser.GameObjects.Image | undefined;
    player: Player | undefined;
    exits: Exit[];
    centerMap: Phaser.Tilemaps.Tilemap | undefined;
    level: number;

    stars: Phaser.Physics.Arcade.Group | null = null;

    score: number;

    constructor(config: Phaser.Types.Scenes.SettingsConfig) {
        super((config) ? config : { key: 'level' });
        this.gamepaused = undefined;

        this.player = undefined;
        this.exits = [];

        this.level = 0;
        this.score = 0;
    }

    create() {
        this.cameras.main.setRoundPixels(true);
        // start controls
        this.controls.start();

        this.exits = [];
        this.cameras.main.setBackgroundColor('#00FF00');

        EventBus.emit('current-scene-ready', this);
    }

    postCreate() {
        this.gamepaused = this.add.image(+this.sys.game.config.width / 2, +this.sys.game.config.height / 2, 'gamepaused');
        this.gamepaused.visible = false;
        this.gamepaused.setScrollFactor(0);
        this.gamepaused.setDepth(3);

        this.resizeField(+this.sys.game.config.width, +this.sys.game.config.height);
        this.cameras.main.flash(3000, window.fadeColor.r, window.fadeColor.g, window.fadeColor.b);
    }

    addPlayer({
        x = 64,
        y = 64
    } = {}) {
        this.player = new Player(this, x, y, 'player', "0", this.startPosition.facing);
        this.cameras.main.startFollow(this.player, true);
    }

    addExit({
        x = -480,
        y = 0,
        w = 512,
        h = 2048,
        startX = 64,
        startY = 64,
        facing = 'right',
        scene = "",
        level = 0
    } = {}) {
        if (!scene) {
            return;
        }
        const exit: Exit = {
            rect: new Phaser.Geom.Rectangle(x, y, w, h),
            startX: startX,
            startY: startY,
            facing: facing,
            scene: scene,
            level: level
        };
        this.exits.push(exit);

        // DEBUGGING: paint the exit for debugging
        if (this.game.config.physics.arcade?.debug) {
            const graphics = this.add.graphics();
            graphics.fillStyle(0x0000ff, 0.5); // sets the fill color and alpha
            graphics.fillRect(x, y, w, h);     // draws the rectangle
            graphics.fillPath(); // applies the fill
        }
    }

    checkExits() {
        if (!this.exits || !this.exits.length || !this.player) {
            return;
        }
        for (let exit of this.exits) {
            if (Phaser.Geom.Rectangle.ContainsPoint(exit.rect, this.player as unknown as Phaser.Geom.Point)) {
                //console.log('time to go');
                this.leaveThroughExit(exit);
                this.player.disappear();
                this.exits = [];
                break;
            }
        }
    }

    createStars() {
        this.stars = this.physics.add.group();
    }

    handleStarCollisions() {
        if (!this.stars) return;
        if (!this.player) return;
        this.physics.add.overlap(this.stars, this.player, (player, star) => {
            this.stars?.remove((star as Phaser.GameObjects.GameObject));
            star.destroy();
            this.score += 40;

            const currentHighScore = getHighScore();
            if (this.score > currentHighScore) {
                updateHighScore(this.score);
            }

            EventBus.emit('player-collected-star', this);
        });
    }

    leaveThroughExit({
        startX = 0,
        startY = 0,
        facing = 'right',
        scene = "",
        level = 0,
    }: Exit) {

        if (level >= 4) {
            this.showGameOver();
            return;
        }

        if (!scene) {
            return;
        }
        this.startPosition.setExit({ x: startX, y: startY, facing: facing, scene: scene });

        if (this.level > level) {
            // going back -- subtract score
            this.score -= this.level * 100;
        } else {
            // going forward -- add score
            this.score += level * 100;
        }

        this.level = level;
        this.cameras.main.once('camerafadeoutcomplete', (camera: Phaser.Cameras.Scene2D.Camera, effect: Phaser.Cameras.Scene2D.Effects.Fade, thisArg: any) => {
            this.scene.start(scene);
        }, this);
        window.fadeColor = { r: 5, g: 4, b: 4 };
        this.cameras.main.fadeOut(3000, window.fadeColor.r, window.fadeColor.g, window.fadeColor.b);

        const currentHighScore = getHighScore();
        if (this.score > currentHighScore) {
            updateHighScore(this.score);
        }
        EventBus.emit('player-went-through-exit', this);
    }

    resizeField(w: number, h: number) {
        //console.log(w, h);
        if (this.gamepaused) {
            this.gamepaused.x = w / 2;
            this.gamepaused.y = h / 2;
        }
        if (this.centerMap) {
            this.cameras.main.setBounds((this.centerMap.widthInPixels - w) / 2, (this.centerMap.heightInPixels - h) / 2, w, h);
        }
    }

    onGamePause() {
        if (this.gamepaused) {
            // don't show "paused" message
            // this.gamepaused.visible = true;
        }
    }

    onGameResume() {
        if (this.gamepaused) {
            // don't show "paused" message
            // this.gamepaused.visible = false;
        }
    }

    showGameOver() {
        this.level = 0;
        EventBus.emit('game-finished', this);
        this.cameras.main.fadeOut(5000, 0, 0, 0, () => {
            this.time.delayedCall(5000, () => {
                this.scene.start("boot"); 
                EventBus.emit('game-finished', this);
            });
        });
    }
}

export default Level;
