// Delete an object
bool OSToken::deleteObject(OSObject* object)
{
	if (!valid) return false;

	if (objects.find(object) == objects.end())
	{
		ERROR_MSG("Cannot delete non-existent object 0x%08X", object);

		return false;
	}

	MutexLocker lock(tokenMutex);

	ObjectFile* fileObject = dynamic_cast<ObjectFile*>(object);
	if (fileObject == NULL)
	{
		ERROR_MSG("Object type not compatible with this token class 0x%08X", object);

		return false;
	}
	
	// Invalidate the object instance
	fileObject->invalidate();

	// Retrieve the filename of the object
	std::string objectFilename = fileObject->getFilename();

	// Attempt to delete the file
	if (!tokenDir->remove(objectFilename))
	{
		ERROR_MSG("Failed to delete object file %s", objectFilename.c_str());

		return false;
	}

	// Retrieve the filename of the lock
	std::string lockFilename = fileObject->getLockname();

	// Attempt to delete the lock
	if (!tokenDir->remove(lockFilename))
	{
		ERROR_MSG("Failed to delete lock file %s", lockFilename.c_str());

		return false;
	}

	objects.erase(object);

	DEBUG_MSG("Deleted object %s", objectFilename.c_str());

	gen->update();

	gen->commit();

	return true;
}
// Create a new object
OSObject* OSToken::createObject()
{
	if (!valid) return NULL;

	// Generate a name for the object
	std::string objectUUID = UUID::newUUID();
	std::string objectPath = tokenPath + OS_PATHSEP + objectUUID + ".object";
	std::string lockPath = tokenPath + OS_PATHSEP + objectUUID + ".lock";

	// Create the new object file
	ObjectFile* newObject = new ObjectFile(this, objectPath, lockPath, true);

	if (!newObject->valid)
	{
		ERROR_MSG("Failed to create new object %s", objectPath.c_str());

		delete newObject;

		return NULL;
	}

	// Now add it to the set of objects
	MutexLocker lock(tokenMutex);

	objects.insert(newObject);
	allObjects.insert(newObject);
	currentFiles.insert(newObject->getFilename());

	DEBUG_MSG("(0x%08X) Created new object %s (0x%08X)", this, objectPath.c_str(), newObject);

	gen->update();

	gen->commit();

	return newObject;
}
// Index the token
bool OSToken::index(bool isFirstTime /* = false */)
{
	// Check if re-indexing is required
	if (!isFirstTime && (!valid || !gen->wasUpdated()))
	{
		return true;
	}

	// Check the integrity
	if (!tokenDir->refresh() || !tokenObject->valid)
	{
		valid = false;

		return false;
	}

	DEBUG_MSG("Token %s has changed", tokenPath.c_str());

	// Retrieve the directory listing
	std::vector<std::string> tokenFiles = tokenDir->getFiles();

	// Filter out the objects
	std::set<std::string> newSet;

	for (std::vector<std::string>::iterator i = tokenFiles.begin(); i != tokenFiles.end(); i++)
	{
		if ((i->size() > 7) &&
		    (!(i->substr(i->size() - 7).compare(".object"))) &&
		    (i->compare("token.object")))
		{
			newSet.insert(*i);
		}
		else
		{
			DEBUG_MSG("Ignored file %s", i->c_str());
		}
	}

	// Compute the changes compared to the last list of files
	std::set<std::string> addedFiles;
	std::set<std::string> removedFiles;

	// No access to object mutable fields before
	MutexLocker lock(tokenMutex);

	if (!isFirstTime)
	{
		// First compute which files were added
		for (std::set<std::string>::iterator i = newSet.begin(); i != newSet.end(); i++)
		{
			if (currentFiles.find(*i) == currentFiles.end())
			{
				addedFiles.insert(*i);
			}
		}

		// Now compute which files were removed
		for (std::set<std::string>::iterator i = currentFiles.begin(); i != currentFiles.end(); i++)
		{
			if (newSet.find(*i) == newSet.end())
			{
				removedFiles.insert(*i);
			}
		}
	}
	else
	{
		addedFiles = newSet;
	}

	currentFiles = newSet;

	DEBUG_MSG("%d objects were added and %d objects were removed", addedFiles.size(), removedFiles.size());
	DEBUG_MSG("Current directory set contains %d objects", currentFiles.size());

	// Now update the set of objects

	// Add new objects
	for (std::set<std::string>::iterator i = addedFiles.begin(); i != addedFiles.end(); i++)
	{
		if ((i->find_last_of('.') == std::string::npos) ||
		    (i->substr(i->find_last_of('.')) != ".object"))
		{
			continue;
		}

		std::string lockName(*i);
		lockName.replace(lockName.find_last_of('.'), std::string::npos, ".lock");

		// Create a new token object for the added file
		ObjectFile* newObject = new ObjectFile(this, tokenPath + OS_PATHSEP + *i, tokenPath + OS_PATHSEP + lockName);

		DEBUG_MSG("(0x%08X) New object %s (0x%08X) added", this, newObject->getFilename().c_str(), newObject);

		objects.insert(newObject);
		allObjects.insert(newObject);
	}

	// Remove deleted objects
	std::set<OSObject*> newObjects;

	for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
	{
		ObjectFile* fileObject = dynamic_cast<ObjectFile*>((*i));
		if (fileObject == NULL)
		{
			ERROR_MSG("Object type not compatible with this token class 0x%08X", (*i));
	
			return false;
		}
		
		DEBUG_MSG("Processing %s (0x%08X)", fileObject->getFilename().c_str(), *i);

		if (removedFiles.find(fileObject->getFilename()) == removedFiles.end())
		{
			DEBUG_MSG("Adding object %s", fileObject->getFilename().c_str());
			// This object gets to stay in the set
			newObjects.insert(*i);
		}
		else
		{
			fileObject->invalidate();
		}
	}

	// Set the new objects
	objects = newObjects;

	DEBUG_MSG("The token now contains %d objects", objects.size());

	return true;
}