#pragma once
#include <drogon/nosql/RedisClient.h>
#include <list>
#include <atomic>
#include <mutex>
#include <utility>
namespace drogon::nosql
{
class SubscribeContext
{
  public:
    static std::shared_ptr<SubscribeContext> newContext(
        std::weak_ptr<RedisSubscriber> &&weakSub,
        const std::string &channel,
        bool isPattern = false)
    {
        return std::shared_ptr<SubscribeContext>(
            new SubscribeContext(std::move(weakSub), channel, isPattern));
    }
    unsigned long long contextId() const
    {
        return contextId_;
    }
    const std::string &channel() const
    {
        return channel_;
    }
    const std::string &subscribeCommand() const
    {
        return subscribeCommand_;
    }
    const std::string &unsubscribeCommand() const
    {
        return unsubscribeCommand_;
    }
    void addMessageCallback(RedisMessageCallback &&messageCallback)
    {
        std::lock_guard<std::mutex> lock(mutex_);
        messageCallbacks_.emplace_back(std::move(messageCallback));
    }
    void disable()
    {
        std::lock_guard<std::mutex> lock(mutex_);
        disabled_ = true;
        messageCallbacks_.clear();
    }
    void clear()
    {
        std::lock_guard<std::mutex> lock(mutex_);
        messageCallbacks_.clear();
    }
    void onMessage(const std::string &channel, const std::string &message);
    void onSubscribe(const std::string &channel, long long numChannels);
    void onUnsubscribe(const std::string &channel, long long numChannels);
    bool alive() const
    {
        return !disabled_ && weakSub_.lock() != nullptr;
    }
  private:
    SubscribeContext(std::weak_ptr<RedisSubscriber> &&weakSub,
                     const std::string &channel,
                     bool isPattern);
    static std::atomic<unsigned long long> maxContextId_;
    unsigned long long contextId_;
    std::weak_ptr<RedisSubscriber> weakSub_;
    std::string channel_;
    bool isPattern_{false};
    std::string subscribeCommand_;
    std::string unsubscribeCommand_;
    std::mutex mutex_;
    std::list<RedisMessageCallback> messageCallbacks_;
    bool disabled_{false};
};
}  