//========================================================================
//
// CertificateInfo.h
//
// This file is licensed under the GPLv2 or later
//
// Copyright 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@gmail.com>
// Copyright 2018, 2019 Albert Astals Cid <aacid@kde.org>
// Copyright 2018 Oliver Sander <oliver.sander@tu-dresden.de>
// Copyright 2020 Thorsten Behrens <Thorsten.Behrens@CIB.de>
//
//========================================================================

#ifndef CERTIFICATEINFO_H
#define CERTIFICATEINFO_H

#include <memory>
#include <ctime>
#include "goo/GooString.h"

enum CertificateKeyUsageExtension
{
    KU_DIGITAL_SIGNATURE = 0x80,
    KU_NON_REPUDIATION = 0x40,
    KU_KEY_ENCIPHERMENT = 0x20,
    KU_DATA_ENCIPHERMENT = 0x10,
    KU_KEY_AGREEMENT = 0x08,
    KU_KEY_CERT_SIGN = 0x04,
    KU_CRL_SIGN = 0x02,
    KU_ENCIPHER_ONLY = 0x01,
    KU_NONE = 0x00
};

enum PublicKeyType
{
    RSAKEY,
    DSAKEY,
    ECKEY,
    OTHERKEY
};

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

    X509CertificateInfo(const X509CertificateInfo &) = delete;
    X509CertificateInfo &operator=(const X509CertificateInfo &) = delete;

    struct PublicKeyInfo
    {
        PublicKeyInfo();

        PublicKeyInfo(PublicKeyInfo &&) noexcept;
        PublicKeyInfo &operator=(PublicKeyInfo &&) noexcept;

        PublicKeyInfo(const PublicKeyInfo &) = delete;
        PublicKeyInfo &operator=(const PublicKeyInfo &) = delete;

        GooString publicKey;
        PublicKeyType publicKeyType;
        unsigned int publicKeyStrength; // in bits
    };

    struct EntityInfo
    {
        EntityInfo();
        ~EntityInfo();

        EntityInfo(EntityInfo &&) noexcept;
        EntityInfo &operator=(EntityInfo &&) noexcept;

        EntityInfo(const EntityInfo &) = delete;
        EntityInfo &operator=(const EntityInfo &) = delete;

        std::string commonName;
        std::string distinguishedName;
        std::string email;
        std::string organization;
    };

    struct Validity
    {
        Validity() : notBefore(0), notAfter(0) { }

        time_t notBefore;
        time_t notAfter;
    };

    /* GETTERS */
    int getVersion() const;
    const GooString &getSerialNumber() const;
    const GooString &getNickName() const;
    const EntityInfo &getIssuerInfo() const;
    const Validity &getValidity() const;
    const EntityInfo &getSubjectInfo() const;
    const PublicKeyInfo &getPublicKeyInfo() const;
    unsigned int getKeyUsageExtensions() const;
    const GooString &getCertificateDER() const;
    bool getIsSelfSigned() const;

    /* SETTERS */
    void setVersion(int);
    void setSerialNumber(const GooString &);
    void setNickName(const GooString &);
    void setIssuerInfo(EntityInfo &&);
    void setValidity(Validity);
    void setSubjectInfo(EntityInfo &&);
    void setPublicKeyInfo(PublicKeyInfo &&);
    void setKeyUsageExtensions(unsigned int);
    void setCertificateDER(const GooString &);
    void setIsSelfSigned(bool);

private:
    EntityInfo issuer_info;
    EntityInfo subject_info;
    PublicKeyInfo public_key_info;
    Validity cert_validity;
    GooString cert_serial;
    GooString cert_der;
    GooString cert_nick;
    unsigned int ku_extensions;
    int cert_version;
    bool is_self_signed;
};

#endif
