// Fake timer for node.js which _guarantees_ that all asynchronous timer
// callbacks are called during a tested period

function FakeTimer(startTime)
{
    this.time = Number(startTime)||0;
    this.timers = [];
    this.id = 0;
    this.setTimeout = (func, ms) =>
    {
        this.timers.push({ id: ++this.id, func, at: this.time+ms });
        return this.id;
    };
    this.setInterval = (func, ms) =>
    {
        this.timers.push({ id: ++this.id, func, at: this.time+ms, repeat: ms });
        return this.id;
    };
    this.clearInterval = this.clearTimeout = (id) =>
    {
        this.timers = this.timers.filter(t => t.id != id);
    };
    this.setImmediate = (func) => this.setTimeout(func, 0);
    this.runFor = (ms) =>
    {
        const end = this.time+ms;
        this.timers.sort((a, b) => a.at - b.at);
        while (this.timers.length && this.timers[0].at <= end)
        {
            const { func, at, repeat } = this.timers[0];
            if (!repeat)
                this.timers.shift();
            else
                this.timers[0].at += repeat;
            if (at > this.time)
                this.time = at;
            func();
            this.timers.sort((a, b) => a.at - b.at);
        }
        this.time = end;
    };
}

module.exports = FakeTimer;
