#ifndef INCLUDED_BOBCAT_SYMCRYPTSTREAMBUFBASE_
#define INCLUDED_BOBCAT_SYMCRYPTSTREAMBUFBASE_

#include <memory>
#include <iosfwd>
#include <string>

#include <openssl/evp.h>

#include <bobcat/ifilterbuf>

namespace FBB
{

namespace IUO   // the facilities defined here are not further documented
{               // elsewhere. The SymCryptStreambufBase class defined below 
                // should only be used by ISymCryptStreambuf.


class SymCryptStreambufBase: public FBB::IFilterBuf
{
    EVP_CIPHER_CTX *d_ctx;

    size_t d_inBufSize;
    size_t d_blockSize;
    size_t d_outBufSize = 0;
    bool d_allDone = false;

    std::istream &d_in;
    
    int (*d_evpUpdate)(EVP_CIPHER_CTX *ctx, 
                unsigned char *out, int *outl, 
                unsigned char const *in, int inl);

    int (*d_evpFinal)(EVP_CIPHER_CTX *, unsigned char *out, int *outl);

    std::unique_ptr<char, void (*)(char *)> d_inBuf;
    std::unique_ptr<char, void (*)(char *)> d_outBuf;
    
    std::string d_cipherName;

    public:
        SymCryptStreambufBase(
            int (*evpInit)(EVP_CIPHER_CTX *ctx, EVP_CIPHER const *type,
                unsigned char const *key, unsigned char const *iv,
                OSSL_PARAM const *params),

            int (*evpUpdate)(EVP_CIPHER_CTX *ctx, unsigned char *out,
                int *outl, unsigned char const *in, int inl),

            int (*evpFinal)(EVP_CIPHER_CTX *ctx, unsigned char *out,
                int *outl),

            std::istream &in,       
            char const *cipherName,
            std::string const &key, 
            std::string const &iv,
            size_t bufSize,         
            size_t filterBufSize,
            OSSL_PARAM const *params
        );

        ~SymCryptStreambufBase() override;        

    private:
        void checkOutBufSize(size_t inputSize);
        static void deleter(char *ptr); // used for d_inBuf/d_outBuf

        bool filter(char const **srcBegin, char const **srcEnd) override;
        void lengthCheck(char const *what, size_t required, size_t actual);

};

}   // IUO

}   // FBB

#endif

