import Stat from "../core/model/stat/Stat.js";
import { current_time_in_seconds } from "../core/time/current_time_in_seconds.js";

/**
 *
 * @param {Clock} clock
 */
function updateElapsedTime(clock) {
    const now = current_time_in_seconds();
    const delta = (now - clock.__lastMeasurement) * clock.speed;
    clock.__lastMeasurement = now;
    clock.elapsedTime += delta;
}

/**
 * Construct for keeping track of time
 */
class Clock {

    /**
     * In seconds
     * @type {number}
     * @private
     */
    __lastMeasurement = 0;

    /**
     * In seconds
     * @type {number}
     */
    elapsedTime = 0;

    /**
     * Timestamp when {@link getDelta} was last called
     * In seconds
     * @type {number}
     */
    timeAtDelta = 0;

    /**
     *
     * @type {boolean}
     * @private
     */
    __isRunning = false;


    /**
     * how fast clock ticks in relation to real time
     * Allows us to slow down or speed up flow of time via modifiers, see {@link Stat} for details
     * Default speed is x1, i.e. - unmodified
     * @type {Stat}
     * @readonly
     */
    speed = new Stat(1);

    constructor() {
        this.speed.postprocess = Stat.Process.clampMin(0);
    }

    /**
     *
     * @param {number} v
     */
    set multiplier(v) {
        this.speed.base.set(v);
    }

    /**
     *
     * @returns {number}
     */
    get multiplier() {
        return this.speed.base.getValue();
    }

    start() {
        this.__lastMeasurement = current_time_in_seconds();
        this.timeAtDelta = this.updateElapsedTime();
        this.__isRunning = true;
    }

    stop() {
        this.__isRunning = false;
    }

    pause() {
        this.__isRunning = false;
        //update time
        updateElapsedTime(this);
    }

    /**
     * Elapsed time since last {@link getDelta} call
     * @returns {number} in seconds
     */
    getDelta() {
        const elapsedTime = this.updateElapsedTime();
        const delta = elapsedTime - this.timeAtDelta;
        this.timeAtDelta = elapsedTime;
        return delta;
    }

    /**
     *
     * @returns {number} in seconds
     */
    updateElapsedTime() {
        if (this.__isRunning) {
            updateElapsedTime(this);
        }
        return this.elapsedTime;
    }

    /**
     * Time elapsed so far, since the clock was started
     * Only counts time while running
     * @return {number}
     */
    getElapsedTime() {
        return this.elapsedTime;
    }

    reset() {
        this.elapsedTime = 0;
        this.timeAtDelta = 0;
    }
}


export default Clock;
