#pragma once

#include <cdefs.h>
#include <cheriot-atomic.hh>
#include <debug.hh>
#include <errno.h>
#include <futex.h>
#include <locks.h>
#include <thread.h>

static constexpr bool DebugLocks =
#ifdef DEBUG_LOCKS
  DEBUG_LOCKS
#else
  false
#endif
  ;
using LockDebug = ConditionalDebug<DebugLocks, "Locking">;

__clang_ignored_warning_push("-Watomic-alignment");

/**
 * A simple flag log, wrapping an atomic word used with the `futex` calls.
 * Threads blocked on this will be woken in priority order. If
 * `IsPriorityInherited` is set, priority is inherited by waiters to avoid
 * priority inversion issues.
 *
 * The lock word that this wraps is directly accessibly by any malicious
 * compartment that has a reference to this thread.  If this is a security
 * concern then you may have other problems: a malicious compartment with
 * access to a mutex's interface (irrespective of the underlying
 * implementation) can cause deadlock by spuriously acquiring a lock or cause
 * data corruption via races by spuriously releasing it.  Anything that
 * requires mutual exclusion in the presence of mutual distrust should
 * consider an using a lock manager compartment with an API that returns a
 * single-use capability to unlock on any lock call.
 */
template<bool IsPriorityInherited>
class FlagLockGeneric
{
	FlagLockState state;

	public:
	/**
	 * Attempt to acquire the lock, blocking until a timeout specified by the
	 * `timeout` parameter has expired.
	 */
	__always_inline bool try_lock(Timeout *timeout)
	{
		if constexpr (IsPriorityInherited)
		{
			return flaglock_priority_inheriting_trylock(timeout, &state) == 0;
		}
		else
		{
			return flaglock_trylock(timeout, &state) == 0;
		}
	}

	/**
	 * Try to acquire the lock, do not block.
	 */
	__always_inline bool try_lock()
	{
		Timeout t{0};
		return try_lock(&t);
	}

	/**
	 * Acquire the lock, potentially blocking forever.
	 */
	__always_inline void lock()
	{
		Timeout t{UnlimitedTimeout};
		try_lock(&t);
	}

	/**
	 * Release the lock.
	 *
	 * Note: This does not check that the lock is owned by the calling thread.
	 */
	__always_inline void unlock()
	{
		flaglock_unlock(&state);
	}

	/**
	 * Set the lock in destruction mode. See the documentation of
	 * `flaglock_upgrade_for_destruction` for more information.
	 */
	__always_inline void upgrade_for_destruction()
	{
		flaglock_upgrade_for_destruction(&state);
	}
};

/**
 * Priority-inheriting recursive mutex.  This can be acquired multiple times
 * from the same thread.
 */
class RecursiveMutex
{
	/// State for the underling recursive mutex.
	RecursiveMutexState state;

	public:
	/**
	 * Attempt to acquire the lock, blocking until a timeout specified by the
	 * `timeout` parameter has expired.
	 */
	__always_inline bool try_lock(Timeout *timeout)
	{
		return recursivemutex_trylock(timeout, &state) == 0;
	}

	/**
	 * Try to acquire the lock, do not block.
	 */
	__always_inline bool try_lock()
	{
		Timeout t{0};
		return try_lock(&t);
	}

	/**
	 * Acquire the lock, potentially blocking forever.
	 */
	__always_inline void lock()
	{
		Timeout t{UnlimitedTimeout};
		try_lock(&t);
	}

	/**
	 * Release the lock.
	 *
	 * Note: This does not check that the lock is owned by the calling thread.
	 */
	__always_inline void unlock()
	{
		recursivemutex_unlock(&state);
	}

	/**
	 * Set the lock in destruction mode. See the documentation of
	 * `flaglock_upgrade_for_destruction` for more information.
	 */
	__always_inline void upgrade_for_destruction()
	{
		flaglock_upgrade_for_destruction(&state.lock);
	}
};

/**
 * A simple ticket lock.
 *
 * A ticket lock ensures that threads that arrive are serviced in order,
 * without regard for priorities.  It has no mechanism for tracking tickets
 * that are discarded and so does not implement a `try_lock` API.
 */
class TicketLock
{
	TicketLockState state;

	public:
	/**
	 * Acquire the lock.
	 */
	__always_inline void lock()
	{
		ticketlock_lock(&state);
	}

	/**
	 * Release the lock.
	 *
	 * Note: This does not check that the lock is owned by the calling thread.
	 */
	__always_inline void unlock()
	{
		ticketlock_unlock(&state);
	}
};

/**
 * Class that implements the locking concept but does not perform locking.
 * This is intended to be used with templated data structures that support
 * locking, for instantiations that do not require locking.
 */
class NoLock
{
	public:
	/**
	 * Attempt to acquire the lock with a timeout.  Always succeeds.
	 */
	bool try_lock(Timeout *timeout)
	{
		return true;
	}

	/**
	 * Try to acquire the lock, do not block.  Always succeeds.
	 */
	bool try_lock()
	{
		return true;
	}

	/**
	 * Acquire the lock.  Always succeeds
	 */
	void lock() {}

	/**
	 * Release the lock.  Does nothing.
	 */
	void unlock() {}
};

using FlagLock                  = FlagLockGeneric<false>;
using FlagLockPriorityInherited = FlagLockGeneric<true>;

template<typename T>
concept Lockable = requires(T l)
{
	{l.lock()};
	{l.unlock()};
};

template<typename T>
concept TryLockable = Lockable<T> && requires(T l, Timeout *t)
{
	{
		l.try_lock(t)
		} -> std::same_as<bool>;
};

static_assert(TryLockable<NoLock>);
static_assert(TryLockable<FlagLock>);
static_assert(TryLockable<FlagLockPriorityInherited>);
static_assert(Lockable<TicketLock>);

/**
 * A simple RAII type that owns a lock.
 */
template<typename Lock>
class LockGuard
{
	/// A reference to the managed lock
	Lock *wrappedLock;

	/// Flag indicating whether the lock is owned.
	bool isOwned;

	public:
	/// Constructor, acquires the lock.
	[[nodiscard]] explicit LockGuard(Lock &lock)
	  : wrappedLock(&lock), isOwned(true)
	{
		wrappedLock->lock();
	}

	/// Constructor, attempts to acquire the lock with a timeout.
	[[nodiscard]] explicit LockGuard(Lock &lock, Timeout *timeout) requires(
	  TryLockable<Lock>)
	  : wrappedLock(&lock), isOwned(false)
	{
		try_lock(timeout);
	}

	/// Move constructor, transfers ownership of the lock.
	[[nodiscard]] explicit LockGuard(LockGuard &&guard)
	  : wrappedLock(guard.wrappedLock), isOwned(guard.isOwned)
	{
		guard.wrappedLock = nullptr;
		guard.isOwned     = false;
	}

	/**
	 * Explicitly lock the wrapped lock. Must be called with the lock unlocked.
	 */
	void lock()
	{
		LockDebug::Assert(!isOwned, "Trying to lock an already-locked lock");
		wrappedLock->lock();
		isOwned = true;
	}

	/**
	 * Explicitly lock the wrapped lock. Must be called with the lock locked by
	 * this wrapper.
	 */
	void unlock()
	{
		LockDebug::Assert(isOwned, "Trying to unlock an unlocked lock");
		wrappedLock->unlock();
		isOwned = false;
	}

	/**
	 * Unwrap the lock without unlocking it. This is useful to call before
	 * destroying a lock.
	 */
	void release()
	{
		wrappedLock = nullptr;
		isOwned     = false;
	}

	/**
	 * If the underlying lock type supports locking with a timeout, try to lock
	 * it with the specified timeout. This must be called with the lock
	 * unlocked.  Returns true if the lock has been acquired, false otherwise.
	 */
	bool try_lock(Timeout *timeout) requires(TryLockable<Lock>)
	{
		LockDebug::Assert(!isOwned, "Trying to lock an already-locked lock");
		isOwned = wrappedLock->try_lock(timeout);
		return isOwned;
	}

	/// Destructor, releases the lock.
	~LockGuard()
	{
		if (isOwned)
		{
			wrappedLock->unlock();
		}
	}

	/**
	 * Conversion to bool.  Returns true if this guard owns the lock, false
	 * otherwise.  This allows lock guards to be used with a timeout in
	 * conditional blocks, such as:
	 *
	 * ```
	 * if (LockGuard g{lock, timeout})
	 * {
	 *    // Run this code if we acquired the lock, releasing the lock at the
	 * end.
	 * }
	 * else
	 * {
	 *    // Run this code if we did not acquire the lock.
	 * }
	 * ```
	 */
	operator bool()
	{
		return isOwned;
	}
};

__clang_ignored_warning_pop();
