"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const long_1 = tslib_1.__importDefault(require("long"));
const light_1 = require("protobufjs/light");
const log_1 = tslib_1.__importDefault(require("../log"));
const protobuf = tslib_1.__importStar(require("protobufjs/light"));
const models_json_1 = tslib_1.__importDefault(require("./models.json"));
/**
 * ProtobufJS uses Uint8Array for a browser environment but we want the Buffer
 * to be available. The following will force the library to use buffer
 * (https://www.npmjs.com/package/buffer) which combines the efficiency of
 * Uint8Array but provide most of the Buffer interface. See README.
 */
if (!protobuf.util.isNode) {
    // The module is needed only for a specific environment so
    // we delay the import
    // tslint:disable-next-line
    const buffer = require('buffer');
    // @ts-ignore
    protobuf.Reader.prototype._slice = buffer.Buffer.prototype.slice;
    protobuf.Reader.create = (buf) => new light_1.Reader(buffer.Buffer.from(buf));
    // @ts-ignore
    protobuf.util.Long = long_1.default;
    protobuf.configure();
}
/**
 * Detect a wrong import of the protobufsjs library that could lead
 * to inconsistency at runtime because of different bundles
 */
if (protobuf.build !== "light") {
    throw new Error("expecting to use the light module of protobufs");
}
exports.root = protobuf.Root.fromJSON(models_json_1.default);
exports.EMPTY_BUFFER = Buffer.allocUnsafe(0);
/**
 * Register the message to be encoded/decoded by protobufjs. The name
 * should match the one in the model and the dependencies of the
 * message should be provided to insure their registration.
 *
 * @param name          The name of the message in the protobuf definition
 * @param ctor          The message class
 * @param dependencies  The message classes of the dependencies
 */
function registerMessage(name, ctor, ...dependencies) {
    // register the messages used inside the new one
    dependencies.forEach((d) => {
        // as we can have cycle dependencies, this will deal with them by retarding
        // the registration until everything is defined
        if (d && d.register) {
            d.register();
        }
    });
    const m = exports.root.lookupType(name);
    m.ctor = ctor;
    log_1.default.lvl3(`Message registered: ${ctor.name}`);
}
exports.registerMessage = registerMessage;
/**
 * Add a JSON definition to the existing root
 *
 * @param json The definition imported from a json file
 */
function addJSON(json) {
    const temp = protobuf.Root.fromJSON(json);
    for (const nested of exports.root.nestedArray) {
        const ns = temp.lookup(nested.name, protobuf.Namespace);
        if (ns !== null) {
            temp.remove(ns);
        }
    }
    for (const nested of temp.nestedArray) {
        exports.root.add(nested);
    }
}
exports.addJSON = addJSON;
