#ifndef CPPCADESCPSIGNEDDATA_H_
#define CPPCADESCPSIGNEDDATA_H_
#include "cppcades.h"
#include "CPPCadesCollections.h"
#include "CPPCadesCPSigner.h"
#include "CPPCadesContent.h"
#include "CPPCadesCPHashedData.h"
#include "CPPCadesCPStore.h"

namespace CryptoPro {
namespace PKI {
namespace CAdES {

struct SigInfo {
    bool isSigningTimePresent;
    FILETIME signingTime;
    bool isSignatureTimeStampTimePresent;
    FILETIME signatureTimeStampTime;
    bool isValid;
};

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

#ifndef UNIX
    HRESULT put_Content(const BSTR pVal);
    HRESULT get_Content(CComBSTR& pVal);
#endif // UNIX

    HRESULT put_Content(LPCSTR pbData, DWORD cbData);
    HRESULT get_Content(CStringBlob& pVal);

    HRESULT put_DisplayData(DWORD Val);
    HRESULT get_DisplayData(DWORD *pVal);

    HRESULT put_ContentEncoding(CADESCOM_CONTENT_ENCODING_TYPE EncodingType);
    HRESULT get_ContentEncoding(CADESCOM_CONTENT_ENCODING_TYPE* pVal);

    HRESULT get_Signers(boost::shared_ptr<CPPCadesCPSignersObject>& pVal);
    HRESULT get_Certificates(boost::shared_ptr<CPPCadesCPCertificatesObject>& pVal);

    HRESULT Sign(boost::shared_ptr<CPPCadesCPSignerObject>& pSigner, BOOL bDetached,
        CAPICOM_ENCODING_TYPE EncodingType, CBlob* pVal);
    HRESULT CoSign(boost::shared_ptr<CPPCadesCPSignerObject>& pSigner,
        CAPICOM_ENCODING_TYPE EncodingType, CBlob* pVal);

    HRESULT EnhanceCades(CADESCOM_CADES_TYPE CadesType,
        CAtlString TSAAddress,
        CAPICOM_ENCODING_TYPE EncodingType, CBlob *pVal);

    HRESULT SignCades(boost::shared_ptr<CPPCadesCPSignerObject>& pSigner,
        CADESCOM_CADES_TYPE CadesType, BOOL bDetached,
        CAPICOM_ENCODING_TYPE EncodingType, CBlob *pVal);
    HRESULT CoSignCades(boost::shared_ptr<CPPCadesCPSignerObject>& pSigner,
        CADESCOM_CADES_TYPE CadesType, 
        CAPICOM_ENCODING_TYPE EncodingType, CBlob *pVal);

    HRESULT CoSignHash(boost::shared_ptr<CPPCadesCPSignerObject>& pSigner,
        boost::shared_ptr<CPPCadesCPHashedDataObject>& pHashedData,
        CADESCOM_CADES_TYPE CadesType,
        CAPICOM_ENCODING_TYPE EncodingType, CBlob *pVal);
    HRESULT SignHash(boost::shared_ptr<CPPCadesCPSignerObject>& pSigner,
        boost::shared_ptr<CPPCadesCPHashedDataObject>& pHashedData,
        CADESCOM_CADES_TYPE CadesType,
        CAPICOM_ENCODING_TYPE EncodingType, CBlob *pVal);

    HRESULT AddCertificateChain( boost::shared_ptr<CPPCadesCPCertificateObject> pCert,
        std::vector<PCCERT_CONTEXT> &certs,
        CAPICOM_CERTIFICATE_INCLUDE_OPTION includeCertOption );

    HRESULT VerifyHash(boost::shared_ptr<CPPCadesCPHashedDataObject>& pHashedData,
        const CBlob& SignedMessage,
        CADESCOM_CADES_TYPE CadesType = CADESCOM_CADES_DEFAULT);

    HRESULT Verify(const CBlob& SignedMessage, BOOL bDetached,
        CAPICOM_SIGNED_DATA_VERIFY_FLAG VerifyFlag);
    HRESULT VerifyCades(const CBlob& SignedMessage,
        CADESCOM_CADES_TYPE CadesType = CADESCOM_CADES_DEFAULT, 
        BOOL bDetached = 0);

    HRESULT Display(LONG hwndParent, const wchar_t* Title);

    HRESULT AdditionalStore(boost::shared_ptr<CPPCadesCPStoreObject>& pStore);

private:
    DISALLOW_COPY_AND_ASSIGN(CPPCadesSignedDataObject);
    // Сбросить состояние CadesSignedData при задании нового контента
    void ResetState();
    void SetAlgIdentifier(CAtlStringA &oid);
    HRESULT CheckState();
    //DISALLOW_COPY_AND_ASSIGN(CPPCadesSignedDataObject);    
    HRESULT SignCadesImpl(boost::shared_ptr<CPPCadesCPSignerObject>& pSigner,
        CADESCOM_CADES_TYPE CadesType, BOOL bDetached,
        CAPICOM_ENCODING_TYPE EncodingType, CBlob *pVal);
    HRESULT CoSignCadesImpl(boost::shared_ptr<CPPCadesCPSignerObject>& pSigner,
        CADESCOM_CADES_TYPE CadesType, 
        CAPICOM_ENCODING_TYPE EncodingType, CBlob *pVal);
    HRESULT FillCertificates();           

    CBlob m_signedMsg;
    BOOL m_bDetached;
    DWORD m_dwDisplayData;

    // для передачи CADES_USE_OCSP_AUTHORIZED_POLICY
    DWORD m_dwDisplayFlags;
#pragma warning(push)
#pragma warning(disable: 4251)
    //ATL2::CCryptMsg m_msg;
    CCadesContent m_content; 
    CBlob m_hashBlob;
    CRYPT_ALGORITHM_IDENTIFIER m_alg;
    boost::shared_ptr<CPPCadesCPCertificatesObject> m_pCertificates;
    boost::shared_ptr<CPPCadesCPSignersObject> m_pSigners;
    std::vector<SigInfo> m_sigInfos;
    boost::shared_ptr<CPPCadesCPStoreObject> m_additionalStore;
#pragma warning(pop)
	BOOL m_isVerifyHash;
};

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

#endif //CPPCADESCPSIGNEDDATA_H_
