#include "Entities.h"

#include "../Room/Room.h"
#include "Pacman.h"

//IENTITY
void IEntity::set_location(Room* ptr_room) {
	m_ptr_room = ptr_room;
	this->prepare_for_drawing();	//отрисовываем себя
}

Room* IEntity::get_location() {
	return m_ptr_room;
}


//ENEMY
Enemy::Enemy() {
	size_t ind = rand() % config::PATH_ENEMY_TEXTURES.size();

	if (!m_texture.loadFromFile("../../../textures/" + config::PATH_ENEMY_TEXTURES.at(ind))) {
		throw std::runtime_error("Textures loading error\n");
	}

	m_sprite.setOrigin({ m_texture.getSize().x / 2.0f, m_texture.getSize().y / 2.0f});
	m_sprite.setTexture(m_texture);
	m_sprite.setScale({ 2.5f,2.5f });
}

void Enemy::draw_into(sf::RenderWindow& window) const {
	window.draw(m_sprite);
}

void Enemy::prepare_for_drawing() {	//prep drawing проходит в конце set_pos
	m_sprite.setTexture(m_texture);
	m_sprite.setPosition(m_ptr_room->get_position());
}

std::unique_ptr<IDynamicEntity> Enemy::clone() const {
	return std::make_unique<Enemy>(*this);
}

void Enemy::action() {
	auto miliseconds = static_cast<size_t>(m_stopwatch.getElapsedTime().asMilliseconds());	//получаем сколько прошло времени
	if (miliseconds < 500 + rand() % 10000) //если время меньше, чем случайное число до 10000 мс, то бездействие
		return;
	auto direction = static_cast<Room::Direction>(rand() % 4);
	m_ptr_room->get_side(direction)->enter(this);
	m_stopwatch.restart();	//запускаем секундомер сначала
}

std::unique_ptr<IGameEvent> Enemy::accept(IVisitor* ptr_visitor) {
	return ptr_visitor->visit(this);
}


//FOOD
Food::Food() {
	m_circle = sf::CircleShape(config::GAME_FOOD_SIZE/2);
	m_circle.setOrigin({ config::GAME_FOOD_SIZE/2, config::GAME_FOOD_SIZE/2 });
	m_circle.setFillColor(config::GAME_FOOD_COLOR);
}

void Food::catched(Inventory& inventory) {
	inventory.increase_food();
}

void Food::draw_into(sf::RenderWindow& window) const {
	window.draw(m_circle);
}

void Food::prepare_for_drawing() {
	m_circle.setPosition(m_ptr_room->get_position());
}

std::unique_ptr<IStaticEntity> Food::clone() const {
	return std::make_unique<Food>(*this);
}

std::unique_ptr<IGameEvent> Food::accept(IVisitor* ptr_visitor) {
	return ptr_visitor->visit(this);
}


//INVISPOTION
InvisPotion::InvisPotion() {
	m_circle = sf::CircleShape(config::GAME_INVIS_POTION_SIZE / 2);
	m_circle.setOrigin({ config::GAME_INVIS_POTION_SIZE / 2, config::GAME_INVIS_POTION_SIZE / 2 });
	m_circle.setFillColor(config::GAME_INVIS_POTION_COLOR);

	m_rect = sf::RectangleShape({ config::GAME_INVIS_POTION_SIZE * 3 / 8, config::GAME_INVIS_POTION_SIZE * 3 / 4 });
	m_rect.setFillColor(config::GAME_INVIS_POTION_COLOR);
	m_rect.setOrigin({ config::GAME_INVIS_POTION_SIZE * 3 / 16, config::GAME_INVIS_POTION_SIZE });
}

void InvisPotion::catched(Inventory& inventory) {
	inventory.increase_IP();
}

void InvisPotion::draw_into(sf::RenderWindow& window) const {
	window.draw(m_circle);
	window.draw(m_rect);
}

void InvisPotion::prepare_for_drawing() {
	m_circle.setPosition(m_ptr_room->get_position());
	sf::Vector2f circle_pos = m_circle.getPosition();
	m_rect.setPosition({ circle_pos.x, circle_pos.y + config::GAME_INVIS_POTION_SIZE * 0.1f });
}

std::unique_ptr<IStaticEntity> InvisPotion::clone() const {
	return std::make_unique<InvisPotion>(*this);
}

std::unique_ptr<IGameEvent> InvisPotion::accept(IVisitor* ptr_visitor) {
	return ptr_visitor->visit(this);
}