#pragma once

#include <winscard.h>

#if defined __pcsclite_h__
    #include <reader.h>
#endif

#include <string>
#include <vector>
class CSlot;
#include "P15File.h"
#include "P15TokenInfo.h"

#include "TokenType.h"

#ifdef __APPLE__
#include <wintypes.h>
#endif

#define MAX_CMD_ANSWER	300
#define HWVERSION_MAJOR 0x0D
#define HWVERSION_MINOR 0x0E
#define FMVERSION_MAJOR 0x0F
#define FMVERSION_MINOR 0x10

using namespace std;

class CMech;

/********************************************************************************************
	Clase que representa un lector.
********************************************************************************************/
class CSlot
{
	public:

		// Constructor
		CSlot(string sName, CK_SLOT_ID slotId);
		CSlot(const CSlot & slot);
/*
		CSlot(void)
		{
			DBG_TRACE(( "Constructor CSlot() [0x%08x]\n", this ));
		};
*/
		// Destructor
		~CSlot(void);

		// Método que obtiene el nombre del lector
		const string & GetName() const;

		// Método que obtiene el identificador del lector
		CK_SLOT_ID GetSlotId() const;

		// Método que obtiene el handle de la tarjeta del lector
		SCARDHANDLE GetCardHandle() const;

		// Método que obtiene el estado del lector
		SCARD_READERSTATE GetState();

		// Método que asigna un nuevo estado al lector
		void SetState(SCARD_READERSTATE &state);

		// Método que obtiene el TokenInfo de la tarjeta del lector.
		TokenInfo * GetTokenInfo(CK_TOKEN_INFO_PTR pInfo = NULL);
		void ReadTokenInfo( CCommunicator & comm );

		// Método para gestionar los mecanismos soportados por el token
		void GetMechanismList( CK_MECHANISM_TYPE_PTR pMechanismList,
							   CK_ULONG_PTR          pulCount);

		bool IsValidMechanism ( CK_MECHANISM_TYPE mechanism );

		CMech* newMechanism( CK_MECHANISM_TYPE mechanism );

		// Métodos para establecer/liberar una conexión con la tarjeta del lector
		void Connect( DWORD dwShareMode = SCARD_SHARE_SHARED );
		//void Disconnect( void );
		void Disconnect( bool bCritical = NULL );

		//
		void TransmitData( byteBuffer & cmd, byteBuffer & answer );
		void TransmitData( byte * pCmd, ulong cmdLen, byteBuffer & answer );

		void BeginTransaction( void );
		void EndTransaction( void );

		// Método que hace una comprobación de la tarjeta del lector
		string CheckToken();

		// Método que indica el número de ficheros elementales hijos del DF Publico (6061).
		int GetNumberPublicFE( CCommunicator & comm );

        #if defined WIN32
            // Handle del evento de control de drivers para tokens con certificados Publicos/Privados
            HANDLE			m_hEvento;
        #endif

		// Método que comprueba si el lector tiene una tarjeta de las soportadas por el módulo
		bool SupportedTokenPresent();

		CTokenType & getTokenType(void);

		void SetP15Error(){m_bTokenP15Error = true;};

		//
		// Conversión de errores PCSC a errores PKCS#11
		//
		static ulong PCSCErr2P11Err( ulong ulPCSCErr );

		//
		// Variable que nos va a indicar si se trata de un DNIe + Pasaporte (DNIe 3.0)
		// 
		int m_DniType;	// 0 no es DNIe
						// 1 DNIe 2.0 (canal USUARIO)
						// 2 DNIe 3.0 (canal PIN y canal USUARIO)
	private:

		//Transation begun
		bool transactionBegun;

		// Nombre
		string m_sName;

		// Identificador
		CK_SLOT_ID m_slotId;

		// Handle de la tarjeta del lector
		SCARDHANDLE m_hCard;

		// Número de EFs para objetos públicos encontrados en el DF 6061
		int m_numPublic;

		// Puntero al tipo de token identificado
		CTokenType	* m_pTokenType;

		// TokenInfo de la tarjeta insertada en ese slot
		CP15TokenInfo m_tokenInfoCard;

		SCARD_READERSTATE m_readerState;

		bool m_bTokenP15Error;

		// evento solicitado con C_WaitForSlotEvent
		bool m_slotEvent;

		// Método que actualiza los flags de estado del PIN
		void UpdatePINFlags(CK_TOKEN_INFO_PTR pInfo);

};
