#ifndef CPPCADES_UECARD_H_
#define CPPCADES_UECARD_H_
#define BOOST_ALL_NO_LIB 
#include "cppcades.h"
#include "CPPCadesCardholderData.h"
#include "CPPCadesPersonalCardholderData.h"
#include "CPPCadesOMSData.h"
#include "CPPCadesCPCertificate.h"
#include <boost/thread/mutex.hpp>

namespace CryptoPro {
namespace PKI {
namespace CAdES {

class CPPCadesUECardObject
{
public:
    CPPCadesUECardObject();
    ~CPPCadesUECardObject();

    HRESULT set_Pin1(const CAtlStringA& Pin1);
    HRESULT get_PersonalCardholderData(bool isTrustedData,
        boost::shared_ptr<CPPCadesPersonalCardholderDataObject>& pVal);
    HRESULT get_CardholderData(
        boost::shared_ptr<CPPCadesCardholderDataObject>& pVal);
    HRESULT get_UECardWelcomeText(CAtlStringW& cardWelcomeText);
    HRESULT get_ProviderVersion(CAtlString& providerVersion);
    HRESULT get_Certificate(boost::shared_ptr<CPPCadesCPCertificateObject>& pVal);
    HRESULT get_OMSData(boost::shared_ptr<CPPCadesOMSDataObject>& pVal);
    //internal use
    HRESULT checkUECProv();
    HRESULT getReaderName(CAtlStringA& readerName);
private:
    DISALLOW_COPY_AND_ASSIGN(CPPCadesUECardObject);

    HRESULT initCryptProv();
    ATL2::CCryptProvEx m_cryptProv;

    HRESULT initCryptProvSig();
    ATL2::CCryptProvEx m_cryptProvSig;

    // mutex используется только для инициализации m_cryptProvSig,
    // так как эта инициализация может происходить и в другом потоке.
    // Потокобезопасность при использовании заполненного 
    // m_cryptProvSig обеспечит криптопровайдер.
    boost::mutex m_cryptProvSigMutex;

    CAtlString m_provVersion;

    boost::shared_ptr<CPPCadesCardholderDataObject> m_pPublicData;
    boost::shared_ptr<CPPCadesPersonalCardholderDataObject> m_pPersonalData;
    boost::shared_ptr<CPPCadesOMSDataObject> m_pOMSData;
    boost::shared_ptr<CPPCadesCPCertificateObject> m_pCertificate;
};

// Класс, позволяющий безопасно получить имя считывателя в отдельном потоке.
// При неодходимости заполнит хэндл провайдера для подписи у аггрегированного
// объекта.
// Наружу намеренно выставлен только один метод, чтобы не было соблазна позвать
// из другого потока что-то еще, не убедившись в потокобезопасности.
class CPPCadesUECardThreadObject
{
public:
    CPPCadesUECardThreadObject(){};
    CPPCadesUECardThreadObject(boost::shared_ptr<CPPCadesUECardObject> pCard)
    {
        m_pCard = pCard;
    };
    HRESULT getReaderName(CAtlStringA& readerName)
    {
        return m_pCard->getReaderName(readerName);
    };

private:
    boost::shared_ptr<CPPCadesUECardObject> m_pCard;
};

} /* namespace CAdES */
} /* namespace PKI */
} /* namespace CryptoPro */

#endif //CPPCADES_UECARD_H_
