#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <ctype.h>
#include "lib.h"
#include "sharedlib.h"

#define BITS 8
#define BUFFER_SIZE 256

volatile uint8_t buffer[BUFFER_SIZE];
volatile size_t byte_index = 0;
volatile int sample_interval = 100;  // Default: 100 µs
volatile int threshold = 245;        // Default: 245 cycles

void signal_handler(int signo) {
    if (signo == SIGALRM) 
    {
        // Check if buffer is full
        if (byte_index >= BUFFER_SIZE) 
        {
            ualarm(0, 0);  // Stop sampling
            printf("Buffer full. Stopping capture.\n");
            return;
        }

        // Receive a byte
        uint8_t byte = 0;
        for (int i = 0; i < BITS; i++) 
        {
            size_t time = time_maccess((void *) myStupidNOPFunction + (i << 9));
            if (time < threshold) 
            {
                // set the ith bit of byte to 1 if it was a cache hit
                byte |= (1 << i);
            }
        }

        // flush the cache
        for (int i = 0; i < BITS; i++) 
        {
            flush((void *) myStupidNOPFunction + (i << 9));
        }

        buffer[byte_index++] = byte;  // Store received byte
    }
}

int main(int argc, char *argv[]) {
    if (argc < 3) 
    {
        fprintf(stderr, "Usage: %s <sample_interval> <threshold>\n", argv[0]);
        return 1;
    }

    sample_interval = atoi(argv[1]);
    threshold = atoi(argv[2]);

    printf("Receiver started with sample interval: %d µs, threshold: %d cycles\n", sample_interval, threshold);

    // Flush the cache once before starting
    for (int i = 0; i < BITS; i++) 
    {
        flush((void *) myStupidNOPFunction + (i << 9));
    }

    signal(SIGALRM, signal_handler);
    ualarm(sample_interval, sample_interval);

    while (byte_index < BUFFER_SIZE) {
        pause();
    }

    // Print received bytes in hex
    printf("Received %zu bytes:\n", byte_index);
    for (size_t i = 0; i < byte_index; i++) {
        printf("%02X ", buffer[i]);
    }
    printf("\n");

    // Print as ASCII characters
    printf("ASCII Output:\n");
    for (size_t i = 0; i < byte_index; i++) {
        //if (buffer[i] >= 32 && buffer[i] <= 126) // Printable ASCII
        if (isalnum(buffer[i]))
        {   
            printf("%c", buffer[i]);  
        } else 
        {
            printf(".");  // Placeholder for non-printables
        }
    }
    printf("\n");

    return 0;
}