/// Simple DirectMedia Layer
/// Copyright (C) 1997-2025 Sam Lantinga
///
/// This software is provided 'as-is', without any express or implied
/// warranty. In no event will the authors be held liable for any damages
/// arising from the use of this software.
///
/// Permission is granted to anyone to use this software for any purpose,
/// including commercial applications, and to alter it and redistribute it
/// freely, subject to the following restrictions:
///
/// 1. The origin of this software must not be misrepresented; you must not
/// claim that you wrote the original software. If you use this software
/// in a product, an acknowledgment in the product documentation would be
/// appreciated but is not required.
/// 2. Altered source versions must be plainly marked as such, and must not be
/// misrepresented as being the original software.
/// 3. This notice may not be removed or altered from any source distribution.
/// # CategoryTimer
///
/// SDL provides time management functionality. It is useful for dealing with
/// (usually) small durations of time.
///
/// This is not to be confused with _calendar time_ management, which is
/// provided by [CategoryTime](CategoryTime).
///
/// This category covers measuring time elapsed (SDL_GetTicks(),
/// SDL_GetPerformanceCounter()), putting a thread to sleep for a certain
/// amount of time (SDL_Delay(), SDL_DelayNS(), SDL_DelayPrecise()), and firing
/// a callback function after a certain amount of time has elasped
/// (SDL_AddTimer(), etc).
///
/// There are also useful macros to convert between time units, like
/// SDL_SECONDS_TO_NS() and such.
///|
/// Number of milliseconds in a second.
///
/// This is always 1000.
///
/// @since This macro is available since SDL 3.2.0.
pub const SDL_MS_PER_SECOND : Int = 1000
///|
/// Number of microseconds in a second.
///
/// This is always 1000000.
///
/// @since This macro is available since SDL 3.2.0.
pub const SDL_US_PER_SECOND : Int = 1000000
///|
/// Number of nanoseconds in a second.
///
/// This is always 1000000000.
///
/// @since This macro is available since SDL 3.2.0.
pub const SDL_NS_PER_SECOND : Int64 = 1000000000L
///|
/// Number of nanoseconds in a millisecond.
///
/// This is always 1000000.
///
/// @since This macro is available since SDL 3.2.0.
pub const SDL_NS_PER_MS : Int = 1000000
///|
/// Number of nanoseconds in a microsecond.
///
/// This is always 1000.
///
/// @since This macro is available since SDL 3.2.0.
pub const SDL_NS_PER_US : Int = 1000
///|
/// Definition of the timer ID type.
///
/// @since This datatype is available since SDL 3.2.0.
///
/// ```c
/// typedef Uint32 SDL_TimerID;
/// ```
pub type SDL_TimerID = UInt
///|
/// Function prototype for the millisecond timer callback function.
///
/// The callback function is passed the current timer interval and returns the
/// next timer interval, in milliseconds. If the returned value is the same as
/// the one passed in, the periodic alarm continues, otherwise a new alarm is
/// scheduled. If the callback returns 0, the periodic alarm is canceled and
/// will be removed.
///
/// @param userdata an arbitrary pointer provided by the app through
/// SDL_AddTimer, for its own use.
/// @param timerID the current timer being processed.
/// @param interval the current callback time interval.
/// @return the new callback time interval, or 0 to disable further runs of
/// the callback.
///
/// @threadsafety SDL may call this callback at any time from a background
/// thread; the application is responsible for locking resources
/// the callback touches that need to be protected.
///
/// @since This datatype is available since SDL 3.2.0.
///
/// @see SDL_AddTimer
///
/// ```c
/// typedef Uint32 (SDLCALL *SDL_TimerCallback)(void *userdata, SDL_TimerID timerID, Uint32 interval);
/// ```
pub type SDL_TimerCallback = FuncRef[(VoidPtr, SDL_TimerID, UInt) -> UInt]
///|
/// Function prototype for the nanosecond timer callback function.
///
/// The callback function is passed the current timer interval and returns the
/// next timer interval, in nanoseconds. If the returned value is the same as
/// the one passed in, the periodic alarm continues, otherwise a new alarm is
/// scheduled. If the callback returns 0, the periodic alarm is canceled and
/// will be removed.
///
/// @param userdata an arbitrary pointer provided by the app through
/// SDL_AddTimer, for its own use.
/// @param timerID the current timer being processed.
/// @param interval the current callback time interval.
/// @return the new callback time interval, or 0 to disable further runs of
/// the callback.
///
/// @threadsafety SDL may call this callback at any time from a background
/// thread; the application is responsible for locking resources
/// the callback touches that need to be protected.
///
/// @since This datatype is available since SDL 3.2.0.
///
/// @see SDL_AddTimerNS
///
/// ```c
/// typedef Uint64 (SDLCALL *SDL_NSTimerCallback)(void *userdata, SDL_TimerID timerID, Uint64 interval);
/// ```
pub type SDL_NSTimerCallback = FuncRef[(VoidPtr, SDL_TimerID, UInt64) -> UInt64]
///|
/// Get the number of milliseconds that have elapsed since the SDL library
/// initialization.
///
/// @return an unsigned 64‑bit integer that represents the number of
/// milliseconds that have elapsed since the SDL library was
/// initialized (typically via a call to SDL_Init).
///
/// @threadsafety It is safe to call this function from any thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_GetTicksNS
///
/// ```c
/// extern SDL_DECLSPEC Uint64 SDLCALL SDL_GetTicks(void);
/// ```
pub extern "C" fn sdl_GetTicks() -> UInt64 = "SDL_GetTicks"
///|
/// Get the number of nanoseconds since SDL library initialization.
///
/// @return an unsigned 64-bit value representing the number of nanoseconds
/// since the SDL library initialized.
///
/// @threadsafety It is safe to call this function from any thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// ```c
/// extern SDL_DECLSPEC Uint64 SDLCALL SDL_GetTicksNS(void);
/// ```
pub extern "C" fn sdl_GetTicksNS() -> UInt64 = "SDL_GetTicksNS"
///|
/// Get the current value of the high resolution counter.
///
/// This function is typically used for profiling.
///
/// The counter values are only meaningful relative to each other. Differences
/// between values can be converted to times by using
/// SDL_GetPerformanceFrequency().
///
/// @return the current counter value.
///
/// @threadsafety It is safe to call this function from any thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_GetPerformanceFrequency
///
/// ```c
/// extern SDL_DECLSPEC Uint64 SDLCALL SDL_GetPerformanceCounter(void);
/// ```
pub extern "C" fn sdl_GetPerformanceCounter() -> UInt64 = "SDL_GetPerformanceCounter"
///|
/// Get the count per second of the high resolution counter.
///
/// @return a platform-specific count per second.
///
/// @threadsafety It is safe to call this function from any thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_GetPerformanceCounter
///
/// ```c
/// extern SDL_DECLSPEC Uint64 SDLCALL SDL_GetPerformanceFrequency(void);
/// ```
pub extern "C" fn sdl_GetPerformanceFrequency() -> UInt64 = "SDL_GetPerformanceFrequency"
///|
/// Wait a specified number of milliseconds before returning.
///
/// This function waits a specified number of milliseconds before returning. It
/// waits at least the specified time, but possibly longer due to OS
/// scheduling.
///
/// @param ms the number of milliseconds to delay.
///
/// @threadsafety It is safe to call this function from any thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_DelayNS
/// @see SDL_DelayPrecise
///
/// ```c
/// extern SDL_DECLSPEC void SDLCALL SDL_Delay(Uint32 ms);
/// ```
pub extern "C" fn sdl_Delay(ms : UInt) -> Unit = "SDL_Delay"
///|
/// Wait a specified number of nanoseconds before returning.
///
/// This function waits a specified number of nanoseconds before returning. It
/// waits at least the specified time, but possibly longer due to OS
/// scheduling.
///
/// @param ns the number of nanoseconds to delay.
///
/// @threadsafety It is safe to call this function from any thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_Delay
/// @see SDL_DelayPrecise
///
/// ```c
/// extern SDL_DECLSPEC void SDLCALL SDL_DelayNS(Uint64 ns);
/// ```
pub extern "C" fn sdl_DelayNS(ns : UInt64) -> Unit = "SDL_DelayNS"
///|
/// Wait a specified number of nanoseconds before returning.
///
/// This function waits a specified number of nanoseconds before returning. It
/// will attempt to wait as close to the requested time as possible, busy
/// waiting if necessary, but could return later due to OS scheduling.
///
/// @param ns the number of nanoseconds to delay.
///
/// @threadsafety It is safe to call this function from any thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_Delay
/// @see SDL_DelayNS
///
/// ```c
/// extern SDL_DECLSPEC void SDLCALL SDL_DelayPrecise(Uint64 ns);
/// ```
pub extern "C" fn sdl_DelayPrecise(ns : UInt64) -> Unit = "SDL_DelayPrecise"
///|
/// Call a callback function at a future time.
///
/// The callback function is passed the current timer interval and the user
/// supplied parameter from the SDL_AddTimer() call and should return the next
/// timer interval. If the value returned from the callback is 0, the timer is
/// canceled and will be removed.
///
/// The callback is run on a separate thread, and for short timeouts can
/// potentially be called before this function returns.
///
/// Timers take into account the amount of time it took to execute the
/// callback. For example, if the callback took 250 ms to execute and returned
/// 1000 (ms), the timer would only wait another 750 ms before its next
/// iteration.
///
/// Timing may be inexact due to OS scheduling. Be sure to note the current
/// time with SDL_GetTicksNS() or SDL_GetPerformanceCounter() in case your
/// callback needs to adjust for variances.
///
/// @param interval the timer delay, in milliseconds, passed to `callback`.
/// @param callback the SDL_TimerCallback function to call when the specified
/// `interval` elapses.
/// @param userdata a pointer that is passed to `callback`.
/// @return a timer ID or 0 on failure; call SDL_GetError() for more
/// information.
///
/// @threadsafety It is safe to call this function from any thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_AddTimerNS
/// @see SDL_RemoveTimer
///
/// ```c
/// extern SDL_DECLSPEC SDL_TimerID SDLCALL SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *userdata);
/// ```
pub extern "C" fn sdl_AddTimer(
interval : UInt,
callback : SDL_TimerCallback,
userdata : VoidPtr,
) -> SDL_TimerID = "SDL_AddTimer"
///|
/// Call a callback function at a future time.
///
/// The callback function is passed the current timer interval and the user
/// supplied parameter from the SDL_AddTimerNS() call and should return the
/// next timer interval. If the value returned from the callback is 0, the
/// timer is canceled and will be removed.
///
/// The callback is run on a separate thread, and for short timeouts can
/// potentially be called before this function returns.
///
/// Timers take into account the amount of time it took to execute the
/// callback. For example, if the callback took 250 ns to execute and returned
/// 1000 (ns), the timer would only wait another 750 ns before its next
/// iteration.
///
/// Timing may be inexact due to OS scheduling. Be sure to note the current
/// time with SDL_GetTicksNS() or SDL_GetPerformanceCounter() in case your
/// callback needs to adjust for variances.
///
/// @param interval the timer delay, in nanoseconds, passed to `callback`.
/// @param callback the SDL_TimerCallback function to call when the specified
/// `interval` elapses.
/// @param userdata a pointer that is passed to `callback`.
/// @return a timer ID or 0 on failure; call SDL_GetError() for more
/// information.
///
/// @threadsafety It is safe to call this function from any thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_AddTimer
/// @see SDL_RemoveTimer
///
/// ```c
/// extern SDL_DECLSPEC SDL_TimerID SDLCALL SDL_AddTimerNS(Uint64 interval, SDL_NSTimerCallback callback, void *userdata);
/// ```
pub extern "C" fn sdl_AddTimerNS(
interval : UInt64,
callback : SDL_NSTimerCallback,
userdata : VoidPtr,
) -> SDL_TimerID = "SDL_AddTimerNS"
///|
/// Remove a timer created with SDL_AddTimer().
///
/// @param id the ID of the timer to remove.
/// @return true on success or false on failure; call SDL_GetError() for more
/// information.
///
/// @threadsafety It is safe to call this function from any thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_AddTimer
///
/// ```c
/// extern SDL_DECLSPEC bool SDLCALL SDL_RemoveTimer(SDL_TimerID id);
/// ```
pub extern "C" fn sdl_RemoveTimer(id : SDL_TimerID) -> Bool = "SDL_RemoveTimer"