#include <stdio.h>
#include <unistd.h>

static void utoa(unsigned int value, char *buf, int base) {
    char temp[32];
    int i = 0;

    // Handle zero explicitly
    if (value == 0) {
        buf[0] = '0';
        buf[1] = '\0';
        return;
    }

    // Convert digits in reverse order
    while (value > 0) {
        int remainder = value % base;
        if (remainder < 10) {
            temp[i++] = '0' + remainder;
        } else {
            temp[i++] = 'a' + (remainder - 10);
        }
        value /= base;
    }

    // Reverse the string into the output destination buffer
    int j = 0;
    while (i > 0) {
        buf[j++] = temp[--i];
    }
    buf[j] = '\0';
}

/* Helper function to convert a signed integer to a string */
static void itoa(int value, char *buf, int base) {
    if (value < 0 && base == 10) {
        *buf++ = '-';
        value = -value;
    }
    utoa((unsigned int)value, buf, base);
}

int printf(const char *format, ...) {
    va_list args;
    va_start(args, format);

    int written_total = 0;
    char num_buf[32]; // Stack-allocated scratchpad for string conversions

    while (*format != '\0') {
        if (*format == '%') {
            format++; // Move past '%'
            
            switch (*format) {
                case 'c': {
                    char c = (char)va_arg(args, int);
                    write(1, &c, 1);
                    written_total++;
                    break;
                }
                case 's': {
                    char *s = va_arg(args, char *);
                    if (!s) s = "(null)";
                    // Find length manually without dragging headers
                    int len = 0;
                    while (s[len] != '\0') len++;
                    write(1, s, len);
                    written_total += len;
                    break;
                }
                case 'd':
                case 'i': {
                    int n = va_arg(args, int);
                    itoa(n, num_buf, 10);
                    int len = 0;
                    while (num_buf[len] != '\0') len++;
                    write(1, num_buf, len);
                    written_total += len;
                    break;
                }
                case 'x': {
                    unsigned int x = va_arg(args, unsigned int);
                    utoa(x, num_buf, 16);
                    int len = 0;
                    while (num_buf[len] != '\0') len++;
                    write(1, num_buf, len);
                    written_total += len;
                    break;
                }
                case '%': {
                    write(1, "%", 1);
                    written_total++;
                    break;
                }
                default:
                    // Unknown conversion, print verbatim
                    write(1, format - 1, 2);
                    written_total += 2;
                    break;
            }
        } else {
            // Standard text character
            write(1, format, 1);
            written_total++;
        }
        format++;
    }

    va_end(args);
    return written_total;
}

char getchar(void) {
    char c;
    int res = read(0, &c, 1);
    
    if (res <= 0) {
        return -1;
    }

    return (char)c;
}
