import { EventType, IncrementalSource } from '../types.js';

class Timer {
    constructor(actions = [], speed) {
        this.timeOffset = 0;
        this.raf = null;
        this.actions = actions;
        this.speed = speed;
    }
    addAction(action) {
        const index = this.findActionIndex(action);
        this.actions.splice(index, 0, action);
    }
    addActions(actions) {
        this.actions = this.actions.concat(actions);
    }
    replaceActions(actions) {
        this.actions.length = 0;
        this.actions.splice(0, 0, ...actions);
    }
    start() {
        this.timeOffset = 0;
        let lastTimestamp = performance.now();
        const { actions } = this;
        const self = this;
        function check() {
            const time = performance.now();
            self.timeOffset += (time - lastTimestamp) * self.speed;
            lastTimestamp = time;
            while (actions.length) {
                const action = actions[0];
                if (self.timeOffset >= action.delay) {
                    actions.shift();
                    action.doAction();
                }
                else {
                    break;
                }
            }
            if (actions.length > 0 || self.liveMode) {
                self.raf = requestAnimationFrame(check);
            }
        }
        this.raf = requestAnimationFrame(check);
    }
    clear() {
        if (this.raf) {
            cancelAnimationFrame(this.raf);
            this.raf = null;
        }
        this.actions.length = 0;
    }
    setSpeed(speed) {
        this.speed = speed;
    }
    toggleLiveMode(mode) {
        this.liveMode = mode;
    }
    isActive() {
        return this.raf !== null;
    }
    findActionIndex(action) {
        let start = 0;
        let end = this.actions.length - 1;
        while (start <= end) {
            const mid = Math.floor((start + end) / 2);
            if (this.actions[mid].delay < action.delay) {
                start = mid + 1;
            }
            else if (this.actions[mid].delay > action.delay) {
                end = mid - 1;
            }
            else {
                return mid + 1;
            }
        }
        return start;
    }
}
function addDelay(event, baselineTime) {
    if (event.type === EventType.IncrementalSnapshot &&
        event.data.source === IncrementalSource.MouseMove) {
        const firstOffset = event.data.positions[0].timeOffset;
        const firstTimestamp = event.timestamp + firstOffset;
        event.delay = firstTimestamp - baselineTime;
        return firstTimestamp - baselineTime;
    }
    event.delay = event.timestamp - baselineTime;
    return event.delay;
}

export { Timer, addDelay };
