import Reel from '../../systems/reels/Reel';
import { easeInOutBack } from '../../utils/easing/easeInOutBack';
import { REEL_STATES } from './states';
import { State } from '@popiplay/state-machine';

/**
 * @class Acceleration
 * @extends State
 * @description Represents the acceleration phase of a reel. In this state, the reel gradually increases
 * its speed up to a defined maximum speed using an easing function.
 */
export default class Acceleration extends State
{
    private reel: Reel;
    private elapsedTime: number;
    private t: number;

    /**
     * @class
     * @param {Reel} reel - The reel instance that this state belongs to.
     */
    constructor(reel: Reel)
    {
        super('Acceleration');
        this.reel = reel;
        this.elapsedTime = 0;
        this.t = 0;
    }

    /** Initializes the state by resetting the elapsed time and easing progress. Called when the state is entered. */
    override enter(): void
    {
        this.elapsedTime = 0; // Total time spent in the acceleration phase
        this.t = 0; // Normalized time (from 0 to 1) for easing calculations
    }

    /**
     * Updates the reel's position and speed based on elapsed time and an easing function.
     * The reel's speed is increased smoothly up to the maximum speed defined in reel settings.
     * @param {number} dt - Delta time since the last update, in milliseconds.
     */
    override update(dt: number): void
    {
        this.elapsedTime += dt * 0.001;
        this.t = Math.min(this.elapsedTime / this.reel.accelerationTime, 1);

        // Apply easing function to calculate progress
        const easedProgress = easeInOutBack(this.t, this.reel.backCoef);

        // Update reel speed and position
        this.reel.speed = this.reel.maxSpeed * easedProgress;
        this.reel.position += dt * 0.001 * this.reel.speed;
    }

    /**
     * Handles state transition input. Transitions the reel to the spinning state
     * once half of the acceleration duration has passed.
     * @param {unknown} _input - Optional input for state handling, unused in this implementation.
     */
    override handleInput(_input: unknown): void
    {
        if (this.t >= 0.5)
        {
            this.reel.setState(REEL_STATES.SPINNING);
        }
    }

}
