import Signal from "../../core/events/signal/Signal.js";
import Script from "../ecs/components/Script.js";
import TransitionFunctions from "./TransitionFunctions.js";

class Tween {
    timeElapsed = 0;

    on = {
        ended: new Signal()
    };

    /**
     *
     * @param {function(value:number, timeDelta:number)} callback
     * @param {number} valueStart
     * @param {number} valueEnd
     * @param {number} duration time in seconds
     * @param {function(fraction:number):number} [formula=TransitionFunctions.Linear]
     * @param {boolean} [oscillate=false]
     */
    constructor(
        callback,
        valueStart,
        valueEnd,
        duration,
        formula = TransitionFunctions.Linear,
        oscillate = false
    ) {

        this.oscillate = oscillate;
        this.formula = formula;

        const valueRange = valueEnd - valueStart;
        this.script = new Script( (timeDelta) => {
            this.timeElapsed += timeDelta;
            const timeElapsed = this.timeElapsed;

            const cycleWhole = Math.floor(timeElapsed / duration);
            const cycleFraction = (timeElapsed % duration) / duration;
            let state = cycleFraction;
            if (this.oscillate) {
                if (cycleWhole % 2 === 1) {
                    state = 1 - cycleFraction;
                }
            } else {
                if (cycleWhole > 0) {
                    state = 1;
                    this.on.ended.dispatch();
                    //remove self
                    this.destroy();
                }
            }
            const y = this.formula(state);
            const value = y * valueRange + valueStart;
            callback(value, timeDelta);
        });
    }

    destroy() {
        this.entityManager.removeEntity(this.entity);
    }

    build(em) {
        this.entityManager = em;
        this.entity = em.createEntity();
        em.addComponentToEntity(this.entity, this.script);
        return this.entity;
    }
}


export default Tween;
