#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

#define uint_64 unsigned long long

int N; 
//travailler avec des linkendList
typedef struct node{ 
    uint_64 value;
    struct node *next;
}node_t;

typedef struct queue{ 
    struct node *tail;
    int size;
    int final;
}queue_t;

struct buffer_rc{
    char **tab;
    int size;       
    int len;
    int head;
    int tail;
    FILE *file1;
};


struct buffer_cw
{
    queue_t **tab;
    int size;       
    int len;
    int head;
    int tail;
    FILE *file2;
};

struct buffer_rccw{
    struct buffer_rc *struct1;
    struct buffer_cw *struct2; 
};

/* sémaphore est une structure de donné qui contient :
    *un entier qui stocke la valeur, positive ou nulle du sémaphore.
    *une queue qui contient les pointeurs vers les threads
*/
pthread_mutex_t mutex1;
sem_t empty1;
sem_t full1;

pthread_mutex_t mutex2;
sem_t empty2;
sem_t full2;


void put_in_buffer_1(char *c, struct buffer_rc *ptr);
char *get_from_buffer_1(struct buffer_rc *ptr);
void put_in_buffer_2(struct queue *ptr, struct buffer_cw *buf);
queue_t *get_from_buffer_2(struct buffer_cw *buf);

int is_div(uint_64 number, uint_64 i);
uint_64 modpow (uint_64 base, uint_64 exp, uint_64 mod);
uint_64* randomiser (int k, uint_64 N);
int is_prime(uint_64 number);

void enqueue(queue_t* q, uint_64 val);
queue_t* prime_divs(uint_64 number);

void *reading (void *param);
void *calculating(void *param);
void *writing(void *param);

void sem_1_initializer(struct buffer_rc *buf);
void sem_2_initializer (struct buffer_cw *buf);

struct buffer_rc * buff_init_1(FILE *file1);
struct buffer_cw * buff_init_2(FILE *file2);
struct buffer_rccw *buff_init_12(struct buffer_rc *ptr1,struct buffer_cw *ptr2);

int thread_create_join(struct buffer_rc *ptr1,struct buffer_cw *ptr2,struct buffer_rccw *ptr3);
void mut_sem_destroy(void);

int run (char *input,char *output,int n_threads);