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

#define N 14
#define AUTO 0
#define BUS 1
#define KAMION 2
#define HITNA 3

#define smerA 10
#define smerB 20
#define NIKO 0

int smer = 0;
int brAuT = 0;
int brBuT = 0;
int brKuT = 0;
int brHuT = 0;
int brVozila = 0;
int hitna = 0;

int cekaA = 0;
int cekaB = 0;

pthread_mutex_t mutex;
pthread_cond_t cond;

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

    int sta = rand()%4; //dodela sta sam

    int dolazak = rand()%5;
    sleep(dolazak);
    printf("VoziloA %d id: %ld, je doslo za %ds.\n", sta, id, dolazak);

    pthread_mutex_lock(&mutex);

    cekaA++;
    printf("Povecavanje A: %d\n", cekaA);

    if(sta == HITNA){ hitna++;}

    while(smer == smerB 
    || (sta == AUTO && (brAuT > 3 || brKuT > 0 || hitna)) 
    || (sta == BUS && (brBuT > 0 || brKuT > 0 || hitna)) 
    || (sta == KAMION && (brAuT > 0 || brBuT > 0 || brHuT > 0 || brKuT > 0 || hitna))
    || (sta == HITNA && (brKuT > 0)))
    {
        pthread_cond_wait(&cond, &mutex);
    }
    printf("VoziloA %d id: %ld proso while\n", sta, id);
    if(smer != smerA)
    {
        smer = smerA;
        brAuT = 0;
        brBuT = 0;
        brKuT = 0;
        brHuT = 0;
        brVozila = brAuT + brBuT + brHuT + brKuT;
    }

    if(sta == AUTO){ brAuT++;}
    else if(sta == BUS){brBuT++;}
    else if(sta == KAMION){ brKuT++;}
    else if(sta == HITNA){brHuT++; hitna--;}
    printf("VoziloA %d id: %ld hitna: %d\n", sta, id, hitna);
    cekaA--;
    printf("Smanjivanje A: %d\n", cekaA);
    brVozila = brAuT + brBuT + brHuT + brKuT;

    pthread_mutex_unlock(&mutex);

    int prolazak = rand()%5;
    sleep(prolazak);
    printf("VoziloA %d id: %ld, je prolazilo za %ds.\n", sta, id, prolazak);

    pthread_mutex_lock(&mutex);

    if(sta == AUTO){ brAuT--;}
    else if(sta == BUS){brBuT--;}
    else if(sta == KAMION){ brKuT--;}
    else if(sta == HITNA){brHuT--;}
    brVozila = brAuT + brBuT + brHuT + brKuT;
    printf("VoziloA %d id: %ld pre obrtanja %d %d\n", sta, id, cekaA, brVozila);
    if(cekaA == 0 && brVozila == 0)
    {
        printf("VoziloA %d id: %ld doso do obrtanja\n", sta, id);
        smer = smerB;
        brAuT = 0;
        brBuT = 0;
        brKuT = 0;
        brHuT = 0;
        brVozila = brAuT + brBuT + brHuT + brKuT;
        pthread_cond_broadcast(&cond);
    }
    else if(sta == AUTO && brAuT < 3 && brKuT < 1)
    {
        pthread_cond_broadcast(&cond);
    }
    else if(sta == BUS && brBuT < 1 && brKuT < 1)
    {
        pthread_cond_broadcast(&cond);
    }
    else if(sta == KAMION && brVozila < 1)
    {
        pthread_cond_broadcast(&cond);
    }
    else if(sta == HITNA && brKuT < 1)
    {
        pthread_cond_broadcast(&cond);
    }




    pthread_mutex_unlock(&mutex);

    pthread_exit(NULL);
}
////////////////////////////////////////////////////////////////////
void* B(void *t){
    long id = (long)t;

    int sta = rand()%4; //dodela sta sam

    int dolazak = rand()%5;
    sleep(dolazak);
    printf("VoziloB %d id: %ld, je doslo za %ds.\n", sta, id, dolazak);

    pthread_mutex_lock(&mutex);

    cekaB++;

    if(sta == HITNA){ hitna++;}

    while(smer == smerA 
    || (sta == AUTO && (brAuT > 3 || brKuT > 0 || hitna)) 
    || (sta == BUS && (brBuT > 0 || brKuT > 0 || hitna)) 
    || (sta == KAMION && (brAuT > 0 || brBuT > 0 || brHuT > 0 || brKuT > 0 || hitna))
    || (sta == HITNA && (brKuT > 0)))
    {
        pthread_cond_wait(&cond, &mutex);
    }
    printf("VoziloB %d id: %ld proso while\n", sta, id);
    if(smer != smerB)
    {
        smer = smerB;
        brAuT = 0;
        brBuT = 0;
        brKuT = 0;
        brHuT = 0;
        brVozila = brAuT + brBuT + brHuT + brKuT;
    }

    if(sta == AUTO){ brAuT++;}
    else if(sta == BUS){brBuT++;}
    else if(sta == KAMION){ brKuT++;}
    else if(sta == HITNA){brHuT++; hitna--;}
    cekaB--;
    brVozila = brAuT + brBuT + brHuT + brKuT;

    pthread_mutex_unlock(&mutex);

    int prolazak = rand()%5;
    sleep(prolazak);
    printf("VoziloB %d id: %ld, je prolazilo za %ds.\n", sta, id, prolazak);

    pthread_mutex_lock(&mutex);

    if(sta == AUTO){ brAuT--;}
    else if(sta == BUS){brBuT--;}
    else if(sta == KAMION){ brKuT--;}
    else if(sta == HITNA){brHuT--;}
    brVozila = brAuT + brBuT + brHuT + brKuT;

    if(cekaB == 0 && brVozila == 0)
    {
        smer = smerA;
        brAuT = 0;
        brBuT = 0;
        brKuT = 0;
        brHuT = 0;
        brVozila = brAuT + brBuT + brHuT + brKuT;
        pthread_cond_broadcast(&cond);
    }
    else if(sta == AUTO && brAuT < 3 && brKuT < 1)
    {
        pthread_cond_broadcast(&cond);
    }
    else if(sta == BUS && brBuT < 1 && brKuT < 1)
    {
        pthread_cond_broadcast(&cond);
    }
    else if(sta == KAMION && brVozila < 1)
    {
        pthread_cond_broadcast(&cond);
    }
    else if(sta == HITNA && brKuT < 1)
    {
        pthread_cond_broadcast(&cond);
    }




    pthread_mutex_unlock(&mutex);

    pthread_exit(NULL);
}

int main()
{
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);
    pthread_t niz[N];
    long t;
    for(t = 0; t < N/2; t++)
    {
        pthread_create(&niz[t], NULL, A, (void*)t);
    }
    for(t = N/2; t < N; t++)
    {
        pthread_create(&niz[t], NULL, B, (void*)t);
    }
    pthread_exit(NULL);
    return 0;
}