#ifndef CMS_PKI_CERT_H_INCLUDED
#define  CMS_PKI_CERT_H_INCLUDED

#include <iostream>
#include <vector>

class Certificate;

#include "pki/icert.h"
#include "../common/common.h"
#include "wrapper/utils/smartbuffer.h"
#include "../stdafx.h"
#include "cert_request.h"
#include "pki.h"
#include "pki/icert_request.h"
#include "wrapper/utils/license_mng.h"

#ifndef DLV_AND_JWT_NO_LICENSE
extern License_Mng* m_objLicense;
#endif // !DLV_AND_JWT_NO_LICENSE

class Certificate : public ICertificate {
public:
	//constructor
	Certificate();
	Certificate(PCCERT_CONTEXT pcertContext);
	Certificate(Handle<ICertificationRequest> cert_req);
	~Certificate();

	//properties
	long getVersion();
	Handle<std::string> getProviderName();
	Handle<std::string> getSerialNumber();
	Handle<std::string> getNotBefore();
	Handle<std::string> getNotAfter();
	Handle<std::string> getKeyNotBefore();
	Handle<std::string> getKeyNotAfter();
	Handle<std::string> getIssuerFriendlyName();
	Handle<std::string> getIssuerName();
	Handle<std::string> getSubjectFriendlyName();
	Handle<std::string> getSubjectName();
	Handle<std::string> getThumbprint();
	Handle<std::string> getPublicKeyAlgorithm();
	Handle<std::string> getSignatureAlgorithm();
	Handle<std::string> getSignatureDigestAlgorithm();
	Handle<std::string> getOrganizationName();
	Handle<std::string> getSubjectKeyIdentifier();

	Handle<std::string> getCertEncoded(DataFormat::DATA_FORMAT format);
	PCCERT_CONTEXT getCertContext();

	//TODO: Написать после реализации класса Key
	//Handle<Key> getPublicKey();

	std::vector<std::string> getOCSPUrls();
	std::vector<std::string> getCAIssuersUrls();

	//TODO: Пустая функция, реализация по мере необходимости
	int getType();

	int getKeyUsage();
	std::vector<std::string> getKeyUsageString();
	std::vector<std::string> getEnhancedKeyUsage();
	bool isSelfSigned();
	bool isCA();
    int getOcspNocheck();

	//Требуется реалиация в cert_request
	//void setSubject(Handle<std::string> x509Name);
	//void setIssuer(Handle<std::string> x509Name);
	//void setVersion(long version);
	////TODO
	//void setExtensions(Handle<ExtensionCollection> exts);
	void setNotBefore(time_t timeUTC);
	void setNotAfter(time_t timeUTC);
	void setSerialNumber(Handle<std::string> serial);

	//TODO
	//Handle<ExtensionCollection> getExtensions();
	//Methods
	void read(Handle<std::string> in, DataFormat::DATA_FORMAT format);
	void write(Handle<std::string> out, DataFormat::DATA_FORMAT format);
	void import(Handle<std::string> data, DataFormat::DATA_FORMAT format);
	Handle<std::string> exportContentFile(DataFormat::DATA_FORMAT format);
	Handle<ICertificate> duplicate();
	int compare(Handle<ICertificate> cert);
	bool equals(Handle<ICertificate> cert);
	void sign();
	void sign(HCRYPTPROV  hCryptProv, DWORD dwKeySpec = AT_KEYEXCHANGE);
	Handle<std::string> hash();
	Handle<std::string> hash(Handle<std::string> algorithm);
	Handle<std::string> hash(ALG_ID algId);
	CRYPT_INTEGER_BLOB stringToSerialNumber(std::string strSerialNumber);
	LPSTR CertBase64ToDer(DWORD dwFlag, DWORD * dsSize);
    void view();

	//TODO: Рассмотреть перенос функции в класс Algorithm
	static DWORD OIDToAlgId(LPCSTR pszObjId);

	bool isEmpty() {
		LOGGER_FN();

		if (m_pCertContext) {
			return false;
		}
		else {
			return true;
		}

	}

	bool hasPrivateKey(Handle<IPkiStore> store = NULL);
	static bool hasPrivateKey(PCCERT_CONTEXT pCertContext);
	std::string getPrivateKeyName(Handle<IPkiStore> store = NULL);
	static std::string getPrivateKeyName(PCCERT_CONTEXT pCertContext);

	static Handle<Certificate> ConvertToInternal(Handle<ICertificate> cert, bool throwOnError = true);

protected:
	/*!
	* \brief Контекст сертификата
	*/
	PCCERT_CONTEXT m_pCertContext;

	PCERT_INFO m_pCertInfo;
	PCRYPT_DATA_BLOB m_pBlobEncCert;

	//for self signed cert
	FILETIME m_ftNotBefore;
	FILETIME m_ftNotAfter;
	std::string m_strSerialNumber;
	std::string m_strContainerName;
	std::string m_strPubKeyAlg;
	DWORD m_dwProvType;
	BOOL m_isExportable;
	BOOL m_bKeyUsagePeriodFromContainer;
};

#endif //!CMS_PKI_CERT_H_INCLUDED
