#pragma once

#include <cstdint>
#include <mutex>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>

#include "flags_iface.hpp"

class SharedFlags : public FlagsIface {
public:
    SharedFlags() : flags_{0} {
    }

    virtual void set_flag(uint32_t mask) override {
        {
            std::lock_guard guard(mutex_);
            flags_ |= mask;
        }
        /// Уведомляем об изменении флага
        flag_cond_.notify_all();
    }

   virtual uint32_t get_flag(uint32_t mask) override {
        uint32_t out;
        {
            std::lock_guard guard(mutex_);
            out = flags_ & mask;
        }
        return out;
    }

    virtual uint32_t get_flags() override{
        uint32_t out;
        {
            std::lock_guard guard(mutex_);
            out = flags_;
        }

        return out;
    }

    virtual void clear_flags(uint32_t mask) override
    {
       std::lock_guard guard(mutex_);
       flags_ &= ~mask;
    }
    
    virtual uint32_t wait_flags(uint32_t mask) override
    {
        boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(mutex_wait_);
        flag_cond_.wait(lock); //Ожидаем изменения данных
        /// Данные изменились
        uint32_t out;
        {
            std::lock_guard guard(mutex_);
            out = flags_ & mask;
        }
        return out;
    }
private:
    uint32_t flags_;
    boost::interprocess::interprocess_mutex mutex_;
    boost::interprocess::interprocess_mutex mutex_wait_;
    boost::interprocess::interprocess_condition  flag_cond_;
};