import { getConnectedCog } from "../../utils/CogManager";
import { EventBus } from "../EventBus";
import { safeAddSound } from "../../utils/safe-add-sound";
export class Player extends Phaser.Physics.Arcade.Sprite {
    scene;
    hitSound;
    canMoveDown = true;
    canMoveUp = true;
    pointerPressThreshold = 200;
    lastStartTrigger = null;
    constructor(scene) {
        const x = 0;
        const y = 0;
        super(scene, x, y, "marty-in-plane");
        this.scene = scene;
        scene.add.existing(this);
        scene.physics.add.existing(this);
        this.init();
        this.scene.events.on(Phaser.Scenes.Events.UPDATE, this.update, this);
        this.once(Phaser.GameObjects.Events.DESTROY, this.cleanup, this);
    }
    init() {
        if (!this.scene.input.keyboard)
            return;
        // const gravity = 2000 * (this.scene.sky?.scaleFactors.height || 1);
        // this
        //   .setOrigin(0.5, 1)  // Origin at the bottom center of the player
        //   // .setGravityY(gravity)
        //   .setCollideWorldBounds(false)
        //   .setBodySize(90, 120)
        //   .setOffset(35, 0)
        //   .setDepth(4);
        this.registerSounds();
        // Handle resizing
        this.scene.scale.on('resize', this.scaleToFit, this);
        this.scene.scale.on('resize', this.positionOnSky, this);
        this.scaleToFit();
        this.positionOnSky();
    }
    positionOnSky() {
        this
            .setOrigin(0.5, 1) // Origin at the bottom center of the player
            // .setGravityY(gravity)
            .setCollideWorldBounds(false)
            .setBodySize(90, 120)
            .setOffset(35, 0)
            .setDepth(4);
        const visibleWidth = this.scene.scale.width;
        const visibleHeight = this.scene.scale.height;
        const playerHeight = this.displayHeight || 285 * (this.scene.sky?.scaleFactors.height || 1);
        const bottomMargin = Math.max(24, visibleHeight * 0.14);
        const y = Math.max(playerHeight + 8, visibleHeight - bottomMargin);
        this.setY(y);
        this.setX(Math.max(80, visibleWidth * 0.28));
    }
    scaleToFit() {
        // Use the scale factor from the Sky class to maintain consistency
        const scaleFactor = this.scene.sky?.scaleFactors.height || 1;
        const width = 285;
        const height = 285;
        // Apply the scale factor to the player
        this.setDisplaySize(width * scaleFactor, height * scaleFactor);
    }
    getStartTrigger() {
        /* If the player is connected to a cog, use the cog's buttonClick state to determine if the player should jump / start the game */
        /* Otherwise, use the W or S keys to determine if the player should jump / start the game */
        const connectedCog = getConnectedCog();
        if (connectedCog) {
            const buttonClick = connectedCog.publishedDataAnalyser.cogState.buttonClick;
            if (buttonClick === "click" || buttonClick === "release") {
                return buttonClick;
            }
            else if (buttonClick === "none") {
                return "release";
            }
        }
        else {
            if (this.scene.isPreviewOnly)
                return this.scene.previewInputState ?? "release";
            const manualTrigger = this.getManualTrigger();
            if (manualTrigger)
                return manualTrigger;
        }
        return null;
    }
    getManualTrigger() {
        const pointer = this.scene.input?.activePointer;
        const { up, space } = this.scene.cursors || {};
        const isPressed = Boolean(pointer?.isDown || up?.isDown || space?.isDown);
        if (!pointer && !this.scene.cursors)
            return null;
        return isPressed ? "click" : "release";
    }
    manualPressJustStarted() {
        if (getConnectedCog())
            return false;
        const pointer = this.scene.input?.activePointer;
        const pointerPressed = Boolean(pointer?.isDown && pointer.getDuration() < this.pointerPressThreshold);
        const { up, space } = this.scene.cursors || {};
        const keyboardPressed = Boolean(up?.isDown && up.getDuration() < this.pointerPressThreshold)
            || Boolean(space?.isDown && space.getDuration() < this.pointerPressThreshold);
        return pointerPressed || keyboardPressed;
    }
    actionDecider(button) {
        if (!button)
            return;
        if (!this.scene?.sys || !this.active)
            return;
        if (button === "click") {
            if (this.scene.selectedCogClickedBlock?.block === "moveup") {
                this.moveUp(button);
            }
            else if (this.scene.selectedCogClickedBlock?.block === "movedown") {
                this.moveDown(button);
            }
        }
        else if (button === "release") {
            if (this.scene.selectedCogNoClickBlock?.block === "movedown") {
                this.moveDown(button);
            }
            else if (this.scene.selectedCogNoClickBlock?.block === "moveup") {
                this.moveUp(button);
            }
        }
    }
    async moveUp(state = "click") {
        if (!this.canMoveUp)
            return;
        EventBus.emit('action-executed', { block: "moveup", state });
        const minY = this.displayHeight + 8;
        const move = 10;
        for (let i = 0; i < move; i++) {
            if (!this.scene?.sys || !this.active)
                return;
            this.setY(Math.max(minY, this.y - .3));
            await new Promise((resolve) => setTimeout(resolve, 10));
        }
    }
    async moveDown(state = "release") {
        if (!this.canMoveDown)
            return;
        EventBus.emit('action-executed', { block: "movedown", state });
        const maxY = (this.scene.ground?.y ?? this.scene.scale.height) - 4;
        const move = 10;
        for (let i = 0; i < move; i++) {
            if (!this.scene?.sys || !this.active)
                return;
            this.setY(Math.min(maxY, this.y + .5));
            await new Promise((resolve) => setTimeout(resolve, 10));
        }
    }
    isOffScreen() {
        const bounds = this.getBounds();
        const adjustedGameWidth = this.scene.scale.width;
        const isOffScreen = bounds.right < 0 || bounds.left > adjustedGameWidth;
        return isOffScreen;
    }
    update() {
        if (!this.scene?.sys || !this.body)
            return;
        const isCogsButtonClickedOrSpaceDown = this.getStartTrigger();
        if (isCogsButtonClickedOrSpaceDown !== this.lastStartTrigger) {
            EventBus.emit('input-received', {
                source: getConnectedCog() ? 'cog' : 'fallback-keyboard',
                state: isCogsButtonClickedOrSpaceDown,
            });
            this.lastStartTrigger = isCogsButtonClickedOrSpaceDown;
        }
        if (!this.scene.isGameRunning && this.manualPressJustStarted()) {
            this.scene.handleGameStart();
        }
        if (!this.scene.isGameRunning) {
            return;
        }
        this.actionDecider(isCogsButtonClickedOrSpaceDown);
        // if (isCogsButtonClickedOrSpaceDown && !this.scene.isGameRunning && !this.scene.isGameOverVisible) {
        //   this.scene.handleGameStart();
        // }
        // if (!this.scene.isGameRunning) {
        //   return;
        // }
    }
    registerSounds() {
        this.hitSound = safeAddSound(this.scene, "hit", { volume: 0.4 });
    }
    die() {
        this.anims.pause();
        if (this.texture.key !== "marty-hurt") {
            this.setTexture("marty-hurt");
        }
        this.hitSound?.play();
    }
    cleanup() {
        this.scene?.events.off(Phaser.Scenes.Events.UPDATE, this.update, this);
        this.scene?.scale.off('resize', this.scaleToFit, this);
        this.scene?.scale.off('resize', this.positionOnSky, this);
    }
}
