import * as plugins from './smarttime.plugins.js'; import { TimeStamp } from './smarttime.classes.timestamp.js'; export type TimerState = 'initiated' | 'started' | 'paused' | 'completed'; export class Timer { /** * the original amount of milliseconds for this Timer */ public timeInMilliseconds: number; /** * the state of the timer */ public state: TimerState = 'initiated'; /** * completed Promise */ public completed: Promise; /** * a reference to when the Timeout started */ public startedAt: TimeStamp; /** * a reference to when a Timer has been potentially paused */ public pausedAt: TimeStamp; get timeLeft(): number { return this.timeInMilliseconds - this.pausedAt.change; } /** * the current timeout the needs to be canceled when this Timer is stopped */ private currentTimeout: NodeJS.Timeout; // a deferred triggeted when Timer has completed private completedDeferred = plugins.smartpromise.defer(); constructor(timeInMillisecondsArg: number) { this.timeInMilliseconds = timeInMillisecondsArg; this.completed = this.completedDeferred.promise; } /** * starts the timer */ public start() { if (!this.startedAt) { this.currentTimeout = setTimeout(() => { this.completedDeferred.resolve(); }, this.timeInMilliseconds); this.startedAt = new TimeStamp(); } else { throw new Error('timer has been started before. Please use resume instead'); } } public pause() { if (this.startedAt) { clearTimeout(this.currentTimeout); this.currentTimeout = null; this.pausedAt = TimeStamp.fromTimeStamp(this.startedAt); } } public resume() { if (this.startedAt) { this.currentTimeout = setTimeout(() => { this.completedDeferred.resolve(); }, this.timeLeft); } else { throw new Error('timer has NOT been started before. Please use .start() instead'); } } public reset() { this.pause(); this.startedAt = null; this.pausedAt = null; } }