#include <atomic>
#include <cstdlib>
#include <errno.h>
#include <event.h>
#include <locks.hh>
#include <stdint.h>
#include <thread.h>

using Debug = ConditionalDebug<false, "Event groups library">;

struct EventWaiter
{
	std::atomic<uint32_t> bitsSeen;
	bool                  waitForAll : 1;
	bool                  clearOnExit : 1;
	unsigned int          bitsWanted : 24;
	bool                  is_triggered(uint32_t bits)
	{
		Debug::log("bits wanted: {}, bits: {}, mask: {}",
		           bitsWanted,
		           bits,
		           (bitsWanted & bits));
		return (waitForAll ? ((bitsWanted & bits) == bitsWanted)
		                   : ((bitsWanted & bits) != 0));
	};
};

struct EventGroup
{
	FlagLock    lock;
	uint32_t    bits;
	size_t      waiterCount;
	EventWaiter waiters[];
};

int eventgroup_create(Timeout     *timeout,
                      SObjStruct  *heapCapability,
                      EventGroup **outGroup)
{
	auto threads = thread_count();
	if (threads == uint16_t(-1))
	{
		return -ERANGE;
	}
	size_t size = sizeof(EventGroup) + (threads * sizeof(EventWaiter));
	auto   group =
	  static_cast<EventGroup *>(heap_allocate(timeout, heapCapability, size));
	*outGroup = group;
	if (!group)
	{
		return -ENOMEM;
	}
	group->waiterCount = threads;
	return 0;
}

int eventgroup_wait(Timeout    *timeout,
                    EventGroup *group,
                    uint32_t   *outBits,
                    uint32_t    bitsWanted,
                    bool        waitForAll,
                    bool        clearOnExit)
{
	// Bits wanted can be only a 24-bit value.
	if (bitsWanted & 0xff000000)
	{
		return -ERANGE;
	}
	// Condition that holds if the bits are triggered.
	auto isTriggered = [&](uint32_t bits) {
		return (waitForAll ? ((bitsWanted & bits) == bitsWanted)
		                   : ((bitsWanted & bits) != 0));
	};
	auto    &waiter = group->waiters[thread_id_get()];
	uint32_t bitsSeen;
	// Set up our state for the waiter with the lock held.
	if (LockGuard g{group->lock, timeout})
	{
		bitsSeen = group->bits;
		// If the condition holds, return immediately
		if (isTriggered(bitsSeen))
		{
			if (clearOnExit)
			{
				group->bits &= ~bitsWanted;
			}
			*outBits = bitsSeen;
			return 0;
		}
		waiter.bitsWanted  = bitsWanted;
		waiter.clearOnExit = clearOnExit;
		waiter.waitForAll  = waitForAll;
		waiter.bitsSeen    = bitsSeen;
	}
	else
	{
		return -ETIMEDOUT;
	}
	// If the condition didn't hold, wait for
	Debug::log("Waiting on futex {} ({})", &waiter.bitsSeen, bitsSeen);
	while (waiter.bitsSeen.wait(timeout, bitsSeen) != -ETIMEDOUT)
	{
		bitsSeen = waiter.bitsSeen.load();
		if (isTriggered(bitsSeen))
		{
			*outBits = bitsSeen;
			return 0;
		}
	};
	waiter.bitsWanted = 0;
	*outBits          = group->bits;
	return -ETIMEDOUT;
}

int eventgroup_clear(Timeout    *timeout,
                     EventGroup *group,
                     uint32_t   *outBits,
                     uint32_t    bitsToClear)
{
	if (LockGuard g{group->lock, timeout})
	{
		Debug::log(
		  "Bits was {}, clearing with mask {}", group->bits, ~bitsToClear);
		group->bits &= ~bitsToClear;
		*outBits = group->bits;
		return 0;
	}
	*outBits = group->bits;
	return -ETIMEDOUT;
}

int eventgroup_set(Timeout    *timeout,
                   EventGroup *group,
                   uint32_t   *outBits,
                   uint32_t    bitsToSet)
{
	if (LockGuard g{group->lock, timeout})
	{
		Debug::log("Bits was {}, setting {}", group->bits, bitsToSet);
		group->bits |= bitsToSet;
		uint32_t bits        = group->bits;
		uint32_t bitsToClear = 0;
		Debug::log("Bits {} are set", bits);
		for (size_t i = 0; i < group->waiterCount; ++i)
		{
			auto &waiter = group->waiters[i];
			Debug::log("Waiter {} wants bits {}", i, waiter.bitsWanted);
			if (waiter.bitsWanted == 0)
			{
				continue;
			}
			Debug::log("Triggered? {}", waiter.is_triggered(bitsToSet));
			if (waiter.is_triggered(bits))
			{
				if (waiter.clearOnExit)
				{
					bitsToClear |= (waiter.bitsWanted & bits);
				}
				waiter.bitsWanted = 0;
				waiter.bitsSeen   = bits;
				Debug::log("Waking futex {} ({})", &waiter.bitsSeen, bits);
				waiter.bitsSeen.notify_one();
			}
		}
		Debug::log("Clearing bits {}", bitsToClear);
		group->bits &= ~bitsToClear;
		*outBits = group->bits;
		return 0;
	}
	*outBits = group->bits;
	return -ETIMEDOUT;
}

int eventgroup_get(EventGroup *group, uint32_t *outBits)
{
	*outBits = group->bits;
	return 0;
}

int eventgroup_destroy(SObjStruct *heapCapability, EventGroup *group)
{
	group->lock.lock();
	// Force all waiters to wake.
	for (size_t i = 0; i < group->waiterCount; ++i)
	{
		auto &waiter = group->waiters[i];
		if (waiter.bitsWanted == 0)
		{
			continue;
		}
		waiter.bitsSeen.notify_one();
	}
	heap_free(heapCapability, group);
	return 0;
}
