#include "gameplay/weapons/bulletmanager.h"
#include "gameplay/weapons/bullet.h"
#include "gameplay/physics.h"
#include "utility/events.h"
#include "utility/component.h"

#include <algorithm>

void BulletManager::hookEventManager(const std::shared_ptr<EventManager>& eventManager)
{
	this->eventManager = eventManager;
	this->eventManager->subscribe("OnBulletDied", [this](std::shared_ptr<Event> e) {
		auto bulletEvent = std::static_pointer_cast<BulletDiedEvent>(e);
		auto iterator = std::find_if(bullets.begin(), bullets.end(), [&](std::shared_ptr<Bullet> bullet) {
			return bullet->getPhysicsComponent() == bulletEvent->physObj;
		});
		if (iterator != bullets.end())
			bullets.erase(iterator);
	});
}

void BulletManager::addBullet(const std::shared_ptr<Bullet>& bullet)
{
	bullets.emplace_back(bullet);
}

void BulletManager::addBullet(const unsigned int owner, const glm::vec3& fireFrom, 
	const glm::vec2& direction, 
	float bulletSpeed, 
	float bulletDrop,
	glm::vec2 bulletSize,
	const std::shared_ptr<Shader>& shader, 
	const std::shared_ptr<Component>& sprite)
{
	auto bullet = std::make_shared<Bullet>(owner, shader, fireFrom, direction, bulletSpeed, bulletDrop, bulletSize);
	bullet->addComponent(sprite);
	//bullet->addPhysicsComponent(phy)
	bullets.emplace_back(bullet);
}

void BulletManager::update(float deltaTime)
{
	for (auto& bullet : bullets)
	{
		if (!bullet) continue;
		bullet->update(deltaTime);
		float distance = glm::distance(bullet->getPosition(), bullet->getBulletOrigin());
		if (distance > bullet->getBulletDrop())
		{
			if (eventManager)
				eventManager->notify(std::make_shared<BulletDiedEvent>(bullet->getPhysicsComponent()));
			//bullets.erase(std::remove(bullets.begin(), bullets.end(), bullet));
		}
	}
}

void BulletManager::render(const std::shared_ptr<Camera>& camera)
{
	for (auto& bullet : bullets)
	{
		if (!bullet) continue;
		bullet->render(camera);
	}
}