#ifndef _TIME_H
#define _TIME_H

#ifdef __cplusplus
extern "C" {
#endif

typedef long          time_t;
typedef unsigned long clock_t;
typedef unsigned long size_t;

#ifndef NULL
# define NULL ((void *)0)
#endif

#define CLOCKS_PER_SEC 60   // IIgs vsync tick (placeholder)

// C11 / POSIX nanosecond-precision time.  IIgs has only second-level
// hardware resolution; tv_nsec is reported as 0 by callers that fill
// a struct timespec.  Defined here so <threads.h> can refer to it.
struct timespec {
    time_t tv_sec;
    long   tv_nsec;
};

struct tm {
    int tm_sec;        // 0..60 (60 = leap second)
    int tm_min;        // 0..59
    int tm_hour;       // 0..23
    int tm_mday;       // 1..31
    int tm_mon;        // 0..11 (Jan=0)
    int tm_year;       // years since 1900
    int tm_wday;       // 0..6 (Sun=0)
    int tm_yday;       // 0..365 (Jan 1 = 0)
    int tm_isdst;      // > 0 = DST in effect, 0 = not, < 0 = unknown
};

time_t  time(time_t *t);
clock_t clock(void);
double  difftime(time_t end, time_t start);

// Calendar conversions. gmtime and localtime are identical here —
// no timezone support; "local" is treated as UTC.
//
// ⚠ gmtime/localtime are KNOWN-BROKEN under the GS/OS Loader.  The
// interface returns a pointer to a static global; user code reads
// `r->tm_field` via [dp],Y bank=0 but the global lives in the user's
// bank (cRELOC patches its IMM16 reference for the user bank, not
// bank 0).  Use gmtime_r / localtime_r below — they take a caller-
// supplied buffer (a stack local works) which is reachable
// consistently in either environment.
//
// Under runInMame (DBR=0) plain gmtime/localtime work for sec/min/hour
// only; date fields stay at the 1970-01-01 sentinel.
struct tm *gmtime   (const time_t *t);
struct tm *localtime(const time_t *t);
struct tm *gmtime_r   (const time_t *t, struct tm *out);
struct tm *localtime_r(const time_t *t, struct tm *out);
time_t     mktime   (struct tm *tm);

// Text formatting. asctime returns "Sun Jan  1 00:00:00 1970\n" form.
// Both functions return a pointer to a static buffer (overwritten on
// each call — not thread-safe).
char *asctime(const struct tm *tm);
char *ctime  (const time_t *t);

// strftime: format `tm` per `fmt` into `buf` (max `n` bytes incl.
// terminator). Supports a useful subset: %Y %m %d %H %M %S %j %w %a
// %A %b %B %p %% — sufficient for log timestamps and date display.
size_t strftime(char *buf, size_t n, const char *fmt, const struct tm *tm);

// Initialise the IIgs Tool Locator so time() can call ReadTimeHex.
// Call once before any time() use.  Idempotent — repeated calls
// are no-ops.  clock() works regardless of whether this is called.
void    iigsToolboxInit(void);

// ETL chrono clock hooks (Phase 5.3 cxxchrono).  Each returns a
// 32-bit millisecond count derived from the VBL counter (60 Hz, so
// each VBL tick = 50/3 ms).  All three are backed by the SAME monotonic
// source: the IIgs has no hardware tick faster than VBL and no
// monotonic-vs-realtime distinction.  Steady is therefore literally
// steady (never decreases, no wall-clock adjustment).  The chrono
// rep is forced to int32_t (==long on this target) by clock-duration
// overrides in runtime/include/c++/etl_profile.h to keep i64 libcalls
// out of every now() comparison.  Wraps after ~24.8 days at 60 Hz.
long    etl_get_steady_clock(void);
long    etl_get_high_resolution_clock(void);
long    etl_get_system_clock(void);

#ifdef __cplusplus
}
#endif

#endif
