// automatically generated by the FlatBuffers compiler, do not modify
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any,
 * @typescript-eslint/no-non-null-assertion */
import * as flatbuffers from 'flatbuffers';

import {KeyValue} from '../reflection/key-value.js';
import {Object_} from '../reflection/object.js';

export class RPCCall {
  constructor() {
    this.bb = null;
    this.bb_pos = 0;
  }
  __init(i, bb) {
    this.bb_pos = i;
    this.bb = bb;
    return this;
  }
  static getRootAsRPCCall(bb, obj) {
    return (obj || new RPCCall())
        .__init(bb.readInt32(bb.position()) + bb.position(), bb);
  }
  static getSizePrefixedRootAsRPCCall(bb, obj) {
    bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
    return (obj || new RPCCall())
        .__init(bb.readInt32(bb.position()) + bb.position(), bb);
  }
  name(optionalEncoding) {
    const offset = this.bb.__offset(this.bb_pos, 4);
    return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) :
                    null;
  }
  request(obj) {
    const offset = this.bb.__offset(this.bb_pos, 6);
    return offset ?
        (obj || new Object_())
            .__init(this.bb.__indirect(this.bb_pos + offset), this.bb) :
        null;
  }
  response(obj) {
    const offset = this.bb.__offset(this.bb_pos, 8);
    return offset ?
        (obj || new Object_())
            .__init(this.bb.__indirect(this.bb_pos + offset), this.bb) :
        null;
  }
  attributes(index, obj) {
    const offset = this.bb.__offset(this.bb_pos, 10);
    return offset ?
        (obj || new KeyValue())
            .__init(
                this.bb.__indirect(
                    this.bb.__vector(this.bb_pos + offset) + index * 4),
                this.bb) :
        null;
  }
  attributesLength() {
    const offset = this.bb.__offset(this.bb_pos, 10);
    return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
  }
  documentation(index, optionalEncoding) {
    const offset = this.bb.__offset(this.bb_pos, 12);
    return offset ? this.bb.__string(
                        this.bb.__vector(this.bb_pos + offset) + index * 4,
                        optionalEncoding) :
                    null;
  }
  documentationLength() {
    const offset = this.bb.__offset(this.bb_pos, 12);
    return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
  }
  static getFullyQualifiedName() {
    return 'reflection.RPCCall';
  }
  static startRPCCall(builder) {
    builder.startObject(5);
  }
  static addName(builder, nameOffset) {
    builder.addFieldOffset(0, nameOffset, 0);
  }
  static addRequest(builder, requestOffset) {
    builder.addFieldOffset(1, requestOffset, 0);
  }
  static addResponse(builder, responseOffset) {
    builder.addFieldOffset(2, responseOffset, 0);
  }
  static addAttributes(builder, attributesOffset) {
    builder.addFieldOffset(3, attributesOffset, 0);
  }
  static createAttributesVector(builder, data) {
    builder.startVector(4, data.length, 4);
    for (let i = data.length - 1; i >= 0; i--) {
      builder.addOffset(data[i]);
    }
    return builder.endVector();
  }
  static startAttributesVector(builder, numElems) {
    builder.startVector(4, numElems, 4);
  }
  static addDocumentation(builder, documentationOffset) {
    builder.addFieldOffset(4, documentationOffset, 0);
  }
  static createDocumentationVector(builder, data) {
    builder.startVector(4, data.length, 4);
    for (let i = data.length - 1; i >= 0; i--) {
      builder.addOffset(data[i]);
    }
    return builder.endVector();
  }
  static startDocumentationVector(builder, numElems) {
    builder.startVector(4, numElems, 4);
  }
  static endRPCCall(builder) {
    const offset = builder.endObject();
    builder.requiredField(offset, 4);  // name
    builder.requiredField(offset, 6);  // request
    builder.requiredField(offset, 8);  // response
    return offset;
  }
  unpack() {
    return new RPCCallT(
        this.name(), (this.request() !== null ? this.request().unpack() : null),
        (this.response() !== null ? this.response().unpack() : null),
        this.bb.createObjList(
            this.attributes.bind(this), this.attributesLength()),
        this.bb.createScalarList(
            this.documentation.bind(this), this.documentationLength()));
  }
  unpackTo(_o) {
    _o.name = this.name();
    _o.request = (this.request() !== null ? this.request().unpack() : null);
    _o.response = (this.response() !== null ? this.response().unpack() : null);
    _o.attributes = this.bb.createObjList(
        this.attributes.bind(this), this.attributesLength());
    _o.documentation = this.bb.createScalarList(
        this.documentation.bind(this), this.documentationLength());
  }
}
export class RPCCallT {
  constructor(
      name = null, request = null, response = null, attributes = [],
      documentation = []) {
    this.name = name;
    this.request = request;
    this.response = response;
    this.attributes = attributes;
    this.documentation = documentation;
  }
  pack(builder) {
    const name = (this.name !== null ? builder.createString(this.name) : 0);
    const request = (this.request !== null ? this.request.pack(builder) : 0);
    const response = (this.response !== null ? this.response.pack(builder) : 0);
    const attributes = RPCCall.createAttributesVector(
        builder, builder.createObjectOffsetList(this.attributes));
    const documentation = RPCCall.createDocumentationVector(
        builder, builder.createObjectOffsetList(this.documentation));
    RPCCall.startRPCCall(builder);
    RPCCall.addName(builder, name);
    RPCCall.addRequest(builder, request);
    RPCCall.addResponse(builder, response);
    RPCCall.addAttributes(builder, attributes);
    RPCCall.addDocumentation(builder, documentation);
    return RPCCall.endRPCCall(builder);
  }
}
