"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var bsock = require('bsock');
//fix args with defaults like "force = true" -> "force"
function stripAfterEquals(str) {
    return str.split("=")[0];
}
/**
 * Dynamic library to communicate with FrontblockService remotely
 *
 * This will be automatically injected into the webpages served by FrontblockService
 * Will ask it's service for available RPCs and parse them into methods of this object
 * for convenient access.
 */
class RPCaller {
    constructor(port, server, tls = false) {
        this.socket = bsock.connect(port, server, tls);
    }
    async connect() {
        const info = await this.info();
        info.forEach(i => {
            let f;
            switch (i.type) {
                case 'call':
                    f = this.callGenerator(i.uniqueName, i.argNames);
                    break;
                case 'hook':
                    f = this.hookGenerator(i.uniqueName, i.argNames);
                    break;
                case 'unhook':
                    f = this.unhookGenerator(i.uniqueName, i.argNames);
                    break;
            }
            if (this[i.owner] == null)
                this[i.owner] = {};
            this[i.owner][i.name] = f;
            this[i.owner][i.name].bind(this);
        });
    }
    async info() {
        return await this.socket.call('info');
    }
    callGenerator(fnName, fnArgs) {
        const headerArgs = fnArgs.join(",");
        const argParams = fnArgs.map(stripAfterEquals).join(",");
        return eval('( () => async (' + headerArgs + ') => { return await this.socket.call("' + fnName + '", ' + argParams + ')} )()');
    }
    hookGenerator(fnName, fnArgs) {
        const headerArgs = fnArgs.join(",");
        const argParams = fnArgs.map(stripAfterEquals).join(",");
        return eval(`( () => async (` + headerArgs + (headerArgs.length !== 0 ? "," : "") + ` callback) => {
                            const r = await this.socket.call("` + fnName + `", ` + argParams + `)
                            if(r.uid != null){
                                this.socket.hook(res.uid, callback)
                            }
                            return res
                        } )()`);
    }
    unhookGenerator(fnName, fnArgs) {
        const headerArgs = fnArgs.join(",");
        const argParams = fnArgs.map(stripAfterEquals).join(",");
        if (fnArgs.length != 1)
            console.error("UnhookFunction", fnName, "specified more than one argument: (" + headerArgs + ")");
        return eval(`( () => async (` + headerArgs + `) => {
                            const r = await this.socket.call("` + fnName + `", ` + argParams + `)
                            this.socket.unhook(` + argParams + `)
                            return res
                        } )()`);
    }
}
exports.RPCaller = RPCaller;
