export class Runtime {
    constructor(private port: number) {}

    async connect(): Promise<RuntimeConnection> {
        return new RuntimeConnection(
            await Deno.connect({
                port: this.port,
            }),
        );
    }
}

export class RuntimeConnection {
    constructor(private connection: Deno.Conn) {}

    async write(text: string): Promise<void> {
        const req = new TextEncoder().encode(text);
        await this.connection.write(req);
    }

    async send<T>(value: T): Promise<void> {
        await this.write(JSON.stringify(value));
    }

    async read(): Promise<string> {
        let result = "";
        while (true) {
            const buf = new Uint8Array(256);
            const readRes = await this.connection.read(buf);
            if (readRes != null) {
                result += new TextDecoder().decode(buf.slice(0, readRes));
            } else {
                break;
            }
        }
        return result;
    }

    async receive<T>(): Promise<T> {
        return JSON.parse(await this.read()) as T;
    }

    close() {
        this.connection.close();
    }
}