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

#include <algorithm>
#include <memory>

void BulletManager::hookEventManager(std::weak_ptr<EventManager> eventManager)
{
	this->eventManager = eventManager;
	if (auto event = this->eventManager.lock()) {
		std::weak_ptr<BulletManager> weakSelf = shared_from_this();
		event->subscribe<BulletDiedEvent>([weakSelf](const BulletDiedEvent& e) {
			if (auto self = weakSelf.lock()) {
				auto iterator = std::find_if(self->bullets.begin(), self->bullets.end(), [&](std::shared_ptr<Bullet> bullet) {
					return bullet->getPhysicsComponent() == e.physObj;
				});
				if (iterator != self->bullets.end())
					self->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 unsigned& shaderID, 
	std::unique_ptr<Component> sprite)
{
	auto bullet = std::make_shared<Bullet>(owner, shaderID, fireFrom, direction, bulletSpeed, bulletDrop, bulletSize);
	bullet->addComponent(sprite.get());
	//bullet->addPhysicsComponent(phy)
	bullets.emplace_back(bullet);
}

void BulletManager::update(double deltaTime)
{
	for (auto& bullet : bullets)
	{
		if (!bullet) continue;
		bullet->update(deltaTime);
		float distance = glm::distance(glm::vec3(bullet->getPhysicsComponent()->rigidBody.position, 0.f), bullet->getBulletOrigin());
		if (distance > bullet->getBulletDrop() || glm::length(bullet->getPhysicsComponent()->rigidBody.velocity) < 100.0f)
		{
			if (auto event = eventManager.lock())
				event->notify<BulletDiedEvent>((BulletDiedEvent){ bullet->getPhysicsComponent() });
			//bullets.erase(std::remove(bullets.begin(), bullets.end(), bullet));
		}
	}
}

void BulletManager::draw()
{
	for (auto& bullet : bullets)
	{
		if (!bullet) continue;
		bullet->draw();
	}
}
