// Copyright (c) 2023 Alex Diener. All rights reserved.

#ifndef __GameEntity_H__
#define __GameEntity_H__

typedef struct GameEntity GameEntity;
#define GameEntity_superclass StemObject

#include "PROJECT_NAME/SharedDefinitions.h"
#include "stemobject/StemObject.h"
#include "utilities/IOUtilities.h"

typedef enum GameEntity_propertyType {
	PROPERTY_TYPE_Vector2i_int8_t,
	PROPERTY_TYPE_bool,
	PROPERTY_TYPE_uint8_t,
	PROPERTY_TYPE_uint16_t,
	PROPERTY_TYPE_uint32_t
} GameEntity_propertyType;

typedef void (* GameEntity_enumeratePropertiesCallback)(void * address, GameEntity_propertyType type, void * context);

#define GameEntity_createWithEncodedState_implementation() \
	stemobject_implementation * self = malloc(sizeof(stemobject_implementation)); \
	self->vtable = &stemobject_cat(stemobject_implementation, class); \
	self->protected_ivar(allocated) = true; \
	stemobject_cat(stemobject_implementation, initWithEncodedState)(self, memreadContext, roomState); \
	return self;

struct RoomState;

#define GameEntity_ivars \
	StemObject_ivars \
	\
	uint32_t entityID; \
	struct RoomState * roomState; \
	bool markedForRemoval;

#define GameEntity_vtable(self_type) \
	StemObject_vtable(self_type) \
	\
	self_type * (* createWithEncodedState)(struct memreadContext * memreadContext, struct RoomState * roomState); \
	void (* initWithEncodedState)(self_type * self, struct memreadContext * memreadContext, struct RoomState * roomState); \
	self_type * (* copy)(self_type * self, struct RoomState * roomState); \
	void (* initCopy)(self_type * self, compat_type(self_type *) original, struct RoomState * roomState); \
	void (* postinit)(self_type * self); \
	compat_type(GameEntityComponent *) (* getComponent)(self_type * self, ComponentType type); \
	void (* roomEntered)(self_type * self); \
	void (* roomExited)(self_type * self); \
	void (* preadvance)(self_type * self); \
	void (* advanceTurn)(self_type * self); \
	void (* postadvance)(self_type * self); \
	bool (* isEqual)(self_type * self, self_type * compare); \
	void (* encodeState)(self_type * self, struct memwriteContext * memwriteContext, bool transient); \
	void (* xorState)(self_type * self, struct memreadContext * memreadContext); \
	void (* enumerateProperties)(self_type * self, bool transient, GameEntity_enumeratePropertiesCallback callback, void * context); \
	void (* undoActionPerformed)(self_type * self);

stemobject_declare(GameEntity)

bool GameEntity_init(GameEntity * self, struct RoomState * roomState);
GameEntity * GameEntity_createWithEncodedState(struct memreadContext * memreadContext, struct RoomState * roomState);
void GameEntity_initWithEncodedState(GameEntity * self, struct memreadContext * memreadContext, struct RoomState * roomState);
void GameEntity_dispose(GameEntity * self);
GameEntity * GameEntity_copy(GameEntity * self, struct RoomState * roomState);
void GameEntity_initCopy(GameEntity * self, compat_type(GameEntity *) original, struct RoomState * roomState);
compat_type(GameEntityComponent *) GameEntity_getComponent(GameEntity * self, ComponentType type);
void GameEntity_postinit(GameEntity * self);
void GameEntity_roomEntered(GameEntity * self);
void GameEntity_roomExited(GameEntity * self);
void GameEntity_preadvance(GameEntity * self);
void GameEntity_advanceTurn(GameEntity * self);
void GameEntity_postadvance(GameEntity * self);
bool GameEntity_isEqual(GameEntity * self, GameEntity * compare); // Transient only
void GameEntity_encodeState(GameEntity * self, struct memwriteContext * memwriteContext, bool transient);
void GameEntity_xorState(GameEntity * self, struct memreadContext * memreadContext); // Transient only
void GameEntity_enumerateProperties(GameEntity * self, bool transient, GameEntity_enumeratePropertiesCallback callback, void * context);
void GameEntity_undoActionPerformed(GameEntity * self);

#endif
