// SPDX-License-Identifier: Apache-2.0

#pragma once

#include <assert.h>
#include <stdbool.h>

#include <tactility/freertos/semphr.h>
#include <tactility/check.h>

#ifdef __cplusplus
extern "C" {
#endif

struct Mutex {
    QueueHandle_t handle;
    // TODO: Debugging functionality
};

inline static void mutex_construct(struct Mutex* mutex) {
    mutex->handle = xSemaphoreCreateMutex();
}

inline static void mutex_destruct(struct Mutex* mutex) {
    vPortAssertIfInISR();
    vSemaphoreDelete(mutex->handle);
    mutex->handle = NULL;
}

inline static void mutex_lock(struct Mutex* mutex) {
    check(xPortInIsrContext() != pdTRUE);
    xSemaphoreTake(mutex->handle, portMAX_DELAY);
}

inline static bool mutex_try_lock(struct Mutex* mutex, TickType_t timeout) {
    check(xPortInIsrContext() != pdTRUE);
    return xSemaphoreTake(mutex->handle, timeout) == pdTRUE;
}

inline static bool mutex_is_locked(struct Mutex* mutex) {
    if (xPortInIsrContext() == pdTRUE) {
        return xSemaphoreGetMutexHolderFromISR(mutex->handle) != NULL;
    } else {
        return xSemaphoreGetMutexHolder(mutex->handle) != NULL;
    }
}

inline static void mutex_unlock(struct Mutex* mutex) {
    check(xPortInIsrContext() != pdTRUE);
    xSemaphoreGive(mutex->handle);
}

#ifdef __cplusplus
}
#endif
