import { ScriptContext } from "./ScriptContext.js";
export class BehaviorSystem {
    errors = [];
    hosts = new Set();
    started = new WeakSet();
    services = new Map();
    registerHost(host) {
        this.hosts.add(host);
    }
    unregisterHost(host) {
        this.hosts.delete(host);
    }
    setService(name, value) {
        this.services.set(name, value);
    }
    async fixedUpdate(options = {}) {
        await this.runPhase("fixed", options);
    }
    async update(options = {}) {
        await this.runStart(options);
        await this.runPhase("update", options);
    }
    async runStart(options) {
        for (const host of [...this.hosts]) {
            if (host.isDestroyed) {
                this.hosts.delete(host);
                continue;
            }
            for (const behavior of host.list()) {
                if (behavior.enabled === false || this.started.has(behavior)) {
                    continue;
                }
                this.started.add(behavior);
                await this.invoke("start", behavior, host, options);
            }
        }
    }
    async runPhase(phase, options) {
        for (const host of [...this.hosts]) {
            if (host.isDestroyed) {
                this.hosts.delete(host);
                continue;
            }
            for (const behavior of host.list()) {
                if (behavior.enabled === false) {
                    continue;
                }
                await this.invoke(phase, behavior, host, options);
            }
        }
    }
    async invoke(phase, behavior, host, options) {
        const context = new ScriptContext({
            phase,
            deltaSeconds: options.deltaSeconds,
            fixedDeltaSeconds: options.fixedDeltaSeconds,
            target: host.target,
            services: this.services
        });
        try {
            if (phase === "start") {
                await behavior.onStart?.(context);
            }
            else if (phase === "fixed") {
                await behavior.onFixedUpdate?.(context);
            }
            else if (phase === "update") {
                await behavior.onUpdate?.(context);
            }
        }
        catch (error) {
            this.errors.push({ phase, behavior, error });
        }
    }
}
//# sourceMappingURL=BehaviorSystem.js.map