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: console.Scheduler;

    constructor() {
        this._scheduler = console.director.getScheduler();
        this._scheduler.enableForTarget(this);
        this._scheduler.scheduleUpdate(this, 0, true);
    }

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

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

            if (this._scheduler.isTargetPaused(this)) {
                this._scheduler.resumeTarget(this);
            }
        } 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(delta: number) {
        if (this._nextExecutors.length) {
            this._executors.push(...this._nextExecutors);
            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);
                }
            }
            this._cleanRemoved = false;
        }

        if (this._executors.length == 0) {
            if (true) {
                console.log("[CoroutineV2] All coroutines done");
            }
            this._scheduler.pauseTarget(this);
            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;
    }
}