// <auto-generated>
//  automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>

using global::System;
using global::System.Collections.Generic;
using global::Google.FlatBuffers;

public struct Movie : IFlatbufferObject
{
  private Table __p;
  public ByteBuffer ByteBuffer { get { return __p.bb; } }
  public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_24_3_7(); }
  public static Movie GetRootAsMovie(ByteBuffer _bb) { return GetRootAsMovie(_bb, new Movie()); }
  public static Movie GetRootAsMovie(ByteBuffer _bb, Movie obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
  public static bool MovieBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "MOVI"); }
  public static bool VerifyMovie(ByteBuffer _bb) {Google.FlatBuffers.Verifier verifier = new Google.FlatBuffers.Verifier(_bb); return verifier.VerifyBuffer("MOVI", false, MovieVerify.Verify); }
  public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
  public Movie __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }

  public Character MainCharacterType { get { int o = __p.__offset(4); return o != 0 ? (Character)__p.bb.Get(o + __p.bb_pos) : Character.NONE; } }
  public TTable? MainCharacter<TTable>() where TTable : struct, IFlatbufferObject { int o = __p.__offset(6); return o != 0 ? (TTable?)__p.__union<TTable>(o + __p.bb_pos) : null; }
  public string MainCharacterAsString() { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; }
  public Attacker MainCharacterAsMuLan() { return MainCharacter<Attacker>().Value; }
  public Rapunzel MainCharacterAsRapunzel() { return MainCharacter<Rapunzel>().Value; }
  public BookReader MainCharacterAsBelle() { return MainCharacter<BookReader>().Value; }
  public BookReader MainCharacterAsBookFan() { return MainCharacter<BookReader>().Value; }
  public string MainCharacterAsOther() { return MainCharacterAsString(); }
  public string MainCharacterAsUnused() { return MainCharacterAsString(); }
  public Character CharactersType(int j) { int o = __p.__offset(8); return o != 0 ? (Character)__p.bb.Get(__p.__vector(o) + j * 1) : (Character)0; }
  public int CharactersTypeLength { get { int o = __p.__offset(8); return o != 0 ? __p.__vector_len(o) : 0; } }
#if ENABLE_SPAN_T
  public Span<Character> GetCharactersTypeBytes() { return __p.__vector_as_span<Character>(8, 1); }
#else
  public ArraySegment<byte>? GetCharactersTypeBytes() { return __p.__vector_as_arraysegment(8); }
#endif
  public Character[] GetCharactersTypeArray() { int o = __p.__offset(8); if (o == 0) return null; int p = __p.__vector(o); int l = __p.__vector_len(o); Character[] a = new Character[l]; for (int i = 0; i < l; i++) { a[i] = (Character)__p.bb.Get(p + i * 1); } return a; }
  public TTable? Characters<TTable>(int j) where TTable : struct, IFlatbufferObject { int o = __p.__offset(10); return o != 0 ? (TTable?)__p.__union<TTable>(__p.__vector(o) + j * 4) : null; }
  public string CharactersAsString(int j) { int o = __p.__offset(10); return o != 0 ? __p.__string(__p.__vector(o) + j * 4) : null; }
  public int CharactersLength { get { int o = __p.__offset(10); return o != 0 ? __p.__vector_len(o) : 0; } }

  public static Offset<Movie> CreateMovie(FlatBufferBuilder builder,
      Character main_character_type = Character.NONE,
      int main_characterOffset = 0,
      VectorOffset characters_typeOffset = default(VectorOffset),
      VectorOffset charactersOffset = default(VectorOffset)) {
    builder.StartTable(4);
    Movie.AddCharacters(builder, charactersOffset);
    Movie.AddCharactersType(builder, characters_typeOffset);
    Movie.AddMainCharacter(builder, main_characterOffset);
    Movie.AddMainCharacterType(builder, main_character_type);
    return Movie.EndMovie(builder);
  }

  public static void StartMovie(FlatBufferBuilder builder) { builder.StartTable(4); }
  public static void AddMainCharacterType(FlatBufferBuilder builder, Character mainCharacterType) { builder.AddByte(0, (byte)mainCharacterType, 0); }
  public static void AddMainCharacter(FlatBufferBuilder builder, int mainCharacterOffset) { builder.AddOffset(1, mainCharacterOffset, 0); }
  public static void AddCharactersType(FlatBufferBuilder builder, VectorOffset charactersTypeOffset) { builder.AddOffset(2, charactersTypeOffset.Value, 0); }
  public static VectorOffset CreateCharactersTypeVector(FlatBufferBuilder builder, Character[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddByte((byte)data[i]); return builder.EndVector(); }
  public static VectorOffset CreateCharactersTypeVectorBlock(FlatBufferBuilder builder, Character[] data) { builder.StartVector(1, data.Length, 1); builder.Add(data); return builder.EndVector(); }
  public static VectorOffset CreateCharactersTypeVectorBlock(FlatBufferBuilder builder, ArraySegment<Character> data) { builder.StartVector(1, data.Count, 1); builder.Add(data); return builder.EndVector(); }
  public static VectorOffset CreateCharactersTypeVectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add<Character>(dataPtr, sizeInBytes); return builder.EndVector(); }
  public static void StartCharactersTypeVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); }
  public static void AddCharacters(FlatBufferBuilder builder, VectorOffset charactersOffset) { builder.AddOffset(3, charactersOffset.Value, 0); }
  public static VectorOffset 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 VectorOffset CreateCharactersVectorBlock(FlatBufferBuilder builder, int[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); }
  public static VectorOffset CreateCharactersVectorBlock(FlatBufferBuilder builder, ArraySegment<int> data) { builder.StartVector(4, data.Count, 4); builder.Add(data); return builder.EndVector(); }
  public static VectorOffset CreateCharactersVectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add<int>(dataPtr, sizeInBytes); return builder.EndVector(); }
  public static void StartCharactersVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); }
  public static Offset<Movie> EndMovie(FlatBufferBuilder builder) {
    int o = builder.EndTable();
    return new Offset<Movie>(o);
  }
  public static void FinishMovieBuffer(FlatBufferBuilder builder, Offset<Movie> offset) { builder.Finish(offset.Value, "MOVI"); }
  public static void FinishSizePrefixedMovieBuffer(FlatBufferBuilder builder, Offset<Movie> offset) { builder.FinishSizePrefixed(offset.Value, "MOVI"); }
  public MovieT UnPack() {
    var _o = new MovieT();
    this.UnPackTo(_o);
    return _o;
  }
  public void UnPackTo(MovieT _o) {
    _o.MainCharacter = new CharacterUnion();
    _o.MainCharacter.Type = this.MainCharacterType;
    switch (this.MainCharacterType) {
      default: break;
      case Character.MuLan:
        _o.MainCharacter.Value = this.MainCharacter<Attacker>().HasValue ? this.MainCharacter<Attacker>().Value.UnPack() : null;
        break;
      case Character.Rapunzel:
        _o.MainCharacter.Value = this.MainCharacter<Rapunzel>().HasValue ? this.MainCharacter<Rapunzel>().Value.UnPack() : null;
        break;
      case Character.Belle:
        _o.MainCharacter.Value = this.MainCharacter<BookReader>().HasValue ? this.MainCharacter<BookReader>().Value.UnPack() : null;
        break;
      case Character.BookFan:
        _o.MainCharacter.Value = this.MainCharacter<BookReader>().HasValue ? this.MainCharacter<BookReader>().Value.UnPack() : null;
        break;
      case Character.Other:
        _o.MainCharacter.Value = this.MainCharacterAsString();
        break;
      case Character.Unused:
        _o.MainCharacter.Value = this.MainCharacterAsString();
        break;
    }
    _o.Characters = new List<CharacterUnion>();
    for (var _j = 0; _j < this.CharactersLength; ++_j) {
      var _o_Characters = new CharacterUnion();
      _o_Characters.Type = this.CharactersType(_j);
      switch (this.CharactersType(_j)) {
        default: break;
        case Character.MuLan:
          _o_Characters.Value = this.Characters<Attacker>(_j).HasValue ? this.Characters<Attacker>(_j).Value.UnPack() : null;
          break;
        case Character.Rapunzel:
          _o_Characters.Value = this.Characters<Rapunzel>(_j).HasValue ? this.Characters<Rapunzel>(_j).Value.UnPack() : null;
          break;
        case Character.Belle:
          _o_Characters.Value = this.Characters<BookReader>(_j).HasValue ? this.Characters<BookReader>(_j).Value.UnPack() : null;
          break;
        case Character.BookFan:
          _o_Characters.Value = this.Characters<BookReader>(_j).HasValue ? this.Characters<BookReader>(_j).Value.UnPack() : null;
          break;
        case Character.Other:
          _o_Characters.Value = this.CharactersAsString(_j);
          break;
        case Character.Unused:
          _o_Characters.Value = this.CharactersAsString(_j);
          break;
      }
      _o.Characters.Add(_o_Characters);
    }
  }
  public static Offset<Movie> Pack(FlatBufferBuilder builder, MovieT _o) {
    if (_o == null) return default(Offset<Movie>);
    var _main_character_type = _o.MainCharacter == null ? Character.NONE : _o.MainCharacter.Type;
    var _main_character = _o.MainCharacter == null ? 0 : CharacterUnion.Pack(builder, _o.MainCharacter);
    var _characters_type = default(VectorOffset);
    if (_o.Characters != null) {
      var __characters_type = new Character[_o.Characters.Count];
      for (var _j = 0; _j < __characters_type.Length; ++_j) { __characters_type[_j] = _o.Characters[_j].Type; }
      _characters_type = CreateCharactersTypeVector(builder, __characters_type);
    }
    var _characters = default(VectorOffset);
    if (_o.Characters != null) {
      var __characters = new int[_o.Characters.Count];
      for (var _j = 0; _j < __characters.Length; ++_j) { __characters[_j] = CharacterUnion.Pack(builder,  _o.Characters[_j]); }
      _characters = CreateCharactersVector(builder, __characters);
    }
    return CreateMovie(
      builder,
      _main_character_type,
      _main_character,
      _characters_type,
      _characters);
  }
}

public class MovieT
{
  [Newtonsoft.Json.JsonProperty("main_character_type")]
  private Character MainCharacterType {
    get {
      return this.MainCharacter != null ? this.MainCharacter.Type : Character.NONE;
    }
    set {
      this.MainCharacter = new CharacterUnion();
      this.MainCharacter.Type = value;
    }
  }
  [Newtonsoft.Json.JsonProperty("main_character")]
  [Newtonsoft.Json.JsonConverter(typeof(CharacterUnion_JsonConverter))]
  public CharacterUnion MainCharacter { get; set; }
  [Newtonsoft.Json.JsonProperty("characters_type")]
  private Character[] CharactersType {
    get {
      if (this.Characters == null) return null;
      var _o = new Character[this.Characters.Count];
      for (var _j = 0; _j < _o.Length; ++_j) { _o[_j] = this.Characters[_j].Type; }
      return _o;
    }
    set {
      this.Characters = new List<CharacterUnion>();
      for (var _j = 0; _j < value.Length; ++_j) {
        var _o = new CharacterUnion();
        _o.Type = value[_j];
        this.Characters.Add(_o);
      }
    }
  }
  [Newtonsoft.Json.JsonProperty("characters")]
  [Newtonsoft.Json.JsonConverter(typeof(CharacterUnion_JsonConverter))]
  public List<CharacterUnion> Characters { get; set; }

  public MovieT() {
    this.MainCharacter = null;
    this.Characters = null;
  }

  public static MovieT DeserializeFromJson(string jsonText) {
    return Newtonsoft.Json.JsonConvert.DeserializeObject<MovieT>(jsonText);
  }
  public string SerializeToJson() {
    return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);
  }
  public static MovieT DeserializeFromBinary(byte[] fbBuffer) {
    return Movie.GetRootAsMovie(new ByteBuffer(fbBuffer)).UnPack();
  }
  public byte[] SerializeToBinary() {
    var fbb = new FlatBufferBuilder(0x10000);
    Movie.FinishMovieBuffer(fbb, Movie.Pack(fbb, this));
    return fbb.DataBuffer.ToSizedArray();
  }
}


static public class MovieVerify
{
  static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
  {
    return verifier.VerifyTableStart(tablePos)
      && verifier.VerifyField(tablePos, 4 /*MainCharacterType*/, 1 /*Character*/, 1, false)
      && verifier.VerifyUnion(tablePos, 4, 6 /*MainCharacter*/, CharacterVerify.Verify, false)
      && verifier.VerifyVectorOfData(tablePos, 8 /*CharactersType*/, 1 /*Character*/, false)
      && verifier.VerifyTableEnd(tablePos);
  }
}
