#include "ObjList.h"
#include "Pkcs11Exceptions.h"

extern SCARDCONTEXT g_hContext;


/********************************************************************************************
	Constructor.
	Inicializa el contador con el próximo ID a asignar
********************************************************************************************/
CObjList::CObjList(void)
{
}


/********************************************************************************************
	Destructor.
********************************************************************************************/
CObjList::~CObjList(void)
{
}


/********************************************************************************************
	Método que obtiene un nuevo ID de lector.
	Mantiene actualizado el contador de IDs.
********************************************************************************************/
/*
unsigned long CObjList::GetNewId()
{
	return m_ulNextId++;
}
*/

/********************************************************************************************
	Método que actualiza la lista de objetos P11 del equipo.
********************************************************************************************/
void CObjList::Insert(CPKCS11Object* pPKCS11Object)
{
	// Insertamos el objeto en la última posición
	//m_objectList.push_back(pPKCS11Object);

	// Insertamos el objeto en la última posición
	m_objectList.insert(m_objectList.end(), pPKCS11Object);
	m_mapHandle2P11Object.insert(pair<CK_OBJECT_HANDLE, CPKCS11Object*>(pPKCS11Object->GetHandle(), pPKCS11Object));
}


void CObjList::FindMatchingObjets( CK_ATTRIBUTE_PTR			pSearchTemplate,
								   CK_ULONG					ulCount,
								   CK_BBOOL					soloPublicos,
								   vector<CPKCS11Object *> &	objectsFound )
{
	objectsFound.clear();

	for( ulong idx = 0; idx < m_objectList.size(); ++idx )
	{
		if( soloPublicos && m_objectList[idx]->isPrivate() )
			continue;

		if( m_objectList[idx]->MatchTemplate(pSearchTemplate,ulCount) )
			objectsFound.push_back(m_objectList[idx]);
	}
}

void CObjList::Destroy( CPKCS11Object * pPKCS11Object )
{
	//
	// Buscamos el objeto en la lista para sacarlo de ella
	//
	for( ulong idx=0; idx<m_objectList.size(); ++idx )
	{
		if( m_objectList.at(idx) == pPKCS11Object )
		{
			//
			// Eliminamos el objeto de la lista
			//
			m_objectList.erase(m_objectList.begin()+idx);
			
			//
			// Lo buscamos en el map handle->obj, y lo quitamos
			//
			map<CK_OBJECT_HANDLE,CPKCS11Object *>::iterator	it;

			it = m_mapHandle2P11Object.find(pPKCS11Object->GetHandle());
			if( it != m_mapHandle2P11Object.end() )
				m_mapHandle2P11Object.erase(it);

			delete pPKCS11Object;

			return;
		}
	}
	throw Pkcs11Exception( CKR_OBJECT_HANDLE_INVALID );
}

ulong CObjList::GetNumberOfObjets( void )
{
	return (ulong)m_objectList.size();
}

CPKCS11Object * CObjList::GetObjectFromHandle( CK_OBJECT_HANDLE hObject )
{
	//
	// Lo buscamos en el map handle->obj, y devolvemos el puntero a CPKCS11Object
	//
	map<CK_OBJECT_HANDLE,CPKCS11Object *>::iterator	it;

	it = m_mapHandle2P11Object.find( hObject );
	if( it != m_mapHandle2P11Object.end() )
		return it->second;

	throw Pkcs11Exception( CKR_OBJECT_HANDLE_INVALID );
}

CPKCS11Object & CObjList::at( ulong idx )
{
	if( idx >= m_objectList.size() )
		throw Pkcs11Exception( CKR_GENERAL_ERROR );

	return *m_objectList[idx];
}

