// automatically generated by the FlatBuffers compiler, do not modify

import java.nio.*;
import java.lang.*;
import java.util.*;
import com.google.flatbuffers.*;

@SuppressWarnings("unused")
public final class Movie extends Table {
  public static void ValidateVersion() { Constants.FLATBUFFERS_22_10_25(); }
  public static Movie getRootAsMovie(ByteBuffer _bb) { return getRootAsMovie(_bb, new Movie()); }
  public static Movie getRootAsMovie(ByteBuffer _bb, Movie obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
  public static boolean MovieBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "MOVI"); }
  public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }
  public Movie __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }

  public byte mainCharacterType() { int o = __offset(4); return o != 0 ? bb.get(o + bb_pos) : 0; }
  public Table mainCharacter(Table obj) { int o = __offset(6); return o != 0 ? __union(obj, o + bb_pos) : null; }
  public byte charactersType(int j) { int o = __offset(8); return o != 0 ? bb.get(__vector(o) + j * 1) : 0; }
  public int charactersTypeLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; }
  public ByteVector charactersTypeVector() { return charactersTypeVector(new ByteVector()); }
  public ByteVector charactersTypeVector(ByteVector obj) { int o = __offset(8); return o != 0 ? obj.__assign(__vector(o), bb) : null; }
  public ByteBuffer charactersTypeAsByteBuffer() { return __vector_as_bytebuffer(8, 1); }
  public ByteBuffer charactersTypeInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 1); }
  public Table characters(Table obj, int j) { int o = __offset(10); return o != 0 ? __union(obj, __vector(o) + j * 4) : null; }
  public int charactersLength() { int o = __offset(10); return o != 0 ? __vector_len(o) : 0; }
  public UnionVector charactersVector() { return charactersVector(new UnionVector()); }
  public UnionVector charactersVector(UnionVector obj) { int o = __offset(10); return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; }

  public static int createMovie(FlatBufferBuilder builder,
      byte mainCharacterType,
      int mainCharacterOffset,
      int charactersTypeOffset,
      int charactersOffset) {
    builder.startTable(4);
    Movie.addCharacters(builder, charactersOffset);
    Movie.addCharactersType(builder, charactersTypeOffset);
    Movie.addMainCharacter(builder, mainCharacterOffset);
    Movie.addMainCharacterType(builder, mainCharacterType);
    return Movie.endMovie(builder);
  }

  public static void startMovie(FlatBufferBuilder builder) { builder.startTable(4); }
  public static void addMainCharacterType(FlatBufferBuilder builder, byte mainCharacterType) { builder.addByte(0, mainCharacterType, 0); }
  public static void addMainCharacter(FlatBufferBuilder builder, int mainCharacterOffset) { builder.addOffset(1, mainCharacterOffset, 0); }
  public static void addCharactersType(FlatBufferBuilder builder, int charactersTypeOffset) { builder.addOffset(2, charactersTypeOffset, 0); }
  public static int createCharactersTypeVector(FlatBufferBuilder builder, byte[] data) { builder.startVector(1, data.length, 1); for (int i = data.length - 1; i >= 0; i--) builder.addByte(data[i]); return builder.endVector(); }
  public static void startCharactersTypeVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems, 1); }
  public static void addCharacters(FlatBufferBuilder builder, int charactersOffset) { builder.addOffset(3, charactersOffset, 0); }
  public static int createCharactersVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); }
  public static void startCharactersVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); }
  public static int endMovie(FlatBufferBuilder builder) {
    int o = builder.endTable();
    return o;
  }
  public static void finishMovieBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset, "MOVI"); }
  public static void finishSizePrefixedMovieBuffer(FlatBufferBuilder builder, int offset) { builder.finishSizePrefixed(offset, "MOVI"); }

  public static final class Vector extends BaseVector {
    public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; }

    public Movie get(int j) { return get(new Movie(), j); }
    public Movie get(Movie obj, int j) {  return obj.__assign(__indirect(__element(j), bb), bb); }
  }
  public MovieT unpack() {
    MovieT _o = new MovieT();
    unpackTo(_o);
    return _o;
  }
  public void unpackTo(MovieT _o) {
    CharacterUnion _oMainCharacter = new CharacterUnion();
    byte _oMainCharacterType = mainCharacterType();
    _oMainCharacter.setType(_oMainCharacterType);
    Table _oMainCharacterValue;
    switch (_oMainCharacterType) {
      case Character.MuLan:
        _oMainCharacterValue = mainCharacter(new Attacker());
        _oMainCharacter.setValue(_oMainCharacterValue != null ? ((Attacker) _oMainCharacterValue).unpack() : null);
        break;
      default: break;
    }
    _o.setMainCharacter(_oMainCharacter);
    CharacterUnion[] _oCharacters = new CharacterUnion[charactersLength()];
    for (int _j = 0; _j < charactersLength(); ++_j) {
      CharacterUnion _oCharactersElement = new CharacterUnion();
      byte _oCharactersElementType = charactersType(_j);
      _oCharactersElement.setType(_oCharactersElementType);
      Table _oCharactersElementValue;
      switch (_oCharactersElementType) {
        case Character.MuLan:
          _oCharactersElementValue = characters(new Attacker(), _j);
          _oCharactersElement.setValue(_oCharactersElementValue != null ? ((Attacker) _oCharactersElementValue).unpack() : null);
          break;
        default: break;
      }
      _oCharacters[_j] = _oCharactersElement;
    }
    _o.setCharacters(_oCharacters);
  }
  public static int pack(FlatBufferBuilder builder, MovieT _o) {
    if (_o == null) return 0;
    byte _mainCharacterType = _o.getMainCharacter() == null ? Character.NONE : _o.getMainCharacter().getType();
    int _mainCharacter = _o.getMainCharacter() == null ? 0 : CharacterUnion.pack(builder, _o.getMainCharacter());
    int _charactersType = 0;
    if (_o.getCharacters() != null) {
      byte[] __charactersType = new byte[_o.getCharacters().length];
      int _j = 0;
      for (CharacterUnion _e : _o.getCharacters()) { __charactersType[_j] = _o.getCharacters()[_j].getType(); _j++;}
      _charactersType = createCharactersTypeVector(builder, __charactersType);
    }
    int _characters = 0;
    if (_o.getCharacters() != null) {
      int[] __characters = new int[_o.getCharacters().length];
      int _j = 0;
      for (CharacterUnion _e : _o.getCharacters()) { __characters[_j] = CharacterUnion.pack(builder,  _o.getCharacters()[_j]); _j++;}
      _characters = createCharactersVector(builder, __characters);
    }
    return createMovie(
      builder,
      _mainCharacterType,
      _mainCharacter,
      _charactersType,
      _characters);
  }
}

