#ifndef NETWORK_SWITCH_ECN_SHARED_RED_H
#define NETWORK_SWITCH_ECN_SHARED_RED_H

#include <vector>
#include "network/switch/ecn_engine.h"
#include "network/switch/switch_buffer.h"
#include "core/rng.h"

namespace dofs {

// Dynamic-threshold RED for a shared pool.
// Intuition:
//   - Let active ports = count of ports with non-zero backlog.
//   - Per-port fair share ~ buffer_size / max(1, active).
//   - Class tweak: CTRL lenient, ELE stricter.
//   - min_th = alpha * share; max_th = beta * share; (alpha < beta < 1)
//   - ECN prob grows linearly; above max_th → header trim (not drop).
class SharedREDEngine final : public ECNEngine {
public:
        explicit SharedREDEngine(Rng *const rng = nullptr) noexcept
                : _rng(rng),
                  _avg_total_bytes(0.0),
                  _avg_port_bytes() {}

        virtual Packet &process_packet(Packet &pkt,
                                       SwitchBuffer *buf) noexcept override;

private:
        void ensure_size(uint16_t port_cnt) {
                if (_avg_port_bytes.size() != port_cnt)
                        _avg_port_bytes.assign(port_cnt, 0.0);
        }

        static inline bool is_ctrl(const Packet &p) noexcept {
                return p.priority() == FlowPriority::CTRL;
        }
        static inline bool is_mice(const Packet &p) noexcept {
                return p.priority() == FlowPriority::MICE;
        }
        static inline bool is_ele (const Packet &p) noexcept {
                return p.priority() == FlowPriority::ELEPHANT;
        }

        double ewma(double cur, double avg) const noexcept {
                constexpr double W = 0.125; // same 1/8 smoothing
                return (1.0 - W) * avg + W * cur;
        }

        struct Thresholds {
                double min_th;
                double max_th;
                double p_max; // cap for ECN probability
                bool   allow_trim; // whether we ever trim this class
        };

        // Compute dynamic thresholds from shared state and class.
        Thresholds dynamic_thresholds(const Packet &pkt,
                                      const SwitchBuffer *buf,
                                      double total_bytes_avg) const;

private:
        Rng *const _rng;

        // EWMA of total bytes (shared pool) and per-port bytes
        double _avg_total_bytes;
        std::vector<double> _avg_port_bytes;
};

} // namespace dofs

#endif // NETWORK_SWITCH_ECN_SHARED_RED_H
