#ifndef ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_NODE_H_
#define ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_NODE_H_

#include <android/hardware_buffer.h>
#include <bufferhub/BufferHubIdGenerator.h>
#include <cutils/native_handle.h>
#include <ui/BufferHubEventFd.h>
#include <ui/BufferHubMetadata.h>

namespace android {
namespace frameworks {
namespace bufferhub {
namespace V1_0 {
namespace implementation {

class BufferNode {
public:
    // Allocates a new BufferNode.
    BufferNode(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format,
               uint64_t usage, size_t userMetadataSize, int id = -1);

    ~BufferNode();

    // Returns whether the object holds a valid metadata.
    bool isValid() const { return mMetadata.isValid(); }

    int id() const { return mId; }

    size_t userMetadataSize() const { return mMetadata.userMetadataSize(); }

    // Accessors of the buffer description and handle
    const native_handle_t* bufferHandle() const { return mBufferHandle; }
    const AHardwareBuffer_Desc& bufferDesc() const { return mBufferDesc; }

    // Accessor of event fd.
    const BufferHubEventFd& eventFd() const { return mEventFd; }

    // Accessors of mMetadata.
    const BufferHubMetadata& metadata() const { return mMetadata; }

    // Gets the current value of mActiveClientsBitMask in mMetadata with
    // std::memory_order_acquire, so that all previous releases of
    // mActiveClientsBitMask from all threads will be returned here.
    uint32_t getActiveClientsBitMask() const;

    // Find and add a new client state mask to mActiveClientsBitMask in
    // mMetadata.
    // Return the new client state mask that is added to mActiveClientsBitMask.
    // Return 0U if there are already 16 clients of the buffer.
    uint32_t addNewActiveClientsBitToMask();

    // Removes the value from active_clients_bit_mask in mMetadata with
    // std::memory_order_release, so that the change will be visible to any
    // acquire of mActiveClientsBitMask in any threads after the succeed of
    // this operation.
    void removeClientsBitFromMask(const uint32_t& value);

private:
    // Helper method for constructors to initialize atomic metadata header
    // variables in shared memory.
    void initializeMetadata();

    // Gralloc buffer handles.
    native_handle_t* mBufferHandle;
    AHardwareBuffer_Desc mBufferDesc;

    // Eventfd used for signalling buffer events among the clients of the buffer.
    BufferHubEventFd mEventFd;

    // Metadata in shared memory.
    BufferHubMetadata mMetadata;

    // A system-unique id generated by bufferhub from 0 to std::numeric_limits<int>::max().
    // BufferNodes not created by bufferhub will have id < 0, meaning "not specified".
    // TODO(b/118891412): remove default id = -1 and update comments after pdx is no longer in use
    const int mId = -1;

    // The following variables are atomic variables in mMetadata that are visible
    // to Bn object and Bp objects. Please find more info in
    // BufferHubDefs::MetadataHeader.

    // mBufferState tracks the state of the buffer. Buffer can be in one of these
    // four states: gained, posted, acquired, released.
    std::atomic<uint32_t>* mBufferState = nullptr;

    // TODO(b/112012161): add comments to mFenceState.
    std::atomic<uint32_t>* mFenceState = nullptr;

    // mActiveClientsBitMask tracks all the bp clients of the buffer. It is the
    // union of all client_state_mask of all bp clients.
    std::atomic<uint32_t>* mActiveClientsBitMask = nullptr;
};

} // namespace implementation
} // namespace V1_0
} // namespace bufferhub
} // namespace frameworks
} // namespace android

#endif // ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_NODE_H_
