#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
#include <string.h>
typedef struct poruka{
    long tip;
    int operacija;
    int rezultat;
}PorukaKorisnik;

typedef struct {
    long tip;
    int operacija;
    int rednibroj;
}PorukaRadniCvor;

enum{PRISTUP_KORISNIK, PRIJAVA_RC, ZARSENI_ZADACI_RC, MUTEXDELJENA};

union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
}arg;
#define TIP_KORISNK 444
#define TIP_GLAVNICVOR 555
#define TIP_RADNICVOR 666
#define msgsize sizeof(PorukaKorisnik)-sizeof(long)


struct sembuf P_PRIJAVA_RC = {PRIJAVA_RC, -1,0};
struct sembuf P_ZAVRSENI_ZADACI_RC = {ZARSENI_ZADACI_RC, -3,0};
struct sembuf PMUTEX = {MUTEXDELJENA, -1,0};
struct sembuf VMUTEX = {MUTEXDELJENA, 1,0};

int main(){

    key_t key = ftok("/init.c",1);

    int msgid = msgget(key, IPC_CREAT | 0666);
    int shmid = shmget(key, 12*sizeof(int), IPC_CREAT | 0666);
    int semid = semget(key,5 ,IPC_CREAT | 0666);

    int *niz = (int*)shmat(shmid, NULL,0);
   int *nizRezultat = (int*)shmat(shmid, NULL,0);

   PorukaKorisnik porukakorisnik;
   PorukaRadniCvor porukaradnicvor;

    while(1){
         printf("Glavni cvor: Cekam poruku korisnika..\n");
        msgrcv(msgid, &porukakorisnik,msgsize, TIP_GLAVNICVOR, 0);
        printf("Glavni cvor: Dobio sam poruku, cekam radne cvorove..\n");
        for(int i=1;i<4;i++){
        semop(semid, &P_PRIJAVA_RC, 1);
            porukaradnicvor.rednibroj=i;
            porukaradnicvor.tip = TIP_RADNICVOR;
            porukaradnicvor.operacija = porukakorisnik.operacija;
            msgsnd(msgid, &porukaradnicvor,msgsize,0);
        }

            printf("Glavni cvor: Radni cvorovi gotovi, obradjujem rezulat.\n");

        semop(semid, &P_ZAVRSENI_ZADACI_RC, 1);
    
        int lokalniniz[3];
        semop(semid,&PMUTEX,1);

        for(int i =0;i<3;i++){
            lokalniniz[i]=nizRezultat[i];
        }
          semop(semid,&VMUTEX,1);


        if(porukakorisnik.operacija==0){
            porukakorisnik.rezultat = lokalniniz[0]+ lokalniniz[1] + lokalniniz[2]+lokalniniz[3];
        }
        else if(porukakorisnik.operacija==1){
            porukakorisnik.rezultat = lokalniniz[0]*lokalniniz[1] *lokalniniz[2]*lokalniniz[3];
        }
       else if(porukakorisnik.operacija==2){
        int min=100;
              for(int i=1;i<3;i++){
                for(int j=1;j<3;j++){
                    if(lokalniniz[i]<lokalniniz[j])
                    min=lokalniniz[i];
                }
              }
              porukakorisnik.rezultat =min;
        }
        else 
           {
             int max=0;
              for(int i=1;i<3;i++){
                for(int j=1;j<3;j++){
                    if(lokalniniz[i]<lokalniniz[j])
                    max=lokalniniz[j];
                }
              }
              porukakorisnik.rezultat =max;
           }
          printf("Glavni cvor: Rezultat saljem korisniku.\n");
           porukakorisnik.tip= TIP_KORISNK;
        msgsnd(msgid, &porukakorisnik,msgsize,0);

     }
  }
