class Scheduler {

    constructor() {
        this.jobs = [];
    }

    addJob(name, fn, minInterval, maxInterval, runOnStart = true) {
        this.jobs.push({
            name,
            fn,
            minInterval,
            maxInterval,
            runOnStart,
            timer: null,
            running: false
        });
    }

    start() {
        for (const job of this.jobs) {
            this.runJob(job);
        }
    }
    
    runJob(job) {
        const execute = async () => {
            if (job.running) {
                return;
            }

            job.running = true;
            try {
                await job.fn();
            } catch (err) {
                console.log(
                    `[Scheduler Error - ${job.name}]`,
                    err.message
                );
            } finally {
                job.running = false;
            }
            const delay =
                Math.floor(
                    Math.random() *
                    (job.maxInterval - job.minInterval + 1)
                ) + job.minInterval;

            job.timer = setTimeout(execute, delay);
        };

        if (job.runOnStart) {
            execute();
        } else {
            const delay =
                Math.floor(
                    Math.random() *
                    (job.maxInterval - job.minInterval + 1)
                ) + job.minInterval;
            job.timer = setTimeout(execute, delay);
        }
    }
    
    stop(name = null) {
        if (name) {
            const job = this.jobs.find(j => j.name === name);
            if (job && job.timer) {
                clearTimeout(job.timer);
            }
        } else {

            this.jobs.forEach(j => {
                if (j.timer) {
                    clearTimeout(j.timer);
                }
            });
        }
    }
}

module.exports = new Scheduler();