#ifndef COLOSSUS_APP_H
#define COLOSSUS_APP_H

typedef unsigned long  uint32_t;
typedef long           int32_t;
typedef unsigned short uint16_t;
typedef short          int16_t;
typedef unsigned char  uint8_t;
typedef unsigned long  size_t;
typedef int            bool;
#define true 1
#define false 0
#define NULL ((void*)0)

/* Startup stub — placed in .text.startup so it's first in the binary.
   c_exec starts the process at the load address, so this must be at offset 0. */
__asm__(
	".section .text.startup,\"ax\"\n"
	"	jmp _start\n"
	".previous\n"
	".global syscall\n"
	"syscall:\n"
	"	link %a6, #0\n"
	"	trap #0\n"
	"	unlk %a6\n"
	"	rts\n"
);
extern uint32_t syscall(uint32_t id, uint32_t p1, uint32_t p2,
                        uint32_t p3, uint32_t p4, uint32_t p5, uint32_t p6);

/* Syscall IDs — must match kernel enum */
#define SYS_SEND_MESSAGE     0
#define SYS_CREATE_MESSAGE   1
#define SYS_RECEIVE_MESSAGE  2
#define SYS_DISPOSE_MESSAGE  4
#define SYS_RELEASE_PROC     5
#define SYS_MALLOC           8
#define SYS_FREE             9
#define SYS_EXIT             10
#define SYS_GET_PID          13
#define SYS_GET_JIFFIES      17
#define SYS_PRINTF           30

/* Message field offsets */
#define MSG_BUF(m)        (*(void**)((uint8_t*)(m) + 40))
#define MSG_BUF_SIZE(m)   (*(uint32_t*)((uint8_t*)(m) + 36))
#define MSG_SOURCE_PID(m) (*(uint32_t*)((uint8_t*)(m) + 28))
#define MSG_DELAY(m)      (*(uint32_t*)((uint8_t*)(m) + 8))

/* KCD */
#define KCD_PID        62
#define KCD_OP_REG     0
#define KCD_OP_CHAR    1
#define KCD_OP_ACK     2

typedef struct { uint32_t op; char data; } KCDPacket;

/* Wrappers */
static inline void* c_create_message(size_t sz) {
	return (void*)syscall(SYS_CREATE_MESSAGE, sz, 0,0,0,0,0);
}
static inline int32_t c_send_message(void* m, uint32_t pid) {
	return (int32_t)syscall(SYS_SEND_MESSAGE, (uint32_t)m, pid, 0,0,0,0);
}
static inline void* c_receive_message(uint32_t pid) {
	return (void*)syscall(SYS_RECEIVE_MESSAGE, pid, 0,0,0,0,0);
}
static inline void c_dispose_message(void* m) {
	syscall(SYS_DISPOSE_MESSAGE, (uint32_t)m, 0,0,0,0,0);
}
static inline uint32_t c_get_pid(void) {
	return syscall(SYS_GET_PID, 0,0,0,0,0,0);
}
static inline uint32_t c_get_system_jiffies(void) {
	return syscall(SYS_GET_JIFFIES, 0,0,0,0,0,0);
}
static inline void c_exit(void) {
	syscall(SYS_EXIT, 0,0,0,0,0,0);
}
static inline void sys_printf(const char* s) {
	syscall(SYS_PRINTF, (uint32_t)s, 0,0,0,0,0);
}
static inline int32_t c_send_message_delayed(void* m, uint32_t pid, uint32_t delay) {
	MSG_DELAY(m) = delay;
	return c_send_message(m, pid);
}

/* KCD helpers */
static inline void kcd_register(char c) {
	void* m = c_create_message(8);
	KCDPacket* kp = (KCDPacket*)MSG_BUF(m);
	kp->op = KCD_OP_REG;
	/* Register uppercase first (triggers KCD announcement), then lowercase */
	kp->data = (c >= 'a' && c <= 'z') ? (c - 32) : c;
	c_send_message(m, KCD_PID);
	if (c >= 'a' && c <= 'z') {
		m = c_create_message(8);
		kp = (KCDPacket*)MSG_BUF(m);
		kp->op = KCD_OP_REG;
		kp->data = c;
		c_send_message(m, KCD_PID);
	}
}
static inline void kcd_ack(void* m) {
	c_dispose_message(m);
	void* r = c_create_message(8);
	KCDPacket* kp = (KCDPacket*)MSG_BUF(r);
	kp->op = KCD_OP_ACK;
	c_send_message(r, KCD_PID);
}

/* String utilities */
static int str_len(const char* s) { int n=0; while(*s++)n++; return n; }

static void int_to_str(int32_t val, char* buf) {
	if (val == 0) { buf[0]='0'; buf[1]=0; return; }
	char tmp[12]; int i=0, neg=0;
	if (val < 0) { neg=1; val=-val; }
	while (val > 0) { tmp[i++]='0'+(val%10); val/=10; }
	int j=0;
	if (neg) buf[j++]='-';
	while (i > 0) buf[j++]=tmp[--i];
	buf[j]=0;
}

/* Print helpers — build string then call sys_printf */
static void print_str(const char* s) { sys_printf(s); }

static void print_int(int32_t val) {
	char buf[12];
	int_to_str(val, buf);
	sys_printf(buf);
}

/* Print "prefix<number>suffix" */
static void print_fmt(const char* pre, int32_t val, const char* suf) {
	char line[128];
	int pos = 0;
	const char* s;
	for (s=pre; *s; s++) line[pos++] = *s;
	char num[12]; int_to_str(val, num);
	for (s=num; *s; s++) line[pos++] = *s;
	for (s=suf; *s; s++) line[pos++] = *s;
	line[pos] = 0;
	sys_printf(line);
}

/* ANSI cursor move */
static void move_cursor(int row, int col) {
	char buf[16]; int pos=0; char num[8]; const char* s;
	buf[pos++]='\033'; buf[pos++]='[';
	int_to_str(row, num); for(s=num;*s;s++) buf[pos++]=*s;
	buf[pos++]=';';
	int_to_str(col, num); for(s=num;*s;s++) buf[pos++]=*s;
	buf[pos++]='H'; buf[pos]=0;
	sys_printf(buf);
}

/* memset for BSS clearing */
static inline void* app_memset(void* p, int v, size_t n) {
	uint8_t* d = (uint8_t*)p;
	while (n--) *d++ = (uint8_t)v;
	return p;
}
static inline void* app_memcpy(void* d, const void* s, size_t n) {
	uint8_t* dd = (uint8_t*)d;
	const uint8_t* ss = (const uint8_t*)s;
	while (n--) *dd++ = *ss++;
	return d;
}

#endif
