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

#define brojVozila 7

pthread_mutex_t tunel;
pthread_cond_t condTunel;
int brojAutomobila = 0;
int brojAutobusa = 0;
int brojKamiona = 0;
int brojHitne = 0;
int flag = 0; //0 ako je bez vozila 1 ako ima sa severa 2 ako ima sa juga

void *prolazak(void *tid) {

    long id = (long)tid;
    int tipVozila = (int)rand()%4; //0 auto 1 bus 2 kamion 3 hitna
    int smer = (int)rand()%2; //0 sever 1 jug

    if(tipVozila == 0){
        //auto
        pthread_mutex_lock(&tunel);
        //printf("id %ld tipVozila %d\n", id, tipVozila);
        while(brojAutobusa > 1 || brojAutomobila > 3 || brojKamiona == 1 ||  brojHitne !=0 || (smer==0 && flag == 2) || (smer==1 && flag == 1)) {
            pthread_cond_wait(&condTunel, &tunel);
        }
        
        brojAutomobila++;
        
        if(smer == 0) {
            flag = 1;
        }
        if(smer == 1) {
            flag = 2;
        }
        if(smer == 0)
            printf("Automobil %ld ulazi u tunel sa severa...\n", id);
        else
            printf("Automobil %ld ulazi u tunel sa juga...\n", id);
        int vreme = (int)rand()%10;
        sleep(vreme);
        pthread_mutex_unlock(&tunel);

        //if(smer == 0)
        //     printf("Automobil %ld ulazi u tunel sa severa...\n", id);
        // else
        //     printf("Automobil %ld ulazi u tunel sa juga...\n", id);
        // int vreme = (int)rand()%10;
        // sleep(vreme);

        pthread_mutex_lock(&tunel);
        brojAutomobila--;
        flag = 0;
        printf("Automobil %ld izlazi iz tunela...\n", id);
        pthread_cond_broadcast(&condTunel);
        pthread_mutex_unlock(&tunel);

        //printf("Automobil %ld izlazi iz tunela...\n", id);
        //sleep(5);

    }
    else if(tipVozila == 1){
        //bus
        pthread_mutex_lock(&tunel);
        //printf("id %ld tipVozila %d\n", id, tipVozila);
        while(brojAutomobila > 3 || brojKamiona == 1 || brojAutobusa > 1 || brojHitne != 0 || (smer==0 && flag == 2) || (smer==1 && flag == 1)) {
            pthread_cond_wait(&condTunel, &tunel);
        }
        

        brojAutobusa++;
        if(smer == 0) {
            flag = 1;
        }
        if(smer == 1) {
            flag = 2;
        }
        if(smer == 0)
            printf("Autobus %ld ulazi u tunel sa severa...\n", id);
        else
           printf("Autobus %ld ulazi u tunel sa juga...\n", id); 
        int vreme = (int)rand()%10;
        sleep(vreme);
        pthread_mutex_unlock(&tunel);

        // if(smer == 0)
        //     printf("Autobus %ld ulazi u tunel sa severa...\n", id);
        // else
        //    printf("Autobus %ld ulazi u tunel sa juga...\n", id); 
        // int vreme = (int)rand()%10;
        // sleep(vreme);

        pthread_mutex_lock(&tunel);
        brojAutobusa--;
        flag = 0;
        printf("Autobus %ld izlazi iz tunela...\n", id);
        pthread_cond_broadcast(&condTunel);
        pthread_mutex_unlock(&tunel);

        //printf("Autobus %ld izlazi iz tunela...\n", id);
        //sleep(5);

    }
    else if(tipVozila == 2){
        //kamion
        pthread_mutex_lock(&tunel);
        //printf("id %ld tipVozila %d\n", id, tipVozila);
        while(brojAutomobila !=0 || brojAutobusa!=0 || brojHitne != 0 || brojKamiona>1 || (smer==0 && flag == 2) || (smer==1 && flag == 1)) {
            pthread_cond_wait(&condTunel, &tunel);
        }

        brojKamiona++;
        if(smer == 0) {
            flag = 1;
        }
        if(smer == 1) {
            flag = 2;
        }
        if(smer == 0)
            printf("Kamion %ld ulazi u tunel sa severa...\n", id);
        else
            printf("Kamion %ld ulazi u tunel sa juga...\n", id);
        int vreme = (int)rand()%10;
        sleep(vreme);
        pthread_mutex_unlock(&tunel);

        // if(smer == 0)
        //     printf("Kamion %ld ulazi u tunel sa severa...\n", id);
        // else
        //     printf("Kamion %ld ulazi u tunel sa juga...\n", id);
        // int vreme = (int)rand()%10;
        // sleep(vreme);

        pthread_mutex_lock(&tunel);
        brojKamiona--;
        flag = 0;
        printf("Kamion %ld izlazi iz tunela...\n", id);
        pthread_cond_broadcast(&condTunel);
        pthread_mutex_unlock(&tunel);
        // printf("Kamion %ld izlazi iz tunela...\n", id);
        //sleep(5);

    }
    else if(tipVozila == 3){
        //hitno vozilo
        pthread_mutex_lock(&tunel);
        // while(brojAutomobila !=0 || brojAutobusa!=0 || brojK || (smer==0 && flag == 2) || (smer==1 && flag == 1)) {
        //     pthread_cond_wait(&condTunel, &tunel);
        // }
        //printf("id %ld tipVozila %d\n", id, tipVozila);

        brojHitne++;
        if(smer == 0) {
            flag = 1;
        }
        if(smer == 1) {
            flag = 2;
        }
        if(smer == 0)
            printf("Hitno vozilo %ld ulazi u tunel sa severa...\n", id);
        else
            printf("Hitno vozilo %ld ulazi u tunel sa juga...\n", id);
        int vreme = (int)rand()%10;
        sleep(vreme);
        pthread_mutex_unlock(&tunel);
        
        // if(smer == 0)
        //     printf("Hitno vozilo %ld ulazi u tunel sa severa...\n", id);
        // else
        //     printf("Hitno vozilo %ld ulazi u tunel sa juga...\n", id);
        // int vreme = (int)rand()%10;
        // sleep(vreme);

        pthread_mutex_lock(&tunel);
        brojHitne--;
        flag = 0;
        printf("Hitno vozilo %ld izlazi iz tunela...\n", id);
        pthread_cond_broadcast(&condTunel);
        pthread_mutex_unlock(&tunel);
        // printf("Hitno vozilo %ld izlazi iz tunela...\n", id);
        //sleep(5);

    }

    return NULL;
}

int main() {

    pthread_t vozila[brojVozila];
    pthread_mutex_init(&tunel, NULL);
    pthread_cond_init(&condTunel, NULL);

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

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

    return 0;
}