#include "utility/resourcemanager.h"
#include "utility/component.h"
#include "graphics/sprite.h"
#include "graphics/tile.h"
#include "utility/script.h"
#include "graphics/tiletype.h"
#include "graphics/shader.h"
#include "gameplay/weapons/weapons.h"

std::shared_ptr<Sprite> ResourceManager::loadSpriteAnimated(const std::string& path, float frameSize)
{
	auto iterator = sprites.find(path);
	if (iterator != sprites.end())
		return iterator->second;
	auto sprite = std::make_shared<SpriteAnimated>(path.c_str(), frameSize);
	sprites[path] = sprite;
	return sprite;
}

std::shared_ptr<Sprite> ResourceManager::loadSpriteDirAnimated(const std::string& path, float frameSize)
{
	return std::make_shared<SpriteDirectionalAnimated>(path.c_str(), frameSize);
}

std::shared_ptr<Sprite> ResourceManager::loadSpriteStatic(const std::string& path)
{
	auto iterator = sprites.find(path);
	if (iterator != sprites.end())
		return iterator->second;
	auto sprite = std::make_shared<SpriteStatic>(path.c_str());
	sprites[path] = sprite;
	return sprite;
}

std::shared_ptr<AIScript> ResourceManager::loadAIScript(const std::string& path)
{
	return std::make_shared<AIScript>(path.c_str());
}

std::shared_ptr<WeaponScript> ResourceManager::loadWeaponScript(const std::string& path)
{
	return std::make_shared<WeaponScript>(path.c_str());
}

std::shared_ptr<TileSet> ResourceManager::loadTileSet(const std::string& path, float frameSize)
{
	auto iterator = tileSets.find(path);
	if (iterator != tileSets.end())
		return iterator->second;
	auto tileset = std::make_shared<TileSet>(path.c_str(), frameSize);
	tileSets[path] = tileset;
	return tileset;
}

std::shared_ptr<Shader> ResourceManager::loadShader(const std::string& name, const std::string& vertexPath, const std::string& fragPath)
{
	auto iterator = shaders.find(name);
	if (iterator != shaders.end())
		return iterator->second;
	auto shader = std::make_shared<Shader>(vertexPath.c_str(), fragPath.c_str());
	shaders[name] = shader;
	return shader;
}

// We attach our script after we create our weapon because we are passing a reference to the weapon into the script and we don't want to pass an
// incomplete reference to our script.
std::shared_ptr<Weapon> ResourceManager::loadWeapon(const std::string& name, std::shared_ptr<Shader> weaponShader, std::shared_ptr<Shader> shader)
{
	const WeaponData* data = xmlLoader->getWeaponDataByName(name.c_str());
	auto weapon = std::make_shared<Weapon>(data, weaponShader, shader, this);
	if (!data->script.empty())
		weapon->attachScript(loadWeaponScript(data->script));
	return weapon;
}

std::shared_ptr<SceneData> ResourceManager::loadScene(const std::string& id)
{
	return xmlLoader->getSceneData(id);
}

// this will need some work, but for now where there is only one weapon type we can work with it
// TODO: Allow different weapon types!
/*
template <typename T>
std::shared_ptr<T> ResourceManager::loadWeapon(const std::string& name, std::shared_ptr<Shader> shader, std::shared_ptr<SpriteComponent> spriteComponent)
{
	auto iterator = weapons.find(name);
	if (iterator != weapons.end())
		return iterator->second;
	auto weapon = std::make_shared<T>(T(shader, spriteComponent));
	weapons[name] = weapon;
	return weapon;
}
*/
void ResourceManager::clearResources()
{
	sprites.clear();
	shaders.clear();
	weapons.clear();
}
