#include "ObjectIDManager.h"

// Std
#include <random>

// Custom Classes
#include "MasterPackets.h"
#include "Database.h"
#include "dLogger.h"
#include "Game.h"

// Static Variables
ObjectIDManager* ObjectIDManager::m_Address = nullptr;
static std::uniform_int_distribution<int> uni(10000000, INT32_MAX);

//! Initializes the manager
void ObjectIDManager::Initialize(void) {
	//this->currentRequestID = 0;
	this->currentObjectID = uint32_t(1152921508165007067); //Initial value for this server's objectIDs
}

//! Requests a persistent ID
void ObjectIDManager::RequestPersistentID(std::function<void(uint32_t)> callback) {
	PersistentIDRequest* request = new PersistentIDRequest();
	request->requestID = ++this->currentRequestID;
	request->callback = callback;

	this->requests.push_back(request);

	MasterPackets::SendPersistentIDRequest(Game::server, request->requestID);
}

//! Handles a persistent ID response
void ObjectIDManager::HandleRequestPersistentIDResponse(uint64_t requestID, uint32_t persistentID) {
	for (uint32_t i = 0; i < this->requests.size(); ++i) {
		if (this->requests[i]->requestID == requestID) {

			// Call the callback function
			this->requests[i]->callback(persistentID);

			// Then delete the request
			delete this->requests[i];
			this->requests.erase(this->requests.begin() + i);
			return;
		}
	}
}

//! Handles cases where we have to get a unique object ID synchronously
uint32_t ObjectIDManager::GenerateRandomObjectID() {
	std::random_device rd;

	std::mt19937 rng(rd());

	return  uni(rng);
}


//! Generates an object ID server-sided (used for regular entities like smashables)
uint32_t ObjectIDManager::GenerateObjectID(void) {
	return ++this->currentObjectID;
}