#include "game/gameplay/door_tracker.hpp"

// [SINGLETON]
DoorTracker* DoorTracker::door_tracker = nullptr;

// [SINGLETON] Crearemos el objeto con esta función estática
void DoorTracker::init() {
    DoorTracker::door_tracker = new DoorTracker();
}

// [SINGLETON] Destruiremos el objeto con esta función estática
void DoorTracker::destroy() {
    delete DoorTracker::door_tracker;
}

// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
auto DoorTracker::get() -> DoorTracker* {
    return DoorTracker::door_tracker;
}

// Comprueba si la puerta ya está abierta
auto DoorTracker::hasBeenOpened(const std::string& name, SDL_FPoint pos) -> bool {
    if (const int INDEX = findByName(name); INDEX != NOT_FOUND) {
        if (findByPos(INDEX, pos) != NOT_FOUND) {
            return true;
        }
    }

    return false;
}

// Marca la puerta como abierta
void DoorTracker::addDoor(const std::string& name, SDL_FPoint pos) {
    if (!hasBeenOpened(name, pos)) {
        if (const int INDEX = findByName(name); INDEX != NOT_FOUND) {
            doors_.at(INDEX).pos.push_back(pos);
        } else {
            doors_.emplace_back(name, pos);
        }
    }
}

// Vacía el tracker
void DoorTracker::clear() {
    doors_.clear();
}

// Busca una entrada en la lista por nombre
auto DoorTracker::findByName(const std::string& name) -> int {
    int i = 0;

    for (const auto& door : doors_) {
        if (door.name == name) {
            return i;
        }
        i++;
    }

    return NOT_FOUND;
}

// Busca una entrada en la lista por posición
auto DoorTracker::findByPos(int index, SDL_FPoint pos) -> int {
    int i = 0;

    for (const auto& door : doors_[index].pos) {
        if ((door.x == pos.x) && (door.y == pos.y)) {
            return i;
        }
        i++;
    }

    return NOT_FOUND;
}
