#pragma once
#include <trantor/net/EventLoop.h>
#include <trantor/utils/Logger.h>
#include <trantor/exports.h>
#include <map>
#include <mutex>
#include <deque>
#include <vector>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <atomic>
#include <assert.h>
#define TIMING_BUCKET_NUM_PER_WHEEL 100
#define TIMING_TICK_INTERVAL 1.0
namespace trantor
{
using EntryPtr = std::shared_ptr<void>;
using EntryBucket = std::unordered_set<EntryPtr>;
using BucketQueue = std::deque<EntryBucket>;
class TRANTOR_EXPORT TimingWheel
{
  public:
    class CallbackEntry
    {
      public:
        CallbackEntry(std::function<void()> cb) : cb_(std::move(cb))
        {
        }
        ~CallbackEntry()
        {
            cb_();
        }
      private:
        std::function<void()> cb_;
    };
    TimingWheel(trantor::EventLoop *loop,
                size_t maxTimeout,
                float ticksInterval = TIMING_TICK_INTERVAL,
                size_t bucketsNumPerWheel = TIMING_BUCKET_NUM_PER_WHEEL);
    void insertEntry(size_t delay, EntryPtr entryPtr);
    void insertEntryInloop(size_t delay, EntryPtr entryPtr);
    EventLoop *getLoop()
    {
        return loop_;
    }
    ~TimingWheel();
  private:
    std::vector<BucketQueue> wheels_;
    std::atomic<size_t> ticksCounter_{0};
    trantor::TimerId timerId_;
    trantor::EventLoop *loop_;
    float ticksInterval_;
    size_t wheelsNum_;
    size_t bucketsNumPerWheel_;
};
}  