class TimerManager {
    private static _instance: TimerManager;
    public static get Instance(): TimerManager {
        if (!this._instance) {
            this._instance = new TimerManager();
        }
        return this._instance;
    }

    private interval = 1000; // 1 秒
    private counter = 0;
    private timer: NodeJS.Timeout | null = null;
    private timerPolicies: TimerPolicy[] = [];

    private constructor() {
        this.timer = setInterval(() => {
            this.timerPolicies.forEach(item => {
                if (this.counter * this.interval % item.interval === 0) {
                    if (item.isAsynchronization) {
                        setTimeout(item.action, 0);
                    } else {
                        item.action();
                    }
                }
            });
            if (this.counter === Number.MAX_SAFE_INTEGER) {
                this.counter = 0;
            }
            this.counter++;
        }, this.interval);
    }

    public addTimerPolicy(policy: TimerPolicy) {
        if (!policy || !policy.action) return;
        this.timerPolicies.push(policy);
        if (!this.timer) {
            this.timer = setInterval(() => {
                this.timerPolicies.forEach(item => {
                    if (this.counter * this.interval % item.interval === 0) {
                        if (item.isAsynchronization) {
                            setTimeout(item.action, 0);
                        } else {
                            item.action();
                        }
                    }
                });
                if (this.counter === Number.MAX_SAFE_INTEGER) {
                    this.counter = 0;
                }
                this.counter++;
            }, this.interval);
        }
    }

    public removeTimerPolicy(policy: TimerPolicy) {
        if (!policy) return;
        const index = this.timerPolicies.indexOf(policy);
        if (index !== -1) {
            this.timerPolicies.splice(index, 1);
        }
        if (this.timer && this.timerPolicies.length === 0) {
            clearInterval(this.timer);
            this.timer = null;
        }
    }
}

class TimerPolicy {
    constructor(
        public action: () => void,
        public interval: number,
        public isAsynchronization = false
    ) {
        if (!interval) {
            this.interval = this.interval * 100;
        }
    }
}

export { TimerManager, TimerPolicy };