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

#define prviSmer 10
#define drugiSmer 10

pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;

int brojAutomobila=0;
int brojAutobusa=0;
int brKamiona=0;
int hitna=0;

int smer=0;//1-prvi smer, 2- drugi smer, 0-neodredjeno

void *radPrviSmer(void *t)
{
    long id=(long)t;

    int sTime=rand()%3;
    sleep(sTime);

    int tip=rand()%4;//0-automobil, 1-autobus, 2-kamion, 3-hitno

    printf("Vozila %ld tipa %d dolazi iz prvog smera\n",id,tip);

    
    if(tip==0)//automobil
    {
        pthread_mutex_lock(&mutex);

        while(smer==2 || (smer==1 && hitna==1) || (smer==1 && brojAutomobila>=3) || (smer==1 && brKamiona>0))
        {
            pthread_cond_wait(&cond,&mutex);
        }
        smer=1;
        brojAutomobila++;
        pthread_mutex_unlock(&mutex);

        printf("Vozilo %ld tipa %d prolazi kroz tunel iz prvog smera\n",id,tip);
        sleep(rand()%3);

        pthread_mutex_lock(&mutex);
        brojAutomobila--;
        printf("Vozilo %ld tipa %d PROSLO kroz tunel iz prvog smera\n",id,tip);
        
        smer=0;
        pthread_cond_broadcast(&cond);
        pthread_mutex_unlock(&mutex);



    } 
    else if(tip==1)//autobus
    {
        pthread_mutex_lock(&mutex);

        while(smer==2 || (smer==1 && hitna==1)  || (smer==1 && brojAutobusa>0) || (smer==1 && brKamiona>0))
        {
            pthread_cond_wait(&cond,&mutex);
        }
        
        smer=1;
        brojAutobusa++;
        pthread_mutex_unlock(&mutex);

        printf("Vozilo %ld tipa %d prolazi kroz tunel iz prvog smera\n",id,tip);
        sleep(rand()%3);

        pthread_mutex_lock(&mutex);
        brojAutobusa--;
        printf("Vozilo %ld tipa %d PROSLO kroz tunel iz prvog smera\n",id,tip);
        
        
        smer=0;
        pthread_cond_broadcast(&cond);
        
        
        
        pthread_mutex_unlock(&mutex);


    }
    else if(tip==2)//kamion
    {
        pthread_mutex_lock(&mutex);

        while(smer==2 || (smer==1 && hitna==1)  ||  (smer==1 && brojAutomobila>0) || (smer==1 && brojAutobusa>0) || (smer==1 && brKamiona>0))
        {
            pthread_cond_wait(&cond,&mutex);
        }
        

        smer=1;
        brKamiona++;
        pthread_mutex_unlock(&mutex);

        printf("Vozilo %ld tipa %d prolazi kroz tunel iz prvog smera\n",id,tip);
        sleep(rand()%3);

        pthread_mutex_lock(&mutex);
        brKamiona--;
        printf("Vozilo %ld tipa %d PROSLO kroz tunel iz prvog smera\n",id,tip);
        
       
        smer=0;
        pthread_cond_broadcast(&cond);
        
        
        
        pthread_mutex_unlock(&mutex);

    }
    else//hitna
    {
        pthread_mutex_lock(&mutex);

        while(smer==2)
        {
            pthread_cond_wait(&cond,&mutex);
        }

        smer=1;
        hitna=1;

        pthread_mutex_unlock(&mutex);

        printf("Vozilo %ld tipa %d prolazi kroz tunel iz prvog smera\n",id,tip);
        sleep(rand()%3);

        pthread_mutex_lock(&mutex);
        hitna=0;
        printf("Vozilo %ld tipa %d PROSLO kroz tunel iz prvog smera\n",id,tip);
        
        
        smer=0;
        pthread_cond_broadcast(&cond);
        
        
        
        pthread_mutex_unlock(&mutex);
    }

    

    
    pthread_exit(NULL);

}
void *radDrugiSmer(void *t)
{
    long id=(long)t;

    int sTime=rand()%3;
    sleep(sTime);

    int tip=rand()%4;//0-automobil, 1-autobus, 2-kamion, 3-hitno

    printf("Vozila %ld tipa %d dolazi iz drugog smera\n",id,tip);

    

    if(tip==0)//automobil
    {
        pthread_mutex_lock(&mutex);
        while(smer==1 || (smer==2 && hitna==1)  || (smer==2 && brojAutomobila>=3) || (smer==2 && brKamiona>0))
        {
            pthread_cond_wait(&cond,&mutex);
        }
        smer=2;
        brojAutomobila++;
        pthread_mutex_unlock(&mutex);

        printf("Vozilo %ld tipa %d prolazi kroz tunel iz drugog smera\n",id,tip);
        sleep(rand()%3);

        pthread_mutex_lock(&mutex);
        brojAutomobila--;
        printf("Vozilo %ld tipa %d PROSLO kroz tunel iz drugog smera\n",id,tip);
        
        
        smer=0;
        pthread_cond_broadcast(&cond);
        
        
        
        pthread_mutex_unlock(&mutex);



    } 
    else if(tip==1)//autobus
    {
        pthread_mutex_lock(&mutex);
        while(smer==1 || (smer==2 && hitna==1)  || (smer==2 && brojAutobusa>0) || (smer==2 && brKamiona>0))
        {
            pthread_cond_wait(&cond,&mutex);
        }
        
        smer=2;
        brojAutobusa++;
        pthread_mutex_unlock(&mutex);

        printf("Vozilo %ld tipa %d prolazi kroz tunel iz drugog smera\n",id,tip);
        sleep(rand()%3);

        pthread_mutex_lock(&mutex);
        brojAutobusa--;
        printf("Vozilo %ld tipa %d PROSLO kroz tunel iz drugog smera\n",id,tip);
        
        
        
        smer=0;
        pthread_cond_broadcast(&cond);
        
        
        pthread_mutex_unlock(&mutex);


    }
    else if(tip==2)//kamion
    {
        pthread_mutex_lock(&mutex);
        while(smer==1 || (smer==2 && hitna==1)  ||  (smer==2 && brojAutomobila>0) || (smer==1 && brojAutobusa>0) || (smer==1 && brKamiona>0))
        {
            pthread_cond_wait(&cond,&mutex);
        }
        

        smer=2;
        brKamiona++;
        pthread_mutex_unlock(&mutex);

        printf("Vozilo %ld tipa %d prolazi kroz tunel iz drugog smera\n",id,tip);
        sleep(rand()%3);

        pthread_mutex_lock(&mutex);
        brKamiona--;
        printf("Vozilo %ld tipa %d PROSLO kroz tunel iz drugog smera\n",id,tip);
        

        smer=0;
        pthread_cond_broadcast(&cond);
        
        
        pthread_mutex_unlock(&mutex);

    }
    else//hitna
    {
        pthread_mutex_lock(&mutex);
        while(smer==1)
        {
            pthread_cond_wait(&cond,&mutex);
        }

        smer=2;
        hitna=1;

        pthread_mutex_unlock(&mutex);

        printf("Vozilo %ld tipa %d prolazi kroz tunel iz prvog smera\n",id,tip);
        sleep(rand()%3);

        pthread_mutex_lock(&mutex);
        hitna=0;
        printf("Vozilo %ld tipa %d PROSLO kroz tunel iz drugog smera\n",id,tip);
        
        
        
        smer=0;
        pthread_cond_broadcast(&cond);
        
        
        pthread_mutex_unlock(&mutex);



    }
    
    pthread_exit(NULL);

}


int main()
{
    srand(time(NULL));
    pthread_t threads[prviSmer+drugiSmer];

    for(long i=0;i<prviSmer;i++)
    {
        pthread_create(threads+i,NULL,radPrviSmer,(void*)i);
    }
    for(long i=0;i<drugiSmer;i++)
    {
        pthread_create(threads+(prviSmer+i),NULL,radDrugiSmer,(void*)i);
    }
    for(long i=0;i<prviSmer+drugiSmer;i++)
    {
        pthread_join(threads[i],NULL);
    }

    pthread_exit(NULL);


    return 0;
}