#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <time.h>

#define PORT 8080
#define SERVER_IP "127.0.0.1"

typedef struct {
    int number;
    struct timespec timestamp;
} Data;

Data shared_data;
pthread_mutex_t lock;

void* receive_data(void* arg) {
    int sockfd = *((int*)arg);
    struct sockaddr_in cliaddr;
    socklen_t len;
    char buffer[sizeof(Data)];

    while (1) {
        recvfrom(sockfd, (char*)buffer, sizeof(Data),
            MSG_WAITALL, (struct sockaddr*)&cliaddr,
            &len);

        Data* data = (Data*)buffer;

        pthread_mutex_lock(&lock);
        shared_data = *data;
        pthread_mutex_unlock(&lock);
    }

    return NULL;
}

int main() {
    int sockfd;
    struct sockaddr_in servaddr;

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&servaddr, 0, sizeof(servaddr));

    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(PORT);
    servaddr.sin_addr.s_addr = inet_addr(SERVER_IP);

    if (bind(sockfd, (const struct sockaddr*)&servaddr,
        sizeof(servaddr)) < 0)
    {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    pthread_t thread_id;
    pthread_create(&thread_id, NULL, receive_data, &sockfd);

    while (1) {
        struct timespec ts = {2,0};
        pthread_mutex_lock(&lock);
        Data data = shared_data;
        pthread_mutex_unlock(&lock);

        struct timespec now;
        clock_gettime(CLOCK_REALTIME, &now);
        double delay = (now.tv_sec - data.timestamp.tv_sec) +
            (now.tv_nsec - data.timestamp.tv_nsec) / 1e9;

        printf("Received number: %d\n", data.number);
        printf("Delay: %.9f seconds\n", delay);

        nanosleep(&ts,NULL);
    }

    close(sockfd);
    return 0;
}

