// Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0.
// SPDX-License-Identifier: MPL-2.0
import "./_dnt.polyfills.js";
import { inspect } from "util";
// import { createInterface, Interface } from "node:readline";
import process from "process";
/**
 * see: module level documentation `meta-cli/src/deploy/actors/task.rs`
 */
const JSONRPC_VERSION = "2.0";
function writeRpcMessage(message) {
    // split into 32-KiB chunks
    const chunkSize = 32758; // 32 KiB - 10 bytes for "jsonrpc^: " or "jsonrpc$: "
    for (let i = 0; i < message.length; i += chunkSize) {
        const chunk = message.slice(i, i + chunkSize);
        if (i + chunkSize < message.length) {
            process.stdout.write(`jsonrpc^: ${chunk}\n`);
            continue;
        }
        process.stdout.write(`jsonrpc$: ${message.slice(i, i + chunkSize)}\n`);
    }
}
// deno-lint-ignore no-explicit-any
const rpcNotify = (method, params = null) => {
    const message = JSON.stringify({
        jsonrpc: JSONRPC_VERSION,
        method,
        params,
    });
    writeRpcMessage(message);
};
// deno-lint-ignore no-explicit-any
function getOutput(args) {
    return args
        .map((arg) => {
        if (typeof arg === "string")
            return arg;
        return inspect(arg, {
            colors: process.stdout.isTTY,
            depth: 10,
            maxStringLength: 1000,
            maxArrayLength: 20,
        });
    })
        .join(" ");
}
export const log = {
    debug(...args) {
        rpcNotify("Debug", { message: getOutput(args) });
    },
    info(...args) {
        rpcNotify("Info", { message: getOutput(args) });
    },
    warn(...args) {
        rpcNotify("Warning", { message: getOutput(args) });
    },
    error(...args) {
        rpcNotify("Error", { message: getOutput(args) });
    },
    failure(data) {
        rpcNotify("Failure", { data: data });
    },
    success(data, noEncode = false) {
        if (noEncode) {
            rpcNotify("Success", { data: JSON.parse(data) });
        }
        else {
            rpcNotify("Success", { data: data });
        }
    },
};
class RpcResponseReader {
    constructor() {
        Object.defineProperty(this, "buffer", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: ""
        });
        process.stdin.setEncoding("utf-8");
    }
    read(id) {
        return new Promise((resolve, reject) => {
            const handler = () => {
                while (true) {
                    const chunk = process.stdin.read();
                    if (chunk == null) {
                        break;
                    }
                    this.buffer += chunk;
                    const lines = this.buffer.split(/\r\n|\n/);
                    if (lines.length > 2) {
                        reject(new Error("not sequential"));
                    }
                    else if (lines.length <= 1) {
                        continue;
                    }
                    this.buffer = lines.pop();
                    try {
                        const message = JSON.parse(lines[0]);
                        if (message.id === id) {
                            resolve(message.result);
                            break;
                        }
                    }
                    catch {
                        reject("invalid message");
                    }
                }
                process.stdin.off("readable", handler);
            };
            process.stdin.on("readable", handler);
        });
    }
}
const rpcCall = (() => {
    const responseReader = new RpcResponseReader();
    let latestRpcId = 0;
    // deno-lint-ignore no-explicit-any
    return (method, params = null) => {
        const rpcId = latestRpcId++;
        const rpcMessage = JSON.stringify({
            jsonrpc: JSONRPC_VERSION,
            id: rpcId,
            method,
            params,
        });
        writeRpcMessage(rpcMessage);
        return responseReader.read(rpcId);
    };
})();
export const rpc = {
    getDeployTarget: () => rpcCall("GetDeployTarget"),
    getDeployData: (typegraph) => rpcCall("GetDeployData", { typegraph }),
};
