#ifndef HOSTS_SUBSCRIBER_H
#define HOSTS_SUBSCRIBER_H

#include <cstdint>
#include <memory>
#include "core/host.h"
#include "core/simulator.h"
#include "hosts/mgmt_msg.h"
#include "hosts/policies.h"

namespace dofs {

class Publisher;

class Subscriber final : public Host {
public:
        Subscriber(Simulator* sim,
                   NodeId id,
                   Publisher* publisher,
                   std::unique_ptr<SubBasePolicy> policy,
                   Time mgmt_latency,
                   Time heartbeat_period) noexcept;

        // Mgmt-plane receive (from publisher)
        virtual void recv_mgmt_msg(MgmtMsgPtr msg) noexcept override;

        // Host overrides (data-plane callbacks)
        void recv_flow(NodeId src, FlowId flow, FlowPriority prio,
                       Bytes flow_size) override;
        void recv_frame(const Packet& frame) override;

        void set_status(NodeStatus s) noexcept;

        // For future: swap publisher pointer
        void set_publisher(Publisher* p) noexcept {
                _publisher = p;
        }

private:
        enum class State : uint8_t { Idle = 0, Processing = 1, Quiesced = 2 };

        void schedule_next_heartbeat(Time delay) noexcept;
        void on_heartbeat_timer() noexcept;
        void send_job_finished(FlowId flow) noexcept;

private:
        Simulator                    *_sim;
        Publisher                    *_publisher;
        std::unique_ptr<SubBasePolicy> _policy;
        Time                          _mgmt_latency;
        Time                          _hb_period;
        EventId                       _hb_evt{NULL_EVENT};
        State                         _state{State::Idle};

        // simple token generator for completions (since FlowId not surfaced here)
        uint64_t                      _next_token{1};
};

} // namespace dofs

#endif // HOSTS_SUBSCRIBER_H
