export class TerminalOwner {
    input;
    active = "idle";
    constructor(input = process.stdin) {
        this.input = input;
    }
    get state() {
        return this.active;
    }
    claimReadline() {
        this.assertCanOwn("readline");
        this.active = "readline";
        let released = false;
        return () => {
            if (released)
                return;
            released = true;
            if (this.active === "readline")
                this.active = "idle";
        };
    }
    async withChildProcess(readline, fn) {
        if (this.active !== "idle" && this.active !== "readline") {
            throw new Error(`Terminal already owned by ${this.active}; cannot start child`);
        }
        const previous = this.active;
        this.active = "child";
        try {
            try {
                readline?.pause();
            }
            catch {
                // Piped input can close readline before queued work finishes.
            }
            try {
                this.input.pause();
            }
            catch {
                // Non-standard test streams may already be closed.
            }
            return await fn();
        }
        finally {
            try {
                this.input.resume();
            }
            catch {
                // EOF/non-TTY test harnesses can close stdin while a child-owned task is settling.
            }
            try {
                readline?.resume();
            }
            catch {
                // Readline may already be closed after piped input EOF; ownership must still reset.
            }
            this.active = previous;
        }
    }
    assertCanOwn(next) {
        if (this.active !== "idle") {
            throw new Error(`Terminal already owned by ${this.active}; cannot start ${next}`);
        }
    }
}
