// iigs/resource.h - typed-C facade over the IIgs Resource Manager.
//
// Phase 3.4 REAL implementation: parses .rsrc resource forks via the
// stdio surface (fopen/fread/fseek/fclose) and serves resources from a
// per-file cache.  Read-only.  No AddResource, no DetachResource, no
// partial-load, no encryption - those are features we do not yet need.
//
// What you GET today:
//   - openResourceFile(path, accessByte, fileType) -> refNum (>0) or
//     0 on failure (errno-style code lands in *err if provided).
//   - loadResource(type, id) -> Handle (void **) on success; cached so
//     repeated calls return the same handle.  *handle points at the
//     resource bytes (already read from the file).
//   - releaseResource(verb, handle) -> 0 on success.  verb 0 just
//     releases the current load; verb 1 also evicts the cache entry
//     and frees the data.
//   - closeResourceFile(refNum) -> 0 on success.  Frees all cached
//     handles owned by that file.
//
// On-disk format (Apple IIgs Toolbox Reference Vol 3, ch.42):
//   File offset 0: rResourceMap header (24 bytes, little-endian fields
//     because the 65816 is LE).  Field rmToIndex is the file offset of
//     the rIndex table; rmIndexUsed is the number of valid entries; the
//     remaining header fields are bookkeeping/zero at build time.
//   Body bytes: resource payloads at the offsets recorded in rIndex.
//   At rmToIndex: array of 20-byte rIndex entries, each:
//     uint16 rType, uint32 rID, uint32 rOffset, uint16 rAttr,
//     uint32 rSize, uint32 rHandle (zero on disk).
//
// HLock semantics:
//   The handles we return are NOT relocatable - they point straight at
//   a malloc'd payload buffer.  That means HLock/HUnlock are no-ops
//   here.  The void ** indirection is preserved so that real Memory
//   Manager handles can swap in later without changing callers.

#ifndef IIGS_RESOURCE_H
#define IIGS_RESOURCE_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>


// Status codes returned by the typed wrappers.  Mirror the runtime's
// existing errno-style convention (negative = error).
enum {
    RES_OK              =  0,
    RES_ERR_BLOCKED     = -1,    // legacy stub marker - kept for
                                 // backwards compat with old probes
    RES_ERR_NOT_STARTED = -2,    // openResourceFile not called yet
    RES_ERR_NOT_FOUND   = -3,    // file open / resource lookup failed
    RES_ERR_TOOLBOX     = -4,    // map header corrupt / IO failure
    RES_ERR_NO_MEM      = -5,    // malloc failed
    RES_ERR_BAD_HANDLE  = -6     // release/close given an unknown ref
};


// Resource type codes we expect to bundle.  See Apple IIgs Toolbox
// Reference Vol 3 chapter 42 for the canonical list.
#define RES_TYPE_RICON       0x8005
#define RES_TYPE_RTEXT       0x8014
#define RES_TYPE_RPSTRING    0x8015
#define RES_TYPE_RCSTRING    0x8016


// Build-time tunables.  These cap the per-process resource footprint.
#ifndef IIGS_RES_MAX_FILES
#define IIGS_RES_MAX_FILES   2
#endif

#ifndef IIGS_RES_MAX_HANDLES
#define IIGS_RES_MAX_HANDLES 16
#endif


// Resource ID (32-bit on disk and in the rIndex).
typedef uint32_t IigsResIdT;


// Resource type code (16-bit; high bit reserved for system/extended
// types, low 15 bits for the actual code).
typedef uint16_t IigsResTypeT;


// 24-byte resource map header at the start of every .rsrc file.
typedef struct {
    uint16_t rmVersion;
    uint32_t rmToIndex;
    uint16_t rmFileNum;
    uint16_t rmID;
    uint32_t rmIndexSize;
    uint32_t rmIndexUsed;
    uint16_t rmFreeListSize;
    uint16_t rmFreeListUsed;
    uint16_t rmPad;
} ResourceMapHeaderT;


// 20-byte rIndex entry.
typedef struct {
    uint16_t rType;
    uint32_t rID;
    uint32_t rOffset;
    uint16_t rAttr;
    uint32_t rSize;
    uint32_t rHandle;
} ResourceIndexEntryT;


// Refnum returned by openResourceFile.  Zero means "no file"; valid
// refnums start at 1.
typedef uint16_t ResourceRefNumT;


// One-shot init.  Returns RES_OK; safe to call more than once.
int resourceProbeInit(void);


// Reports whether the Resource Manager is alive.  Always 1 after
// resourceProbeInit() has run.
int resourceRuntimeEnabled(void);


// Opens a resource fork at `path`.  `accessByte` and `fileType` are
// accepted for API parity with the toolbox but ignored on read-only
// in-memory backends.  Returns refnum (>0) on success, 0 on failure.
// If `err` is non-NULL it receives RES_OK or one of RES_ERR_*.
ResourceRefNumT openResourceFile(const char *path, uint8_t accessByte,
                                  uint16_t fileType, int *err);


// Closes a resource fork and frees any handles cached for that file.
// Returns RES_OK or RES_ERR_BAD_HANDLE.
int closeResourceFile(ResourceRefNumT refNum);


// Loads a resource by (type, id).  Searches all open resource files
// in open order and returns a cached handle if the same (type, id)
// was previously loaded from any open file.  Returns NULL on failure.
//
// The returned handle is `void **`; `*handle` is the resource bytes.
void **loadResource(IigsResTypeT type, IigsResIdT id, int *err);


// Releases a previously-loaded resource.
//   verb 0: keep the cached payload (cheap; the handle may be reused).
//   verb 1: evict the cache entry and free the payload.
// Returns RES_OK on success.
int releaseResource(int verb, void **handle);


// Convenience: byte size of the resource pointed to by `handle`.
// Returns 0 if `handle` is not in the cache.
uint32_t getResourceSize(void **handle);


// ---- Legacy stub API kept for backwards compatibility ----
// The pre-Phase-3.4 stub exposed iigsLoadResource / iigsGetResourceSize
// for the rsrcProbe markers.  Those now dispatch to the real
// implementation when at least one resource file is open.  They report
// RES_ERR_NOT_STARTED when no file is open (instead of the old
// RES_ERR_BLOCKED), preserving the "did Phase 3.4 land?" signal.
void **iigsLoadResource(IigsResTypeT resType, IigsResIdT resId, int *err);


uint32_t iigsGetResourceSize(IigsResTypeT resType, IigsResIdT resId,
                             int *err);


#ifdef __cplusplus
}
#endif

#endif  // IIGS_RESOURCE_H
