#pragma once
#include <array>
#include <atomic>
#include <cstdint>

// One producer (UI owner), one consumer (input sender). Never wait on the
// socket from the GPIO polling task, and never replay telemetry after reconnect.
class UiButtonOutbox {
public:
    struct Event { char button; uint32_t generation; uint64_t timestamp_ms; };
    static constexpr unsigned capacity=8;
    static constexpr uint64_t max_age_ms=2000;
    bool push(char button,uint32_t generation,uint64_t now) {
        const auto head=head_.load(std::memory_order_relaxed);
        const auto next=(head+1)%(capacity+1);
        if(next==tail_.load(std::memory_order_acquire))return false;
        events_[head]={button,generation,now};
        head_.store(next,std::memory_order_release);return true;
    }
    bool pop_current(Event& event,uint32_t generation,bool ready,uint64_t now) {
        auto tail=tail_.load(std::memory_order_relaxed);
        while(tail!=head_.load(std::memory_order_acquire)) {
            event=events_[tail];tail=(tail+1)%(capacity+1);
            tail_.store(tail,std::memory_order_release);
            if(ready && event.generation==generation && now>=event.timestamp_ms &&
               now-event.timestamp_ms<=max_age_ms)return true;
        }
        return false;
    }
private:
    std::array<Event,capacity+1> events_{};
    std::atomic<unsigned> head_{0},tail_{0};
};
