// HTTP server example (macOS only)

#import "modules/std.sx";
#import "modules/std/socket.sx";

// --- Logger ---

Logger :: struct {
    prefix: string;
    count: i64;
}

log :: (logger: *Logger, msg: string) {
    logger.count += 1;
    print("[{}] {}\n", logger.prefix, msg);
}



main :: () -> i32 {
    PORT :: 8080;

    fd := socket(AF_INET, SOCK_STREAM, 0);
    if fd < 0 {
        print("error: socket()\n");
        return 1;
    }

    opt : i32 = 1;
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, @opt, 4);

    addr := SockAddr.{ sin_len = 16, sin_family = 2, sin_port = htons(PORT) };

    if bind(fd, @addr, 16) < 0 {
        print("error: bind()\n");
        return 1;
    }

    if listen(fd, 10) < 0 {
        print("error: listen()\n");
        return 1;
    }

    print("listening on http://localhost:{}\n", PORT);

    arena := Arena.init(context.allocator, 65536);
    logger := Logger.{ prefix = "http", count = 0 };

    while true {
        client := accept(fd, null, null);
        if client < 0 { continue; }

        push Context.{ allocator = xx arena, data = xx @logger } {
            handle(client);
        }

        arena.reset();
        close(client);
    }

    arena.deinit();
    close(fd);
    0
}

handle :: (client: i32) {
    // Read request
    buf : [4096]u8 = ---;
    read(client, buf, buf.len);

    body :: "<html><body><h1>Hello from sx!</h1></body></html>";
    response :: format("HTTP/1.1 200 OK\r
Content-Type: text/html\r
Connection: close\r
Content-Length: {}\r
\r\n{}", body.len, body);

    write(client, response, response.len);
    logger : *Logger = xx context.data;
    log(logger, format("served request #{}", logger.count + 1));
}