// Code generated by ObjectBox; DO NOT EDIT.
// Learn more about defining entities and generating this file - visit https://golang.objectbox.io/entity-annotations

package object

import (
	"errors"
	"github.com/google/flatbuffers/go"
	"github.com/objectbox/objectbox-go/objectbox"
	"github.com/objectbox/objectbox-go/objectbox/fbutils"
)

type nillable_EntityInfo struct {
	objectbox.Entity
	Uid uint64
}

var NillableBinding = nillable_EntityInfo{
	Entity: objectbox.Entity{
		Id: 2,
	},
	Uid: 8274930044578894929,
}

// Nillable_ contains type-based Property helpers to facilitate some common operations such as Queries.
var Nillable_ = struct {
	Id           *objectbox.PropertyUint64
	Int          *objectbox.PropertyInt
	Int8         *objectbox.PropertyInt8
	Int16        *objectbox.PropertyInt16
	Int32        *objectbox.PropertyInt32
	Int64        *objectbox.PropertyInt64
	Uint         *objectbox.PropertyUint
	Uint8        *objectbox.PropertyUint8
	Uint16       *objectbox.PropertyUint16
	Uint32       *objectbox.PropertyUint32
	Uint64       *objectbox.PropertyUint64
	Bool         *objectbox.PropertyBool
	String       *objectbox.PropertyString
	StringVector *objectbox.PropertyStringVector
	Byte         *objectbox.PropertyByte
	ByteVector   *objectbox.PropertyByteVector
	Rune         *objectbox.PropertyRune
	Float32      *objectbox.PropertyFloat32
	Float64      *objectbox.PropertyFloat64
	Date         *objectbox.PropertyInt64
	Time         *objectbox.PropertyInt64
}{
	Id: &objectbox.PropertyUint64{
		BaseProperty: &objectbox.BaseProperty{
			Id:     1,
			Entity: &NillableBinding.Entity,
		},
	},
	Int: &objectbox.PropertyInt{
		BaseProperty: &objectbox.BaseProperty{
			Id:     2,
			Entity: &NillableBinding.Entity,
		},
	},
	Int8: &objectbox.PropertyInt8{
		BaseProperty: &objectbox.BaseProperty{
			Id:     3,
			Entity: &NillableBinding.Entity,
		},
	},
	Int16: &objectbox.PropertyInt16{
		BaseProperty: &objectbox.BaseProperty{
			Id:     4,
			Entity: &NillableBinding.Entity,
		},
	},
	Int32: &objectbox.PropertyInt32{
		BaseProperty: &objectbox.BaseProperty{
			Id:     5,
			Entity: &NillableBinding.Entity,
		},
	},
	Int64: &objectbox.PropertyInt64{
		BaseProperty: &objectbox.BaseProperty{
			Id:     6,
			Entity: &NillableBinding.Entity,
		},
	},
	Uint: &objectbox.PropertyUint{
		BaseProperty: &objectbox.BaseProperty{
			Id:     7,
			Entity: &NillableBinding.Entity,
		},
	},
	Uint8: &objectbox.PropertyUint8{
		BaseProperty: &objectbox.BaseProperty{
			Id:     8,
			Entity: &NillableBinding.Entity,
		},
	},
	Uint16: &objectbox.PropertyUint16{
		BaseProperty: &objectbox.BaseProperty{
			Id:     9,
			Entity: &NillableBinding.Entity,
		},
	},
	Uint32: &objectbox.PropertyUint32{
		BaseProperty: &objectbox.BaseProperty{
			Id:     10,
			Entity: &NillableBinding.Entity,
		},
	},
	Uint64: &objectbox.PropertyUint64{
		BaseProperty: &objectbox.BaseProperty{
			Id:     11,
			Entity: &NillableBinding.Entity,
		},
	},
	Bool: &objectbox.PropertyBool{
		BaseProperty: &objectbox.BaseProperty{
			Id:     12,
			Entity: &NillableBinding.Entity,
		},
	},
	String: &objectbox.PropertyString{
		BaseProperty: &objectbox.BaseProperty{
			Id:     13,
			Entity: &NillableBinding.Entity,
		},
	},
	StringVector: &objectbox.PropertyStringVector{
		BaseProperty: &objectbox.BaseProperty{
			Id:     14,
			Entity: &NillableBinding.Entity,
		},
	},
	Byte: &objectbox.PropertyByte{
		BaseProperty: &objectbox.BaseProperty{
			Id:     15,
			Entity: &NillableBinding.Entity,
		},
	},
	ByteVector: &objectbox.PropertyByteVector{
		BaseProperty: &objectbox.BaseProperty{
			Id:     16,
			Entity: &NillableBinding.Entity,
		},
	},
	Rune: &objectbox.PropertyRune{
		BaseProperty: &objectbox.BaseProperty{
			Id:     17,
			Entity: &NillableBinding.Entity,
		},
	},
	Float32: &objectbox.PropertyFloat32{
		BaseProperty: &objectbox.BaseProperty{
			Id:     18,
			Entity: &NillableBinding.Entity,
		},
	},
	Float64: &objectbox.PropertyFloat64{
		BaseProperty: &objectbox.BaseProperty{
			Id:     19,
			Entity: &NillableBinding.Entity,
		},
	},
	Date: &objectbox.PropertyInt64{
		BaseProperty: &objectbox.BaseProperty{
			Id:     20,
			Entity: &NillableBinding.Entity,
		},
	},
	Time: &objectbox.PropertyInt64{
		BaseProperty: &objectbox.BaseProperty{
			Id:     21,
			Entity: &NillableBinding.Entity,
		},
	},
}

// GeneratorVersion is called by ObjectBox to verify the compatibility of the generator used to generate this code
func (nillable_EntityInfo) GeneratorVersion() int {
	return 6
}

// AddToModel is called by ObjectBox during model build
func (nillable_EntityInfo) AddToModel(model *objectbox.Model) {
	model.Entity("Nillable", 2, 8274930044578894929)
	model.Property("Id", 6, 1, 1543572285742637646)
	model.PropertyFlags(1)
	model.Property("Int", 6, 2, 2661732831099943416)
	model.Property("Int8", 2, 3, 8325060299420976708)
	model.Property("Int16", 3, 4, 7837839688282259259)
	model.Property("Int32", 5, 5, 2518412263346885298)
	model.Property("Int64", 6, 6, 5617773211005988520)
	model.Property("Uint", 6, 7, 2339563716805116249)
	model.PropertyFlags(8192)
	model.Property("Uint8", 2, 8, 7144924247938981575)
	model.PropertyFlags(8192)
	model.Property("Uint16", 3, 9, 161231572858529631)
	model.PropertyFlags(8192)
	model.Property("Uint32", 5, 10, 7259475919510918339)
	model.PropertyFlags(8192)
	model.Property("Uint64", 6, 11, 7373105480197164748)
	model.PropertyFlags(8192)
	model.Property("Bool", 1, 12, 3287288577352441706)
	model.Property("String", 9, 13, 3930927879439176946)
	model.Property("StringVector", 30, 14, 4706154865122290029)
	model.Property("Byte", 2, 15, 2217592893536642650)
	model.PropertyFlags(8192)
	model.Property("ByteVector", 23, 16, 1929546706668609706)
	model.Property("Rune", 5, 17, 6392442863481646880)
	model.Property("Float32", 7, 18, 3706853784096366226)
	model.Property("Float64", 8, 19, 2627038740284806767)
	model.Property("Date", 10, 20, 6303220950515014660)
	model.Property("Time", 10, 21, 4035568504096476779)
	model.EntityLastPropertyId(21, 4035568504096476779)
}

// GetId is called by ObjectBox during Put operations to check for existing ID on an object
func (nillable_EntityInfo) GetId(object interface{}) (uint64, error) {
	return object.(*Nillable).Id, nil
}

// SetId is called by ObjectBox during Put to update an ID on an object that has just been inserted
func (nillable_EntityInfo) SetId(object interface{}, id uint64) error {
	object.(*Nillable).Id = id
	return nil
}

// PutRelated is called by ObjectBox to put related entities before the object itself is flattened and put
func (nillable_EntityInfo) PutRelated(ob *objectbox.ObjectBox, object interface{}, id uint64) error {
	return nil
}

// Flatten is called by ObjectBox to transform an object to a FlatBuffer
func (nillable_EntityInfo) Flatten(object interface{}, fbb *flatbuffers.Builder, id uint64) error {
	obj := object.(*Nillable)
	var propTime *int64
	if obj.Time != nil {
		var err error
		propTime, err = timeInt64PtrToDatabaseValue(obj.Time)
		if err != nil {
			return errors.New("converter timeInt64PtrToDatabaseValue() failed on Nillable.Time: " + err.Error())
		}
	}

	var offsetString flatbuffers.UOffsetT
	if obj.String != nil {
		offsetString = fbutils.CreateStringOffset(fbb, *obj.String)
	}

	var offsetStringVector flatbuffers.UOffsetT
	if obj.StringVector != nil {
		offsetStringVector = fbutils.CreateStringVectorOffset(fbb, *obj.StringVector)
	}

	var offsetByteVector flatbuffers.UOffsetT
	if obj.ByteVector != nil {
		offsetByteVector = fbutils.CreateByteVectorOffset(fbb, *obj.ByteVector)
	}

	// build the FlatBuffers object
	fbb.StartObject(21)
	fbutils.SetUint64Slot(fbb, 0, id)
	if obj.Int != nil {
		fbutils.SetInt64Slot(fbb, 1, int64(*obj.Int))
	}
	if obj.Int8 != nil {
		fbutils.SetInt8Slot(fbb, 2, *obj.Int8)
	}
	if obj.Int16 != nil {
		fbutils.SetInt16Slot(fbb, 3, *obj.Int16)
	}
	if obj.Int32 != nil {
		fbutils.SetInt32Slot(fbb, 4, *obj.Int32)
	}
	if obj.Int64 != nil {
		fbutils.SetInt64Slot(fbb, 5, *obj.Int64)
	}
	if obj.Uint != nil {
		fbutils.SetUint64Slot(fbb, 6, uint64(*obj.Uint))
	}
	if obj.Uint8 != nil {
		fbutils.SetUint8Slot(fbb, 7, *obj.Uint8)
	}
	if obj.Uint16 != nil {
		fbutils.SetUint16Slot(fbb, 8, *obj.Uint16)
	}
	if obj.Uint32 != nil {
		fbutils.SetUint32Slot(fbb, 9, *obj.Uint32)
	}
	if obj.Uint64 != nil {
		fbutils.SetUint64Slot(fbb, 10, *obj.Uint64)
	}
	if obj.Bool != nil {
		fbutils.SetBoolSlot(fbb, 11, *obj.Bool)
	}
	if obj.String != nil {
		fbutils.SetUOffsetTSlot(fbb, 12, offsetString)
	}
	if obj.StringVector != nil {
		fbutils.SetUOffsetTSlot(fbb, 13, offsetStringVector)
	}
	if obj.Byte != nil {
		fbutils.SetUint8Slot(fbb, 14, *obj.Byte)
	}
	if obj.ByteVector != nil {
		fbutils.SetUOffsetTSlot(fbb, 15, offsetByteVector)
	}
	if obj.Rune != nil {
		fbutils.SetInt32Slot(fbb, 16, *obj.Rune)
	}
	if obj.Float32 != nil {
		fbutils.SetFloat32Slot(fbb, 17, *obj.Float32)
	}
	if obj.Float64 != nil {
		fbutils.SetFloat64Slot(fbb, 18, *obj.Float64)
	}
	if obj.Date != nil {
		fbutils.SetInt64Slot(fbb, 19, *obj.Date)
	}
	if obj.Time != nil {
		fbutils.SetInt64Slot(fbb, 20, *propTime)
	}
	return nil
}

// Load is called by ObjectBox to load an object from a FlatBuffer
func (nillable_EntityInfo) Load(ob *objectbox.ObjectBox, bytes []byte) (interface{}, error) {
	if len(bytes) == 0 { // sanity check, should "never" happen
		return nil, errors.New("can't deserialize an object of type 'Nillable' - no data received")
	}

	var table = &flatbuffers.Table{
		Bytes: bytes,
		Pos:   flatbuffers.GetUOffsetT(bytes),
	}

	var propId = table.GetUint64Slot(4, 0)

	propTime, err := timeInt64PtrToEntityProperty(fbutils.GetInt64PtrSlot(table, 44))
	if err != nil {
		return nil, errors.New("converter timeInt64PtrToEntityProperty() failed on Nillable.Time: " + err.Error())
	}

	return &Nillable{
		Id:           propId,
		Int:          fbutils.GetIntPtrSlot(table, 6),
		Int8:         fbutils.GetInt8PtrSlot(table, 8),
		Int16:        fbutils.GetInt16PtrSlot(table, 10),
		Int32:        fbutils.GetInt32PtrSlot(table, 12),
		Int64:        fbutils.GetInt64PtrSlot(table, 14),
		Uint:         fbutils.GetUintPtrSlot(table, 16),
		Uint8:        fbutils.GetUint8PtrSlot(table, 18),
		Uint16:       fbutils.GetUint16PtrSlot(table, 20),
		Uint32:       fbutils.GetUint32PtrSlot(table, 22),
		Uint64:       fbutils.GetUint64PtrSlot(table, 24),
		Bool:         fbutils.GetBoolPtrSlot(table, 26),
		String:       fbutils.GetStringPtrSlot(table, 28),
		StringVector: fbutils.GetStringVectorPtrSlot(table, 30),
		Byte:         fbutils.GetBytePtrSlot(table, 32),
		ByteVector:   fbutils.GetByteVectorPtrSlot(table, 34),
		Rune:         fbutils.GetRunePtrSlot(table, 36),
		Float32:      fbutils.GetFloat32PtrSlot(table, 38),
		Float64:      fbutils.GetFloat64PtrSlot(table, 40),
		Date:         fbutils.GetInt64PtrSlot(table, 42),
		Time:         propTime,
	}, nil
}

// MakeSlice is called by ObjectBox to construct a new slice to hold the read objects
func (nillable_EntityInfo) MakeSlice(capacity int) interface{} {
	return make([]*Nillable, 0, capacity)
}

// AppendToSlice is called by ObjectBox to fill the slice of the read objects
func (nillable_EntityInfo) AppendToSlice(slice interface{}, object interface{}) interface{} {
	if object == nil {
		return append(slice.([]*Nillable), nil)
	}
	return append(slice.([]*Nillable), object.(*Nillable))
}

// Box provides CRUD access to Nillable objects
type NillableBox struct {
	*objectbox.Box
}

// BoxForNillable opens a box of Nillable objects
func BoxForNillable(ob *objectbox.ObjectBox) *NillableBox {
	return &NillableBox{
		Box: ob.InternalBox(2),
	}
}

// Put synchronously inserts/updates a single object.
// In case the Id is not specified, it would be assigned automatically (auto-increment).
// When inserting, the Nillable.Id property on the passed object will be assigned the new ID as well.
func (box *NillableBox) Put(object *Nillable) (uint64, error) {
	return box.Box.Put(object)
}

// Insert synchronously inserts a single object. As opposed to Put, Insert will fail if given an ID that already exists.
// In case the Id is not specified, it would be assigned automatically (auto-increment).
// When inserting, the Nillable.Id property on the passed object will be assigned the new ID as well.
func (box *NillableBox) Insert(object *Nillable) (uint64, error) {
	return box.Box.Insert(object)
}

// Update synchronously updates a single object.
// As opposed to Put, Update will fail if an object with the same ID is not found in the database.
func (box *NillableBox) Update(object *Nillable) error {
	return box.Box.Update(object)
}

// PutAsync asynchronously inserts/updates a single object.
// Deprecated: use box.Async().Put() instead
func (box *NillableBox) PutAsync(object *Nillable) (uint64, error) {
	return box.Box.PutAsync(object)
}

// PutMany inserts multiple objects in single transaction.
// In case Ids are not set on the objects, they would be assigned automatically (auto-increment).
//
// Returns: IDs of the put objects (in the same order).
// When inserting, the Nillable.Id property on the objects in the slice will be assigned the new IDs as well.
//
// Note: In case an error occurs during the transaction, some of the objects may already have the Nillable.Id assigned
// even though the transaction has been rolled back and the objects are not stored under those IDs.
//
// Note: The slice may be empty or even nil; in both cases, an empty IDs slice and no error is returned.
func (box *NillableBox) PutMany(objects []*Nillable) ([]uint64, error) {
	return box.Box.PutMany(objects)
}

// Get reads a single object.
//
// Returns nil (and no error) in case the object with the given ID doesn't exist.
func (box *NillableBox) Get(id uint64) (*Nillable, error) {
	object, err := box.Box.Get(id)
	if err != nil {
		return nil, err
	} else if object == nil {
		return nil, nil
	}
	return object.(*Nillable), nil
}

// GetMany reads multiple objects at once.
// If any of the objects doesn't exist, its position in the return slice is nil
func (box *NillableBox) GetMany(ids ...uint64) ([]*Nillable, error) {
	objects, err := box.Box.GetMany(ids...)
	if err != nil {
		return nil, err
	}
	return objects.([]*Nillable), nil
}

// GetManyExisting reads multiple objects at once, skipping those that do not exist.
func (box *NillableBox) GetManyExisting(ids ...uint64) ([]*Nillable, error) {
	objects, err := box.Box.GetManyExisting(ids...)
	if err != nil {
		return nil, err
	}
	return objects.([]*Nillable), nil
}

// GetAll reads all stored objects
func (box *NillableBox) GetAll() ([]*Nillable, error) {
	objects, err := box.Box.GetAll()
	if err != nil {
		return nil, err
	}
	return objects.([]*Nillable), nil
}

// Remove deletes a single object
func (box *NillableBox) Remove(object *Nillable) error {
	return box.Box.Remove(object)
}

// RemoveMany deletes multiple objects at once.
// Returns the number of deleted object or error on failure.
// Note that this method will not fail if an object is not found (e.g. already removed).
// In case you need to strictly check whether all of the objects exist before removing them,
// you can execute multiple box.Contains() and box.Remove() inside a single write transaction.
func (box *NillableBox) RemoveMany(objects ...*Nillable) (uint64, error) {
	var ids = make([]uint64, len(objects))
	for k, object := range objects {
		ids[k] = object.Id
	}
	return box.Box.RemoveIds(ids...)
}

// Creates a query with the given conditions. Use the fields of the Nillable_ struct to create conditions.
// Keep the *NillableQuery if you intend to execute the query multiple times.
// Note: this function panics if you try to create illegal queries; e.g. use properties of an alien type.
// This is typically a programming error. Use QueryOrError instead if you want the explicit error check.
func (box *NillableBox) Query(conditions ...objectbox.Condition) *NillableQuery {
	return &NillableQuery{
		box.Box.Query(conditions...),
	}
}

// Creates a query with the given conditions. Use the fields of the Nillable_ struct to create conditions.
// Keep the *NillableQuery if you intend to execute the query multiple times.
func (box *NillableBox) QueryOrError(conditions ...objectbox.Condition) (*NillableQuery, error) {
	if query, err := box.Box.QueryOrError(conditions...); err != nil {
		return nil, err
	} else {
		return &NillableQuery{query}, nil
	}
}

// Async provides access to the default Async Box for asynchronous operations. See NillableAsyncBox for more information.
func (box *NillableBox) Async() *NillableAsyncBox {
	return &NillableAsyncBox{AsyncBox: box.Box.Async()}
}

// NillableAsyncBox provides asynchronous operations on Nillable objects.
//
// Asynchronous operations are executed on a separate internal thread for better performance.
//
// There are two main use cases:
//
// 1) "execute & forget:" you gain faster put/remove operations as you don't have to wait for the transaction to finish.
//
// 2) Many small transactions: if your write load is typically a lot of individual puts that happen in parallel,
// this will merge small transactions into bigger ones. This results in a significant gain in overall throughput.
//
// In situations with (extremely) high async load, an async method may be throttled (~1ms) or delayed up to 1 second.
// In the unlikely event that the object could still not be enqueued (full queue), an error will be returned.
//
// Note that async methods do not give you hard durability guarantees like the synchronous Box provides.
// There is a small time window in which the data may not have been committed durably yet.
type NillableAsyncBox struct {
	*objectbox.AsyncBox
}

// AsyncBoxForNillable creates a new async box with the given operation timeout in case an async queue is full.
// The returned struct must be freed explicitly using the Close() method.
// It's usually preferable to use NillableBox::Async() which takes care of resource management and doesn't require closing.
func AsyncBoxForNillable(ob *objectbox.ObjectBox, timeoutMs uint64) *NillableAsyncBox {
	var async, err = objectbox.NewAsyncBox(ob, 2, timeoutMs)
	if err != nil {
		panic("Could not create async box for entity ID 2: %s" + err.Error())
	}
	return &NillableAsyncBox{AsyncBox: async}
}

// Put inserts/updates a single object asynchronously.
// When inserting a new object, the Id property on the passed object will be assigned the new ID the entity would hold
// if the insert is ultimately successful. The newly assigned ID may not become valid if the insert fails.
func (asyncBox *NillableAsyncBox) Put(object *Nillable) (uint64, error) {
	return asyncBox.AsyncBox.Put(object)
}

// Insert a single object asynchronously.
// The Id property on the passed object will be assigned the new ID the entity would hold if the insert is ultimately
// successful. The newly assigned ID may not become valid if the insert fails.
// Fails silently if an object with the same ID already exists (this error is not returned).
func (asyncBox *NillableAsyncBox) Insert(object *Nillable) (id uint64, err error) {
	return asyncBox.AsyncBox.Insert(object)
}

// Update a single object asynchronously.
// The object must already exists or the update fails silently (without an error returned).
func (asyncBox *NillableAsyncBox) Update(object *Nillable) error {
	return asyncBox.AsyncBox.Update(object)
}

// Remove deletes a single object asynchronously.
func (asyncBox *NillableAsyncBox) Remove(object *Nillable) error {
	return asyncBox.AsyncBox.Remove(object)
}

// Query provides a way to search stored objects
//
// For example, you can find all Nillable which Id is either 42 or 47:
//
// box.Query(Nillable_.Id.In(42, 47)).Find()
type NillableQuery struct {
	*objectbox.Query
}

// Find returns all objects matching the query
func (query *NillableQuery) Find() ([]*Nillable, error) {
	objects, err := query.Query.Find()
	if err != nil {
		return nil, err
	}
	return objects.([]*Nillable), nil
}

// Offset defines the index of the first object to process (how many objects to skip)
func (query *NillableQuery) Offset(offset uint64) *NillableQuery {
	query.Query.Offset(offset)
	return query
}

// Limit sets the number of elements to process by the query
func (query *NillableQuery) Limit(limit uint64) *NillableQuery {
	query.Query.Limit(limit)
	return query
}
