// automatically generated by the FlatBuffers compiler, do not modify
import * as flatbuffers from 'flatbuffers';
import { Character, unionToCharacter, unionListToCharacter } from './character';
export class Movie {
    constructor() {
        this.bb = null;
        this.bb_pos = 0;
    }
    __init(i, bb) {
        this.bb_pos = i;
        this.bb = bb;
        return this;
    }
    static getRootAsMovie(bb, obj) {
        return (obj || new Movie()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
    }
    static getSizePrefixedRootAsMovie(bb, obj) {
        bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
        return (obj || new Movie()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
    }
    static bufferHasIdentifier(bb) {
        return bb.__has_identifier('MOVI');
    }
    mainCharacterType() {
        const offset = this.bb.__offset(this.bb_pos, 4);
        return offset ? this.bb.readUint8(this.bb_pos + offset) : Character.NONE;
    }
    mainCharacter(obj) {
        const offset = this.bb.__offset(this.bb_pos, 6);
        return offset ? this.bb.__union_with_string(obj, this.bb_pos + offset) : null;
    }
    charactersType(index) {
        const offset = this.bb.__offset(this.bb_pos, 8);
        return offset ? this.bb.readUint8(this.bb.__vector(this.bb_pos + offset) + index) : 0;
    }
    charactersTypeLength() {
        const offset = this.bb.__offset(this.bb_pos, 8);
        return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
    }
    charactersTypeArray() {
        const offset = this.bb.__offset(this.bb_pos, 8);
        return offset ? new Uint8Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) : null;
    }
    characters(index, obj) {
        const offset = this.bb.__offset(this.bb_pos, 10);
        return offset ? this.bb.__union_with_string(obj, this.bb.__vector(this.bb_pos + offset) + index * 4) : null;
    }
    charactersLength() {
        const offset = this.bb.__offset(this.bb_pos, 10);
        return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
    }
    static getFullyQualifiedName() {
        return 'Movie';
    }
    static startMovie(builder) {
        builder.startObject(4);
    }
    static addMainCharacterType(builder, mainCharacterType) {
        builder.addFieldInt8(0, mainCharacterType, Character.NONE);
    }
    static addMainCharacter(builder, mainCharacterOffset) {
        builder.addFieldOffset(1, mainCharacterOffset, 0);
    }
    static addCharactersType(builder, charactersTypeOffset) {
        builder.addFieldOffset(2, charactersTypeOffset, 0);
    }
    static createCharactersTypeVector(builder, data) {
        builder.startVector(1, data.length, 1);
        for (let i = data.length - 1; i >= 0; i--) {
            builder.addInt8(data[i]);
        }
        return builder.endVector();
    }
    static startCharactersTypeVector(builder, numElems) {
        builder.startVector(1, numElems, 1);
    }
    static addCharacters(builder, charactersOffset) {
        builder.addFieldOffset(3, charactersOffset, 0);
    }
    static createCharactersVector(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 startCharactersVector(builder, numElems) {
        builder.startVector(4, numElems, 4);
    }
    static endMovie(builder) {
        const offset = builder.endObject();
        return offset;
    }
    static finishMovieBuffer(builder, offset) {
        builder.finish(offset, 'MOVI');
    }
    static finishSizePrefixedMovieBuffer(builder, offset) {
        builder.finish(offset, 'MOVI', true);
    }
    static createMovie(builder, mainCharacterType, mainCharacterOffset, charactersTypeOffset, charactersOffset) {
        Movie.startMovie(builder);
        Movie.addMainCharacterType(builder, mainCharacterType);
        Movie.addMainCharacter(builder, mainCharacterOffset);
        Movie.addCharactersType(builder, charactersTypeOffset);
        Movie.addCharacters(builder, charactersOffset);
        return Movie.endMovie(builder);
    }
    unpack() {
        return new MovieT(this.mainCharacterType(), (() => {
            let temp = unionToCharacter(this.mainCharacterType(), this.mainCharacter.bind(this));
            if (temp === null) {
                return null;
            }
            if (typeof temp === 'string') {
                return temp;
            }
            return temp.unpack();
        })(), this.bb.createScalarList(this.charactersType.bind(this), this.charactersTypeLength()), (() => {
            let ret = [];
            for (let targetEnumIndex = 0; targetEnumIndex < this.charactersTypeLength(); ++targetEnumIndex) {
                let targetEnum = this.charactersType(targetEnumIndex);
                if (targetEnum === null || Character[targetEnum] === 'NONE') {
                    continue;
                }
                let temp = unionListToCharacter(targetEnum, this.characters.bind(this), targetEnumIndex);
                if (temp === null) {
                    continue;
                }
                if (typeof temp === 'string') {
                    ret.push(temp);
                    continue;
                }
                ret.push(temp.unpack());
            }
            return ret;
        })());
    }
    unpackTo(_o) {
        _o.mainCharacterType = this.mainCharacterType();
        _o.mainCharacter = (() => {
            let temp = unionToCharacter(this.mainCharacterType(), this.mainCharacter.bind(this));
            if (temp === null) {
                return null;
            }
            if (typeof temp === 'string') {
                return temp;
            }
            return temp.unpack();
        })();
        _o.charactersType = this.bb.createScalarList(this.charactersType.bind(this), this.charactersTypeLength());
        _o.characters = (() => {
            let ret = [];
            for (let targetEnumIndex = 0; targetEnumIndex < this.charactersTypeLength(); ++targetEnumIndex) {
                let targetEnum = this.charactersType(targetEnumIndex);
                if (targetEnum === null || Character[targetEnum] === 'NONE') {
                    continue;
                }
                let temp = unionListToCharacter(targetEnum, this.characters.bind(this), targetEnumIndex);
                if (temp === null) {
                    continue;
                }
                if (typeof temp === 'string') {
                    ret.push(temp);
                    continue;
                }
                ret.push(temp.unpack());
            }
            return ret;
        })();
    }
}
export class MovieT {
    constructor(mainCharacterType = Character.NONE, mainCharacter = null, charactersType = [], characters = []) {
        this.mainCharacterType = mainCharacterType;
        this.mainCharacter = mainCharacter;
        this.charactersType = charactersType;
        this.characters = characters;
    }
    pack(builder) {
        const mainCharacter = builder.createObjectOffset(this.mainCharacter);
        const charactersType = Movie.createCharactersTypeVector(builder, this.charactersType);
        const characters = Movie.createCharactersVector(builder, builder.createObjectOffsetList(this.characters));
        return Movie.createMovie(builder, this.mainCharacterType, mainCharacter, charactersType, characters);
    }
}
