// This Source Code Form is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/
import { protobufsBySchema } from "../messaging/protobuf";
import { recordToDataView } from "../utils/encoding";
import { Logger } from "../utils/logger";
const logger = Logger.getLogger();
export class FoxgloveCommunicator {
    #services = new Map();
    #channels = new Map();
    #serviceCalls = new Map();
    getPublicChannels() {
        return [...this.#channels.values()];
    }
    #getPublicServices() {
        return [...this.#services.values()].map(service => service.name);
    }
    handleReconnect() {
        this.#services.clear();
        this.#channels.clear();
        this.send({ type: "reconnect" });
    }
    handleChannelsAdvertisement(channels) {
        for (const channel of channels) {
            const kind = protobufsBySchema[channel.schemaName]?.kind ?? 'annotations';
            this.#channels.set(channel.id, { ...channel, kind });
        }
        const data = this.getPublicChannels();
        this.send({ type: "channels", data });
    }
    handleChannelsUnadvertisement(channels) {
        for (const channel of channels) {
            this.#channels.delete(channel);
        }
        const data = this.getPublicChannels();
        this.send({ type: "channels", data });
    }
    handleServicesAdvertisement(services) {
        for (const service of services) {
            this.#services.set(service.name, service);
        }
        const data = this.#getPublicServices();
        this.send({ type: "services", data });
    }
    handleServicesUnadvertisement(services) {
        for (const unadvertisedService of services) {
            for (const [name, service] of this.#services) {
                if (service.id === unadvertisedService) {
                    this.#services.delete(name);
                }
            }
        }
        const data = this.#getPublicServices();
        this.send({ type: "services", data });
    }
    handleServiceResponse(response) {
        const name = this.#serviceCalls.get(response.callId) ?? 'unknown';
        this.#serviceCalls.delete(response.callId);
        this.sendWithTransfer({
            type: "service_response",
            data: {
                name,
                ok: true,
                serviceCallId: response.callId,
                buffer: response.data,
                error: null
            }
        }, [response.data.buffer]);
    }
    handleGenericMessage(topic, schema, buffer) {
        this.sendWithTransfer({
            type: "message",
            data: { topic, schema, buffer }
        }, [buffer.buffer]);
    }
    callService({ name, serviceCallId, body = {} }) {
        const service = this.#services.get(name);
        if (!service) {
            this.send({
                type: "service_response",
                data: {
                    name,
                    serviceCallId,
                    ok: false,
                    error: "Service was not advertised",
                    buffer: null
                }
            });
            return;
        }
        if (this.isReady()) {
            this.#serviceCalls.set(serviceCallId, name);
            this.sendServiceCallRequest({
                serviceId: service.id,
                callId: serviceCallId,
                encoding: "json",
                data: recordToDataView(body)
            });
        }
        else {
            logger.warn('Foxglove Communicator Error: requested service call, but connection is not ready');
        }
    }
}
//# sourceMappingURL=communicator.js.map