#pragma once
#include <string>
#include <vector>
#include <memory>
#include <unordered_map>
#include <map>
#include "external/nlohmann/json.hpp"
#include "TextModel.h"
#include "InteractiveObject.h"

namespace ZL {

	class Character;

	struct GameObjectData {
		std::string name;
		std::string texturePath;
		std::string textureDarkandsPath;
		std::string meshPath;
		float rotationX = 0.0f;
		float rotationY = 0.0f;
		float rotationZ = 0.0f;
		float positionX = 0.0f;
		float positionY = 0.0f;
		float positionZ = 0.0f;
		float scale = 1.0f;
	};

	struct InteractiveObjectData {
		GameObjectData base;
		float interactionRadius = 2.0f;
		std::string activateFunctionName;
		float pivotX = 0.0f;
		float pivotY = 0.0f;
		float pivotZ = 0.0f;
	};

	struct NpcData {
		std::string id;
		std::string name;
		std::string texturePath;
		std::map<std::string, std::string> meshTextures;
		std::string animationIdlePath;
		std::string animationWalkPath;
		// Optional combat / death animations. Empty path = slot not loaded.
		std::string animationActionIdlePath;
		std::string animationActionAttackPath;
		std::string animationStandToActionPath;
		std::string animationActionToStandPath;
		std::string animationActionToDeathPath;
		std::string animationDeathIdlePath;
		float positionX = 0.0f;
		float positionY = 0.0f;
		float positionZ = 0.0f;
		float walkSpeed = 1.5f;
		float rotationSpeed = 8.0f;
		float modelScale = 0.01f;
		float modelCorrectionRotX = 0.0f;
		float modelCorrectionRotY = 0.0f;
		float modelCorrectionRotZ = 0.0f;
		float facingAngle = 0.0f;
		float hp = 100.0f;
		bool canAttack = false;
		bool enabled = true;
		float interactionRadius = 0.0f;
	};

	class GameObjectLoader {
	public:
		static std::unordered_map<std::string, LoadedGameObject> loadAndCreateGameObjects(
			const std::string& jsonPath,
			Renderer& renderer,
			const std::string& zipPath = ""
		);

		static std::vector<InteractiveObject> loadAndCreateInteractiveObjects(
			const std::string& jsonPath,
			Renderer& renderer,
			const std::string& zipPath = ""
		);

		static std::vector<std::unique_ptr<ZL::Character>> loadAndCreate_Npcs(
			const std::string& jsonPath,
			const std::string& zipPath = ""
		);

		static std::vector<NpcData> loadNpcsFromJson(const std::string& jsonPath, const std::string& zipPath = "");

		static LoadedGameObject buildLoadedObject(const GameObjectData& data, Renderer& renderer, const std::string& zipPath);

	private:
		static nlohmann::json loadJson(const std::string& jsonPath, const std::string& zipPath);
		static std::vector<GameObjectData> loadFromJson(const std::string& jsonPath, const std::string& zipPath);
		static std::vector<InteractiveObjectData> loadInteractiveFromJson(const std::string& jsonPath, const std::string& zipPath);
	};

} // namespace ZL
