// 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 {RPCCall} from '../reflection/rpccall.js';

export class Service {
  constructor() {
    this.bb = null;
    this.bb_pos = 0;
  }
  __init(i, bb) {
    this.bb_pos = i;
    this.bb = bb;
    return this;
  }
  static getRootAsService(bb, obj) {
    return (obj || new Service())
        .__init(bb.readInt32(bb.position()) + bb.position(), bb);
  }
  static getSizePrefixedRootAsService(bb, obj) {
    bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
    return (obj || new Service())
        .__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;
  }
  calls(index, obj) {
    const offset = this.bb.__offset(this.bb_pos, 6);
    return offset ?
        (obj || new RPCCall())
            .__init(
                this.bb.__indirect(
                    this.bb.__vector(this.bb_pos + offset) + index * 4),
                this.bb) :
        null;
  }
  callsLength() {
    const offset = this.bb.__offset(this.bb_pos, 6);
    return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
  }
  attributes(index, obj) {
    const offset = this.bb.__offset(this.bb_pos, 8);
    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, 8);
    return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
  }
  documentation(index, optionalEncoding) {
    const offset = this.bb.__offset(this.bb_pos, 10);
    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, 10);
    return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
  }
  declarationFile(optionalEncoding) {
    const offset = this.bb.__offset(this.bb_pos, 12);
    return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) :
                    null;
  }
  static getFullyQualifiedName() {
    return 'reflection.Service';
  }
  static startService(builder) {
    builder.startObject(5);
  }
  static addName(builder, nameOffset) {
    builder.addFieldOffset(0, nameOffset, 0);
  }
  static addCalls(builder, callsOffset) {
    builder.addFieldOffset(1, callsOffset, 0);
  }
  static createCallsVector(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 startCallsVector(builder, numElems) {
    builder.startVector(4, numElems, 4);
  }
  static addAttributes(builder, attributesOffset) {
    builder.addFieldOffset(2, 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(3, 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 addDeclarationFile(builder, declarationFileOffset) {
    builder.addFieldOffset(4, declarationFileOffset, 0);
  }
  static endService(builder) {
    const offset = builder.endObject();
    builder.requiredField(offset, 4);  // name
    return offset;
  }
  static createService(
      builder, nameOffset, callsOffset, attributesOffset, documentationOffset,
      declarationFileOffset) {
    Service.startService(builder);
    Service.addName(builder, nameOffset);
    Service.addCalls(builder, callsOffset);
    Service.addAttributes(builder, attributesOffset);
    Service.addDocumentation(builder, documentationOffset);
    Service.addDeclarationFile(builder, declarationFileOffset);
    return Service.endService(builder);
  }
  unpack() {
    return new ServiceT(
        this.name(),
        this.bb.createObjList(this.calls.bind(this), this.callsLength()),
        this.bb.createObjList(
            this.attributes.bind(this), this.attributesLength()),
        this.bb.createScalarList(
            this.documentation.bind(this), this.documentationLength()),
        this.declarationFile());
  }
  unpackTo(_o) {
    _o.name = this.name();
    _o.calls = this.bb.createObjList(this.calls.bind(this), this.callsLength());
    _o.attributes = this.bb.createObjList(
        this.attributes.bind(this), this.attributesLength());
    _o.documentation = this.bb.createScalarList(
        this.documentation.bind(this), this.documentationLength());
    _o.declarationFile = this.declarationFile();
  }
}
export class ServiceT {
  constructor(
      name = null, calls = [], attributes = [], documentation = [],
      declarationFile = null) {
    this.name = name;
    this.calls = calls;
    this.attributes = attributes;
    this.documentation = documentation;
    this.declarationFile = declarationFile;
  }
  pack(builder) {
    const name = (this.name !== null ? builder.createString(this.name) : 0);
    const calls = Service.createCallsVector(
        builder, builder.createObjectOffsetList(this.calls));
    const attributes = Service.createAttributesVector(
        builder, builder.createObjectOffsetList(this.attributes));
    const documentation = Service.createDocumentationVector(
        builder, builder.createObjectOffsetList(this.documentation));
    const declarationFile =
        (this.declarationFile !== null ?
             builder.createString(this.declarationFile) :
             0);
    return Service.createService(
        builder, name, calls, attributes, documentation, declarationFile);
  }
}
