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

#include "PROJECT_NAME/GameEntities.h"
#include "PROJECT_NAME/RoomSavedState.h"
#include "utilities/IOUtilities.h"

RoomSavedState * RoomSavedState_create(void) {
	RoomSavedState * save = malloc(sizeof(*save));
	save->entityStates = ChunkArray_init();
	save->entityStates.alignment = 1;
	return save;
}

RoomSavedState * RoomSavedState_copy(RoomSavedState * save) {
	if (save == NULL) {
		return NULL;
	}
	RoomSavedState * copy = malloc(sizeof(*copy));
	return copy;
}

void RoomSavedState_dispose(RoomSavedState * save) {
	ChunkArray_free(&save->entityStates);
	free(save);
}

void RoomSavedState_encodeEntity(RoomSavedState * save, GameEntity * entity) {
	struct memwriteContext context = memwriteContextInit(NULL, 0, 0, true);
	uint32_t entrySize = 0;
	memwrite(&context, sizeof(entrySize), &entrySize);
	GameEntityTypeID entityTypeID = getEntityTypeFromVtable(entity);
	memwrite(&context, sizeof(entityTypeID), &entityTypeID);
	call_virtual(encodeState, entity, &context, false);
	entrySize = context.length - sizeof(entrySize);
	*(uint32_t *) context.data = entrySize;
	ChunkArray_append(&save->entityStates, context.data, context.length);
}

unsigned int RoomSavedState_getEntityCount(RoomSavedState * save) {
	return save->entityStates.count;
}

GameEntity * RoomSavedState_decodeEntityAtIndex(RoomSavedState * save, unsigned int entityIndex, struct RoomState * roomState) {
	void * entry = ChunkArray_entryAtIndex(&save->entityStates, entityIndex);
	struct memreadContext context = memreadContextInit(entry + sizeof(uint32_t), *(uint32_t *) entry);
	uint16_t entityTypeID;
	memread(&context, sizeof(entityTypeID), &entityTypeID);
	struct GameEntity_vtableStruct * vtable = getVtableFromEntityType(entityTypeID);
	GameEntity * entity = vtable->createWithEncodedState(&context, roomState);
	return entity;
}
