#pragma once
#include <trantor/utils/Logger.h>
#include <map>
#include <memory>
#include <any>
namespace drogon
{
class Attributes
{
  public:
    template <typename T>
    const T &get(const std::string &key) const
    {
        static const T nullVal = T();
        auto it = attributesMap_.find(key);
        if (it != attributesMap_.end())
        {
            if (typeid(T) == it->second.type())
            {
                return *(std::any_cast<T>(&(it->second)));
            }
            else
            {
                LOG_ERROR << "Bad type";
            }
        }
        return nullVal;
    }
    std::any &operator[](const std::string &key)
    {
        return attributesMap_[key];
    }
    void insert(const std::string &key, const std::any &obj)
    {
        attributesMap_[key] = obj;
    }
    void insert(const std::string &key, std::any &&obj)
    {
        attributesMap_[key] = std::move(obj);
    }
    void erase(const std::string &key)
    {
        attributesMap_.erase(key);
    }
    bool find(const std::string &key)
    {
        if (attributesMap_.find(key) == attributesMap_.end())
        {
            return false;
        }
        return true;
    }
    void clear()
    {
        attributesMap_.clear();
    }
    Attributes() = default;
  private:
    using AttributesMap = std::map<std::string, std::any>;
    AttributesMap attributesMap_;
};
using AttributesPtr = std::shared_ptr<Attributes>;
}  