#pragma once
#include <trantor/exports.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
namespace trantor
{
struct TRANTOR_EXPORT TLSPolicy final
{
    TLSPolicy &setConfCmds(
        const std::vector<std::pair<std::string, std::string>> &sslConfCmds)
    {
        sslConfCmds_ = sslConfCmds;
        return *this;
    }
    TLSPolicy &setHostname(const std::string &hostname)
    {
        hostname_ = hostname;
        return *this;
    }
    TLSPolicy &setCertPath(const std::string &certPath)
    {
        certPath_ = certPath;
        return *this;
    }
    TLSPolicy &setKeyPath(const std::string &keyPath)
    {
        keyPath_ = keyPath;
        return *this;
    }
    TLSPolicy &setCaPath(const std::string &caPath)
    {
        caPath_ = caPath;
        return *this;
    }
    TLSPolicy &setUseOldTLS(bool useOldTLS)
    {
        useOldTLS_ = useOldTLS;
        return *this;
    }
    TLSPolicy &setAlpnProtocols(const std::vector<std::string> &alpnProtocols)
    {
        alpnProtocols_ = alpnProtocols;
        return *this;
    }
    TLSPolicy &setAlpnProtocols(std::vector<std::string> &&alpnProtocols)
    {
        alpnProtocols_ = std::move(alpnProtocols);
        return *this;
    }
    TLSPolicy &setUseSystemCertStore(bool useSystemCertStore)
    {
        useSystemCertStore_ = useSystemCertStore;
        return *this;
    }
    TLSPolicy &setValidate(bool enable)
    {
        validate_ = enable;
        return *this;
    }
    TLSPolicy &setAllowBrokenChain(bool allow)
    {
        allowBrokenChain_ = allow;
        return *this;
    }
    const std::vector<std::pair<std::string, std::string>> &getConfCmds() const
    {
        return sslConfCmds_;
    }
    const std::string &getHostname() const
    {
        return hostname_;
    }
    const std::string &getCertPath() const
    {
        return certPath_;
    }
    const std::string &getKeyPath() const
    {
        return keyPath_;
    }
    const std::string &getCaPath() const
    {
        return caPath_;
    }
    bool getUseOldTLS() const
    {
        return useOldTLS_;
    }
    bool getValidate() const
    {
        return validate_;
    }
    bool getAllowBrokenChain() const
    {
        return allowBrokenChain_;
    }
    const std::vector<std::string> &getAlpnProtocols() const
    {
        return alpnProtocols_;
    }
    const std::vector<std::string> &getAlpnProtocols()
    {
        return alpnProtocols_;
    }
    bool getUseSystemCertStore() const
    {
        return useSystemCertStore_;
    }
    static std::shared_ptr<TLSPolicy> defaultServerPolicy(
        const std::string &certPath,
        const std::string &keyPath)
    {
        auto policy = std::make_shared<TLSPolicy>();
        policy->setValidate(false)
            .setUseOldTLS(false)
            .setUseSystemCertStore(false)
            .setCertPath(certPath)
            .setKeyPath(keyPath);
        return policy;
    }
    static std::shared_ptr<TLSPolicy> defaultClientPolicy(
        const std::string &hostname = "")
    {
        auto policy = std::make_shared<TLSPolicy>();
        policy->setValidate(true)
            .setUseOldTLS(false)
            .setUseSystemCertStore(true)
            .setHostname(hostname);
        return policy;
    }
  protected:
    std::vector<std::pair<std::string, std::string>> sslConfCmds_ = {};
    std::string hostname_ = "";
    std::string certPath_ = "";
    std::string keyPath_ = "";
    std::string caPath_ = "";
    std::vector<std::string> alpnProtocols_ = {};
    bool useOldTLS_ = false;  
    bool validate_ = true;
    bool allowBrokenChain_ = false;
    bool useSystemCertStore_ = true;
};
using TLSPolicyPtr = std::shared_ptr<TLSPolicy>;
}  