//
// Created by jovian on 18/07/17.
//

#include "TinyWorld.h"
#include "ScullingQuery.h"
#include "Wall.h"

#define MAX_BLOCS_NUMBER 350
#define MIN_BLOCS_NUMBER 300

#define MAX_WIDTH 400
#define MIN_WIDTH 200

#define MAX_HEIGHT 400
#define MIN_HEIGHT 200

TinyWorld::TinyWorld(const b2Vec2 &gravity) : b2World(gravity) {}

void TinyWorld::createProceduralWorld() {
    // Determine number of blocs
    int numberOfBlocs(MIN_BLOCS_NUMBER + rand() % (MAX_BLOCS_NUMBER - MIN_BLOCS_NUMBER));

    // Dims
    float width(MIN_WIDTH + rand() % (MAX_WIDTH - MIN_WIDTH));
    float height(MIN_HEIGHT + rand() % (MAX_HEIGHT - MIN_HEIGHT));

    // Bloc sizes
    WallShape shapeTab[4] = {TINY, HIGH, WIDE, BIG};

    // Generate
    for (int k(0); k < numberOfBlocs; k++) {
        addEntity(new Wall(b2Vec2(width * rand() / RAND_MAX, height * rand() / RAND_MAX), this, shapeTab[rand() % 4]));
    }
}

void TinyWorld::addEntity(Entity *newcomer) {
    m_entities.push_back(newcomer);
}

void TinyWorld::clearEveryEntity() {
    auto it(m_entities.begin());
    while (it != m_entities.end()) {
        delete (*it);
        it = m_entities.erase(it);
    }
}

void TinyWorld::updateAll() {
    for (auto it(m_entities.begin()); it != m_entities.end(); it++) {
        // Clean dead entities
        while (it != m_entities.end() && !(*it)->isExist()) {
            delete (*it);
            it = m_entities.erase(it);
        }

        // Update living entity
        if (it != m_entities.end())
            (*it)->update();
    }
}

void TinyWorld::collectVisuals(std::vector<Visual *> &scope, b2Vec2 center, b2Vec2 diago) {
    /*for (auto it(m_entities.begin()); it != m_entities.end(); it++) {
        scope.push_back((*it)->makeVisual());
    }*/

    ScullingQuery callback;
    b2AABB aabb;
    aabb.lowerBound = center - diago;
    aabb.upperBound = center + diago;
    QueryAABB(&callback, aabb);

    Entity *currentEntity;
    for (auto it(callback.getTab().begin()); it != callback.getTab().end(); it++) {
        currentEntity = (Entity *) (*it)->GetUserData().pointer;
        scope.push_back(currentEntity->makeVisual());
    }
}