#ifndef CPP_ENROLL_EXTENSION_OBJECT_H_
#define CPP_ENROLL_EXTENSION_OBJECT_H_

#include "cppcades.h"
#include "CPPEnrollEnumerations.h"
#include "CPPEnrollObjectId.h"
#include "CPPEnrollCollections.h"

using namespace ATL;
namespace CryptoPro {
namespace PKI {
namespace Enroll {

class CPPEnrollObjectIds;
class CPPEnrollCertificatePolicies;

class CPPEnrollX509Extension
{
public:
    CPPEnrollX509Extension(void);
    ~CPPEnrollX509Extension(void);
    HRESULT Initialize(boost::shared_ptr<CPPEnrollObjectId>& pObjectId,
        EncodingType Encoding,
        CAtlString& strEncodedData);
    HRESULT put_Critical(bool newVal);

    // web-disabled
    HRESULT get_Critical(bool* pVal);

    //internal
    HRESULT get_CertExtensionStruct(CERT_EXTENSION& certExt);
    boost::shared_ptr<CPPEnrollObjectId> GetOid();

protected:
    CStringBlob m_value;
    bool m_bCritical;
    boost::shared_ptr<CPPEnrollObjectId> m_pOid;
private:
    DISALLOW_COPY_AND_ASSIGN(CPPEnrollX509Extension);
};

class CPPEnrollX509ExtensionKeyUsage : public CPPEnrollX509Extension
{
public:
    CPPEnrollX509ExtensionKeyUsage(void);
    ~CPPEnrollX509ExtensionKeyUsage(void);

    HRESULT InitializeEncode(X509KeyUsageFlags UsageFlags);
private:
    DISALLOW_COPY_AND_ASSIGN(CPPEnrollX509ExtensionKeyUsage);
};

class CPPEnrollX509ExtensionEnhancedKeyUsage : public CPPEnrollX509Extension
{
public:
    CPPEnrollX509ExtensionEnhancedKeyUsage(void);
    ~CPPEnrollX509ExtensionEnhancedKeyUsage(void);

    HRESULT InitializeEncode(boost::shared_ptr<CPPEnrollObjectIds>& pVal);
private:
    DISALLOW_COPY_AND_ASSIGN(CPPEnrollX509ExtensionEnhancedKeyUsage);
};

class CPPEnrollX509ExtensionTemplate : public CPPEnrollX509Extension
{
public:
    CPPEnrollX509ExtensionTemplate(void);
    ~CPPEnrollX509ExtensionTemplate(void);

    HRESULT InitializeEncode(
        boost::shared_ptr<CPPEnrollObjectId>& pTemplateOid,
        DWORD MajorVersion,
        DWORD MinorVersion);
private:
    DISALLOW_COPY_AND_ASSIGN(CPPEnrollX509ExtensionTemplate);
};

class CPPEnrollX509ExtensionSmimeCapabilities : public CPPEnrollX509Extension
{
public:
    CPPEnrollX509ExtensionSmimeCapabilities(void);
    ~CPPEnrollX509ExtensionSmimeCapabilities(void);

    HRESULT InitializeEncode(boost::shared_ptr<CPPEnrollObjectIds>& pVal);
private:
    DISALLOW_COPY_AND_ASSIGN(CPPEnrollX509ExtensionSmimeCapabilities);
};

class CPPEnrollX509ExtensionSubjectKeyIdentifier : public CPPEnrollX509Extension
{
public:
    CPPEnrollX509ExtensionSubjectKeyIdentifier(void);
    ~CPPEnrollX509ExtensionSubjectKeyIdentifier(void);

    HRESULT InitializeEncode(/*EncodingType Encoding,*/ const CAtlStringA& strKeyIdentifier);
private:
    DISALLOW_COPY_AND_ASSIGN(CPPEnrollX509ExtensionSubjectKeyIdentifier);
};

class CPPEnrollX509ExtensionCertificatePolicies : public CPPEnrollX509Extension
{
public:
    CPPEnrollX509ExtensionCertificatePolicies(void);
    ~CPPEnrollX509ExtensionCertificatePolicies(void);

    HRESULT InitializeEncode(boost::shared_ptr<CPPEnrollCertificatePolicies>& pVal);
private:
    DISALLOW_COPY_AND_ASSIGN(CPPEnrollX509ExtensionCertificatePolicies);
};

class CPPEnrollX509ExtensionSubjectSignTool : public CPPEnrollX509Extension
{
public:
    CPPEnrollX509ExtensionSubjectSignTool(void);
    ~CPPEnrollX509ExtensionSubjectSignTool(void);

    HRESULT InitializeEncode();
private:
    DISALLOW_COPY_AND_ASSIGN(CPPEnrollX509ExtensionSubjectSignTool);
};

class CPPEnrollX509ExtensionIdentificationKind : public CPPEnrollX509Extension
{
public:
    CPPEnrollX509ExtensionIdentificationKind(void);
    ~CPPEnrollX509ExtensionIdentificationKind(void);

    HRESULT InitializeEncode(DWORD dwIdentificationKind);
private:
    DISALLOW_COPY_AND_ASSIGN(CPPEnrollX509ExtensionIdentificationKind);
};

} /* namespace Enroll */
} /* namespace PKI */
} /* namespace CryptoPro */

#endif // CPP_ENROLL_EXTENSION_OBJECT_H_
