var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
    if (kind === "m") throw new TypeError("Private method is not writable");
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
    return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
    return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _UIRequestBuilder_env, _UIRequestBuilder_props, _LocalRuntime_local, _LocalRuntime_runtimeDebugLogging, _LocalRuntime_onPluginCall;
import { RealtimeDefinition, } from '@devvit/protos';
import { BrowserLiteClient } from '@devvit/runtime-lite/client/BrowserLiteClient.js';
import { WrappedRequest, WrappedResponse, } from './mappers.js';
export const RenderPostContent = 'RenderPostContent';
export const supportedMethods = new Set([RenderPostContent]);
function getMethodNameFromHandle(input) {
    if (supportedMethods.has(input.split('/').at(-1)))
        return input;
    // If you need to add a method, please make sure it is available in the remote
    // runtime inside of play and the remote-app.ts file inside of ui-renderer. You also
    // need to make sure the local runtime has support for the method.
    //
    // Once you've added support, add it to the supportedMethods array.
    throw Error(`Unsupported RPC ${input}`);
}
export class UIRequestBuilder {
    constructor(env) {
        _UIRequestBuilder_env.set(this, void 0);
        _UIRequestBuilder_props.set(this, void 0);
        __classPrivateFieldSet(this, _UIRequestBuilder_env, env, "f");
    }
    set env(env) {
        __classPrivateFieldSet(this, _UIRequestBuilder_env, env, "f");
    }
    set props(props) {
        __classPrivateFieldSet(this, _UIRequestBuilder_props, props, "f");
    }
    build(state, events) {
        // TODO: We need to decide if env will be a build arg or if we need to add this on top of the UI request
        // builder
        return new WrappedRequest({
            state: state,
            events: events.map((x) => x.uiEvent),
            env: __classPrivateFieldGet(this, _UIRequestBuilder_env, "f"),
            props: __classPrivateFieldGet(this, _UIRequestBuilder_props, "f"),
        });
    }
}
_UIRequestBuilder_env = new WeakMap(), _UIRequestBuilder_props = new WeakMap();
export class ReplayUIResponse {
    constructor(rsp) {
        this.blocks = rsp.blocks;
        this.effects = rsp.effects;
        this.state = rsp.state;
        this.events = rsp.events;
    }
    get replay() {
        return this.events;
    }
}
export class LocalRuntime {
    constructor() {
        /**
         * A client to the local runtime.
         * @internal
         */
        _LocalRuntime_local.set(this, void 0);
        _LocalRuntime_runtimeDebugLogging.set(this, false);
        _LocalRuntime_onPluginCall.set(this, (id, serviceName, method, args, meta) => {
            this.onPluginCall?.(id, serviceName, method, args, meta);
            if (serviceName === RealtimeDefinition.fullName &&
                method === RealtimeDefinition.methods.send.name)
                __classPrivateFieldGet(this, _LocalRuntime_local, "f")?.onPluginResponse(id, { error: undefined, success: true, value: {} });
        });
    }
    isReady() {
        return !!__classPrivateFieldGet(this, _LocalRuntime_local, "f")?.ready;
    }
    set runtimeDebugLogging(on) {
        __classPrivateFieldSet(this, _LocalRuntime_runtimeDebugLogging, on, "f");
        if (__classPrivateFieldGet(this, _LocalRuntime_local, "f"))
            __classPrivateFieldGet(this, _LocalRuntime_local, "f").runtimeDebugLogging = on;
    }
    /** Set the runtime source code. */
    setLocalSrc(src) {
        this.unload();
        __classPrivateFieldSet(this, _LocalRuntime_local, src
            ? new BrowserLiteClient(src, 
            // There are unknown and unhandled errors that means the system is in a very unexpected spot.
            // We just log these for now do not forward them to KMP.
            (type, err) => console.error(type, err), {
                callback: __classPrivateFieldGet(this, _LocalRuntime_onPluginCall, "f"),
                plugins: [],
            })
            : undefined, "f");
        if (__classPrivateFieldGet(this, _LocalRuntime_local, "f"))
            __classPrivateFieldGet(this, _LocalRuntime_local, "f").runtimeDebugLogging = __classPrivateFieldGet(this, _LocalRuntime_runtimeDebugLogging, "f");
    }
    unload() {
        __classPrivateFieldGet(this, _LocalRuntime_local, "f")?.quit();
    }
    /**
     * Load an app bundle into the local runtime, if available. The bundle is
     * assumed to implement a UIApp.
     */
    async load(app) {
        this.unload();
        try {
            return await __classPrivateFieldGet(this, _LocalRuntime_local, "f")?.loadBundle(app);
        }
        catch (err) {
            console.error(err);
        }
    }
    handle(method, req, cb, err) {
        if (!this.isReady() || !__classPrivateFieldGet(this, _LocalRuntime_local, "f")) {
            throw new Error('local runtime handle called before isReady');
        }
        if (devvit?.debug.runtime)
            console.debug('[runtime] Local request', req, this.metadata);
        __classPrivateFieldGet(this, _LocalRuntime_local, "f")
            ?.call(getMethodNameFromHandle(method), req.uiRequest, this.metadata)
            .then((rsp) => cb(new WrappedResponse(rsp)))
            .catch((e) => err(e));
    }
    /**
     * No-ops for web, but used on native!
     */
    pause() { }
    reset() { }
    resume() { }
    snapshot() {
        return {};
    }
}
_LocalRuntime_local = new WeakMap(), _LocalRuntime_runtimeDebugLogging = new WeakMap(), _LocalRuntime_onPluginCall = new WeakMap();
export class RemoteRuntime {
    // TODO: Note that while this is called, it doesn't prevent the KMP dispatcher from
    // calling the associated handle method. This feels like a bug in KMP?
    isReady() {
        return !!this.remote;
    }
    // TODO: Is this an anti-pattern to pass an already constructed UIApp into RemoteApp?
    // That means we can't effectively handle load or pass it in dynamic metadata (like the
    // local runtime).
    load(remote) {
        this.remote = remote;
    }
    handle(method, req, cb, err) {
        if (!this.isReady() || !this.remote) {
            throw new Error(`remote runtime called remote before isReady()`);
        }
        // We're not using promises due to cross platform concerns!
        this.remote[getMethodNameFromHandle(method)](req.uiRequest, this.metadata)
            .then((rsp) => cb(new WrappedResponse(rsp)))
            .catch(err);
    }
    /**
     * No-ops for web, but used on native!
     */
    pause() { }
    reset() { }
    resume() { }
    snapshot() {
        return {};
    }
}
//# sourceMappingURL=runtimes.js.map