#pragma once

#include <winscard.h>
#include <map>

#include "cryptoki.h"
#include "byteBuffer.h"
#include "Util.h"

class CCommunicator;

/* Longitud de las plantillas:                                             */
#define TAM_TEMPL_DATA           7  
#define TAM_TEMPL_CERTIFICATE    11  
#define TAM_TEMPL_PUBLIC_KEY     19
#define TAM_TEMPL_PRIVATE_KEY    29
#define TAM_TEMPL_SECRET_KEY     22


class CPKCS11Object //: public CObject
{
protected:

public:	
	CPKCS11Object ();
	~CPKCS11Object ();

	// Accedentes
	bool isPrivate ();
	
	void SetAttribute( CK_ATTRIBUTE_TYPE type, byte * pValue, ulong ulValueLen );
	void SetAttribute( CK_ATTRIBUTE_TYPE type, byteBuffer & value );
	void SetAttribute( CK_ATTRIBUTE_TYPE type, ulong value );
	void SetAttribute( CK_ATTRIBUTE_TYPE type, byte value );
	void SetAttribute( CK_ATTRIBUTE_TYPE type, bool value );

	void AddAttribute2Object( CK_ATTRIBUTE_PTR att );
	int KindOfAttribute( CK_ATTRIBUTE_TYPE  attribute );
	void CreateObject( CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount );
	virtual bool ValidAttributes( CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount ) = 0;
	virtual bool VerifyModifiableAttributes( CK_ATTRIBUTE_PTR pTemplate, 
											 CK_ULONG ulCount ) = 0;

	void SetValuePath( byte * pPath, int pathSize, int index, int length );
	void SetValuePath( byteBuffer & pPath, int iIndex, int iLength );

	byteBuffer * GetAttribute( CK_ATTRIBUTE_TYPE attType );
	ulong GetAttributeUlong( CK_ATTRIBUTE_TYPE attType );
	bool GetAttributeBool( CK_ATTRIBUTE_TYPE attType );

	void GetAttributeBuffer( CK_ATTRIBUTE_TYPE attType, byteBuffer * bBuffer );

	virtual bool IsSensitive ( CK_ATTRIBUTE_TYPE attType ) { return false; };

	bool MatchTemplate( CK_ATTRIBUTE_PTR pSearchTemplate, CK_ULONG ulCount );

	bool EsExportacionDesdeExplorer( CK_ATTRIBUTE_PTR  pTemplate,
									 CK_ULONG          ulCount);

	bool ModificarEtiquetaExportacion( );

	byteBuffer * GetValuePath( void );
	int * GetValueIndex( void );
	int * GetValueLength( void );
	CK_OBJECT_HANDLE GetHandle( void );

private:
	map<CK_ATTRIBUTE_TYPE,byteBuffer *>	m_attributes;
	byteBuffer							m_valuePath;
	int									m_valueIndex;
	int									m_valueLength;
	CK_OBJECT_HANDLE					m_hObject;

};


class CPKCS11CertificateObject : public CPKCS11Object
{
public:	
	// Contrucción destrucción:
	CPKCS11CertificateObject (); 
	~CPKCS11CertificateObject ();    

	// Método para comprobar si una plantilla es válida para este tipo de objetos
	bool ValidAttributes( CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount );
	bool VerifyModifiableAttributes( CK_ATTRIBUTE_PTR pTemplate, 
									 CK_ULONG ulCount );

private:

};

class CPKCS11KeyObject : public CPKCS11Object
{
public:	
	// Contrucción destrucción:
//	CPKCS11KeyObject (); 
//	~CPKCS11KeyObject (); 

	byte GetKeyReference(){
		return m_keyReference;
	};

	void SetKeyReference(byte keyRef){
		m_keyReference = keyRef;
	};

	//CK_ULONG GetKeyLen();
	CK_ULONG GetKeyLen(){
		return m_ulKeyLen;
	};

	void SetKeyLen(CK_ULONG	ulKeyLen){
		m_ulKeyLen = ulKeyLen;
	};

private:
	byte		m_keyReference;	
	CK_ULONG	m_ulKeyLen;


};

class CPKCS11PublicKeyObject : public CPKCS11KeyObject
{
public:	
	// Contrucción destrucción:
	CPKCS11PublicKeyObject (); 
	~CPKCS11PublicKeyObject (); 

	// Método para comprobar si una plantilla es válida para este tipo de objetos
    bool ValidAttributes( CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount );
	bool VerifyModifiableAttributes( CK_ATTRIBUTE_PTR pTemplate, 
									 CK_ULONG ulCount );

private:

};


class CPKCS11PrivateKeyObject : public CPKCS11KeyObject
{
public:	
	// Contrucción destrucción:
	CPKCS11PrivateKeyObject (); 
	~CPKCS11PrivateKeyObject (); 

	// Método para comprobar si una plantilla es válida para este tipo de objetos
	bool ValidAttributes( CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount );
	bool VerifyModifiableAttributes( CK_ATTRIBUTE_PTR pTemplate, 
									 CK_ULONG ulCount );

	bool IsSensitive ( CK_ATTRIBUTE_TYPE attType );

private:

};

class CPKCS11DataObject : public CPKCS11Object
{
public:	
	// Contrucción destrucción:
	CPKCS11DataObject (); 
	~CPKCS11DataObject (); 

	// Método para comprobar si una plantilla es válida para este tipo de objetos
	bool ValidAttributes( CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount );
	bool VerifyModifiableAttributes( CK_ATTRIBUTE_PTR pTemplate, 
									 CK_ULONG ulCount );

private:

};

