#pragma once

#include "Deer/Components.h"
#include "Deer/Enviroment.h"
#include "Deer/Scene/Serialization/SerializationGlobalVars.h"
#include "EntitySerializationStruct.h"

namespace Deer {
	template <class Archive, typename T>
	void saveComponent(Archive& archive, const std::string& componentName, Entity const& m_entity) {
		bool hasComponent = m_entity.hasComponent<T>();
		archive(cereal::make_nvp(("has_" + componentName).c_str(), hasComponent));
		if (hasComponent) {
			const T& component = m_entity.getComponent<T>();
			archive(cereal::make_nvp(componentName.c_str(), component));
		}
	}

	template <class Archive, typename T>
	void loadComponent(Archive& archive, const std::string& componentName, Entity const& m_entity) {
		bool hasComponent;
		archive(cereal::make_nvp(("has_" + componentName).c_str(), hasComponent));
		if (hasComponent) {
			T& component = m_entity.addComponent<T>();
			archive(cereal::make_nvp(componentName.c_str(), component));
		}
	}
	// ENTITY
	template <class Archive>
	void save(Archive& archive, EntitySerializationStruct const& m_entity) {
		const Entity& entity = m_entity.env->getEntity(m_entity.entityID);

		const TagComponent& name = entity.getComponent<TagComponent>();
		archive(cereal::make_nvp("id", m_entity.entityID));
		archive(cereal::make_nvp("name", name.tag));

		const TransformComponent& transform = entity.getComponent<TransformComponent>();
		archive(cereal::make_nvp("transform", transform));

		const RelationshipComponent& relation = entity.getComponent<RelationshipComponent>();
		archive(cereal::make_nvp("relationship", relation));

#ifdef DEER_RENDER
		if (!is_server_serialization) {
			saveComponent<Archive, MeshComponent>(archive, "meshRenderComponent", entity);
			saveComponent<Archive, CameraComponent>(archive, "cameraComponent", entity);
		}
#endif
	}

	template <class Archive>
	void load(Archive& archive, EntitySerializationStruct& m_entity) {
		uint16_t id;
		std::string name;
		archive(cereal::make_nvp("id", id));
		archive(cereal::make_nvp("name", name));

		Entity& entity = m_entity.env->createEntityWithId(id);
		archive(cereal::make_nvp("transform", entity.getComponent<TransformComponent>()));

		RelationshipComponent& rc = entity.getComponent<RelationshipComponent>();
		archive(cereal::make_nvp("relationship", rc));
		entity.setParent(m_entity.env->getEntity(rc.parent_id));
#ifdef DEER_RENDER
		if (!is_server_serialization) {
			loadComponent<Archive, MeshComponent>(archive, "meshRenderComponent", entity);
			loadComponent<Archive, CameraComponent>(archive, "cameraComponent", entity);
		}
#endif
	}

} // namespace Deer