import { EnumeratorExecutor } from "./EnumeratorExecutor";

export class CoroutineExecutor {
	private static _instance: CoroutineExecutor;
	static get instance() {
		return CoroutineExecutor._instance = CoroutineExecutor._instance || new CoroutineExecutor();
	}

	private _executors: EnumeratorExecutor[] = [];
	private _nextExecutors: EnumeratorExecutor[] = [];
	private _isRunning: boolean = false;
	private _cleanRemoved: boolean = false;
	private _scheduler: NodeJS.Timeout = null;
	private _time: number = 0;

	constructor() {
		this._time = new Date().getTime();
		console.debug("[CoroutineV2] Coroutines Start");
		this._scheduler = setInterval(this.update.bind(this), 1 / 60);
	}

	StartCoroutine(executor: EnumeratorExecutor) {
		executor.next(0);
		// TODO: 這邊要考量next後馬上接BaseEnumerator/Iterator的情形

		if (!this._isRunning) {
			this._executors.push(executor);

			if (!this._scheduler) {
				console.debug("[CoroutineV2] Coroutines Start");
				this._time = new Date().getTime();
				this._scheduler = setInterval(this.update.bind(this), 1 / 60);
			} else {
				// console.debug(`[CoroutineV2] Coroutines add now: ${this._executors.length}`);
			}
		} else {
			this._nextExecutors.push(executor);
		}
	}

	StopCoroutineBy(target: any) {
		if (!target) return;

		for (let r of this._executors) {
			if (target === r.target) {
				r.Stop();
			}
		}

		for (let r of this._nextExecutors) {
			if (target === r.target) {
				r.Stop();
			}
		}
	}

	update() {
		const time: number = new Date().getTime();
		const delta: number = (time - this._time) / 1000;
		this._time = time;
		if (this._nextExecutors.length) {
			this._executors.push(...this._nextExecutors);
			// console.debug(`[CoroutineV2] Coroutines addNext now: ${this._executors.length}, next: ${this._nextExecutors.length}`);
			this._nextExecutors.length = 0;
		}

		if (this._cleanRemoved) {
			// 移除[doneFlag=true]的協程
			let index = this._executors.length;
			while (index--) {
				let r = this._executors[index];
				if (r.doneFlag) {
					this._executors.splice(index, 1);
					// console.debug(`[CoroutineV2] Coroutines sub now: ${this._executors.length}`);
				}
			}
			this._cleanRemoved = false;
		}

		if (this._executors.length == 0) {
			console.debug("[CoroutineV2] All Coroutines Done");
			clearInterval(this._scheduler);
			this._scheduler = null;
			return;
		}

		this._isRunning = true;

		// 執行協程
		for (let r of this._executors) {
			if (r.doneFlag || r.pauseFlag || r.childFlag) {
				if (r.doneFlag) {
					this._cleanRemoved = true;
				}
				continue;
			}

			r.next(delta);
		}

		this._isRunning = false;
	}
}