// <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_25(); }
  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);
  }
}
