#include "block.hpp"
#include <window.h>
#include <render/primitives.h>
#include "world.hpp"

#include "entity/simplyEnemy.hpp"
#include "entity/chaseEnemy.hpp"
#include "entity/shootingEnemy.hpp"

#include "spawner.hpp"

namespace game {

Block::Block(const vec2f &pos, World *world) noexcept: position(pos), world(world)
{
    int difficult = world->GetDifficult();

    Spawner *spawners[] = {
        new SimplyEnemySpawner,
        new ShootingEnemySpawner,
        new ChaseEnemySpawner,
        new ChaseEnemySpawner,
    };

    while (difficult > 0) {

        int type = 1;

        if (difficult > 100) {
            type = 4;
        } else if (difficult > 50) {
            type = 2;
        }

        type = rand() % type;

        difficult -= spawners[type]->SpawnEnemies(this, difficult);
    }

    for (Spawner *spawner: spawners) {
        delete spawner;
    }
}


Block::~Block()
{
    for (entity::Enemy *enemy: this->enemies) {
        if (!enemy->IsOnScreen()) {
            this->world->RemoveManagedEntity(enemy);
        } else {
            enemy->Unlink();
        }
    }
}

bool Block::IsLeftScreen() const noexcept
{
    return this->position.x < -this->size.x;
}

bool Block::IsStoped() const noexcept
{
    return !this->isMoving;
}

World *Block::GetWorld() const noexcept
{
    return this->world;
}

void Block::AddEnemy(entity::Enemy *enemy) noexcept
{
    this->enemies.insert(enemy);
}

void Block::RemoveEnemy(entity::Enemy *enemy) noexcept
{
    this->enemies.erase(enemy);
    this->world->RemoveManagedEntity(enemy);
}

vec2f Block::GetPosition() const noexcept
{
    return this->position;
}

void Block::Update(bool moving) noexcept
{
    bool haveBoss = false;

    for (entity::Enemy *enemy: this->enemies) {
        if (enemy->IsBoss()) {
            haveBoss = true;
        }
    }

    if (moving) {
        this->position.x -= this->speed * window::deltaTime;

        if (haveBoss && this->position.x < 0) {
            this->position.x = 0;
            this->isMoving = false;
        }
    } else if (!haveBoss) {
        this->isMoving = true;
    }
}

}
