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

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

public struct Movie : IFlatbufferObject
{
  private Table __p;
  public ByteBuffer ByteBuffer { get { return __p.bb; } }
  public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_11_1(); }
  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 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 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 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 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);
    fbb.Finish(Movie.Pack(fbb, this).Value);
    return fbb.DataBuffer.ToSizedArray();
  }
}

