import TilePropertyHelper from '../systems/TilePropertyHelper.js';

export default class Player {
    /**
     * @param {Phaser.Scene} scene
     * @param {number} x  World pixel x (center)
     * @param {number} y  World pixel y (center)
     * @param {Phaser.Tilemaps.TilemapLayer} laddersLayer
     */
    constructor(scene, x, y, laddersLayer) {
        this._scene = scene;
        this._laddersLayer = laddersLayer;

        this.lives = 3;
        this.onLadder = false;
        this.atLadderTop = false;

        // Create physics sprite
        this._sprite = scene.physics.add.sprite(x, y, 'player', 0);
        this._sprite.setCollideWorldBounds(false);
        // Body is narrower/shorter than the 128x256 frame to fit the character artwork
        this._sprite.body.setSize(80, 240).setOffset(24, 8);

        // Animations
        scene.anims.create({
            key: 'walk',
            frames: scene.anims.generateFrameNumbers('player', { start: 0, end: 1 }),
            frameRate: 8,
            repeat: -1,
        });
        scene.anims.create({
            key: 'stand',
            frames: [{ key: 'player', frame: 0 }],
            frameRate: 1,
            repeat: 0,
        });

        this._cursors = scene.input.keyboard.createCursorKeys();
        this._jumpKey = this._cursors.up;
    }

    get sprite() { return this._sprite; }
    get body()   { return this._sprite.body; }

    update(time, delta) {
        this._handleLadder();
        this._handleMovement();
        this._updateAnimation();
    }

    _handleLadder() {
        const sprite = this._sprite;
        const cursors = this._cursors;

        // Tile at player center (for body-of-ladder detection)
        const centerTile = this._laddersLayer.getTileAtWorldXY(sprite.x, sprite.y);
        // Tile at player feet (for ladder-top detection)
        const feetTile = this._laddersLayer.getTileAtWorldXY(sprite.x, sprite.y + 116);

        const centerIsLadder = centerTile && TilePropertyHelper.isLadder(centerTile.index);
        const feetIsLadderTop = feetTile && TilePropertyHelper.isLadderTop(feetTile.index);

        // Update atLadderTop: feet are resting on a top rung and not actively climbing
        this.atLadderTop = !!(feetIsLadderTop && !this.onLadder);

        if (this.onLadder) {
            // Move up or down
            if (cursors.up.isDown) {
                sprite.body.setVelocityY(-200);
            } else if (cursors.down.isDown) {
                sprite.body.setVelocityY(200);
            } else {
                sprite.body.setVelocityY(0);
            }

            // Exit ladder when pressing left or right
            if (cursors.left.isDown || cursors.right.isDown) {
                this._exitLadder();
                return;
            }

            // Exit ladder if center is no longer over a ladder tile
            if (!centerIsLadder) {
                this._exitLadder();
            }
        } else {
            // Enter ladder when player center overlaps a ladder tile and pressing up/down
            if (centerIsLadder && (cursors.up.isDown || cursors.down.isDown)) {
                this.onLadder = true;
                sprite.body.setGravityY(-800); // Cancels world gravity (800 + -800 = 0)
                sprite.body.setVelocityY(0);
                sprite.body.setVelocityX(0);
                // Snap horizontally to ladder center
                sprite.x = centerTile.pixelX + 64;
            }
        }
    }

    _exitLadder() {
        this.onLadder = false;
        this._sprite.body.setGravityY(0); // Remove local gravity override; world gravity resumes
    }

    _handleMovement() {
        if (this.onLadder) return;

        const sprite = this._sprite;
        const cursors = this._cursors;
        const body = sprite.body;

        // Horizontal movement
        if (cursors.left.isDown) {
            body.setVelocityX(-250);
            sprite.setFlipX(true);
        } else if (cursors.right.isDown) {
            body.setVelocityX(250);
            sprite.setFlipX(false);
        } else {
            body.setVelocityX(0);
        }

        // Jump: only on key press (JustDown prevents hold-to-jump repeat)
        // Allowed when: grounded AND (not on ladder OR standing at ladder top)
        if (Phaser.Input.Keyboard.JustDown(this._jumpKey)) {
            if (body.blocked.down) {
                body.setVelocityY(-550);
            }
        }
    }

    _updateAnimation() {
        const sprite = this._sprite;

        if (this.onLadder) {
            sprite.anims.stop();
            sprite.setFrame(0);
            return;
        }

        if (sprite.body.velocity.x !== 0) {
            sprite.anims.play('walk', true);
        } else {
            sprite.anims.play('stand', true);
        }
    }
}
