#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>

#define N 10

int smer1 = 0;
int smer2 = 0;
int brojAutomobila = 0;
int brojAutobusa = 0;
int brojKamiona = 0;
int hitnoVozilo = 0;

pthread_mutex_t tunel;
pthread_cond_t tunelCond;
pthread_cond_t hitnaCond;

void* f(void *i){
    long id = (long)i;
    int smer = rand()%2;
    int cekanje = rand()%3; 
    int tipVozila = rand()%4; //0-auto , 1-autobus, 2 - kamion 3- htino 
    
    sleep(cekanje);
    printf("Stize vozilo %ld tipa %d u smeru %d\n", id, tipVozila, smer+1);
    if(smer == 0){
        pthread_mutex_lock(&tunel);
        if(tipVozila == 3 ){
            while(smer2 > 0 || brojKamiona > 0)
                pthread_cond_wait(&hitnaCond, &tunel);
        }
        else{
            while( smer2 > 0 || 
            (tipVozila == 0 && brojAutomobila > 3) ||
            (tipVozila == 1 && brojAutobusa > 0) ||
            (tipVozila == 2 && smer1 > 0) ||
            brojKamiona > 0)
                pthread_cond_wait(&tunelCond, &tunel);
        }
        smer1++;
        if(tipVozila == 0) brojAutomobila++;
        if(tipVozila == 1) brojAutobusa++;
        if(tipVozila == 2) brojKamiona++;
        if(tipVozila == 3) hitnoVozilo++;
        printf("Vozilo %ld tipa % d je uslo u tunel u smeru 1...\n", id, tipVozila);
        pthread_mutex_unlock(&tunel);

        printf("Vozilo %ld tipa %d kosisti tunel u smeru 1...\n", id, tipVozila);
        sleep(rand()%5 +1);

        pthread_mutex_lock(&tunel);
        printf("Vozilo %ld oslobadja tunel u smeru 1...\n", id);
        smer1--;
        if(tipVozila == 0) brojAutomobila--;
        if(tipVozila == 1) brojAutobusa--;
        if(tipVozila == 2) brojKamiona--;
        if(tipVozila == 3) hitnoVozilo--;
        pthread_cond_broadcast(&hitnaCond);
        pthread_cond_broadcast(&tunelCond);
        pthread_mutex_unlock(&tunel);
    }

    if(smer == 1){
        pthread_mutex_lock(&tunel);
        if(tipVozila == 3 ){
            while(smer1 > 0 || brojKamiona > 0)
                pthread_cond_wait(&hitnaCond, &tunel);
        }
        else{
            while( smer1 > 0 || 
            (tipVozila == 0 && brojAutomobila > 3) ||
            (tipVozila == 1 && brojAutobusa > 0) ||
            (tipVozila == 2 && smer2 > 0)
            || brojKamiona > 0)
                pthread_cond_wait(&tunelCond, &tunel);
        }
        smer2++;
        if(tipVozila == 0) brojAutomobila++;
        if(tipVozila == 1) brojAutobusa++;
        if(tipVozila == 2) brojKamiona++;
        if(tipVozila == 3) hitnoVozilo++;
        printf("Vozilo %ld tipa % d je uslo u tunel u smeru 2...\n", id, tipVozila);
        pthread_mutex_unlock(&tunel);

        printf("Vozilo %ld tipa %d kosisti tunel u smeru 2...\n", id, tipVozila);
        sleep(rand()%5+1);

        pthread_mutex_lock(&tunel);
        printf("Vozilo %ld oslobadja tunel u smeru 2...\n", id);
        smer2--;
        if(tipVozila == 0) brojAutomobila--;
        if(tipVozila == 1) brojAutobusa--;
        if(tipVozila == 2) brojKamiona--;
        if(tipVozila == 3) hitnoVozilo--;
        pthread_cond_broadcast(&hitnaCond);
        pthread_cond_broadcast(&tunelCond);
        pthread_mutex_unlock(&tunel);
    }

}

int main(){

    srand(time(NULL));
    pthread_mutex_init(&tunel, NULL);
    pthread_cond_init(&tunelCond, NULL);
    pthread_cond_init(&hitnaCond, NULL);

    pthread_t vozila[N];

    for(long i = 0 ; i < N ; i++){
        pthread_create(vozila+i, NULL, f, (void*)i);
    }

    for(long i = 0 ; i < N ; i++){
        pthread_join(vozila[i], NULL);
    }

    pthread_mutex_destroy(&tunel);
    pthread_cond_destroy(&tunelCond);

    return 1;
}