#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;
}poruka;

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(poruka)-sizeof(long)


struct sembuf V_PRIJAVA_RC = {PRIJAVA_RC, 1,0};
struct sembuf V_ZAVRSENI_ZADACI_RC = {ZARSENI_ZADACI_RC, 1,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);

   PorukaRadniCvor poruka;

  
   while(1){
     int lokalniniz[4];
     msgrcv(msgid, &poruka, msgsize, TIP_RADNICVOR,0);
    printf("Radni cvor %d :Prijavljujem se za rad.\n", poruka.rednibroj);
           
    semop(semid, &V_PRIJAVA_RC,1);

   
    int i=0, n=4,j=0;
    if(poruka.rednibroj==1)
      {  i=0;n=4;}
      else if(poruka.rednibroj==2)
      {  i=4;n=8;}
      else {
        i=8;n=12;
      }

   semop(semid, &PMUTEX, 1);
   for(i; i<n;i++){
    lokalniniz[j]=niz[i];
    j++;
   }
   semop(semid, &VMUTEX, 1);

      printf("Radni cvor %d :Obradjujem rezultat.\n", poruka.rednibroj);
        int rezultat;

        if(poruka.operacija==0){
            rezultat= lokalniniz[0]+ lokalniniz[1] + lokalniniz[2] +lokalniniz[3];
            sleep(1);
        }
        else if(poruka.operacija==1){
            rezultat= lokalniniz[0]*lokalniniz[1] *lokalniniz[2]* lokalniniz[3];
             sleep(1);
        }
       else if(poruka.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];
                }
              }
              rezultat=min;
               sleep(1);
        }
        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];
                }
              }
              rezultat=max;
               sleep(1);
           }
     printf("Radni cvor %d :Rezultat je spreman, upisujem u niz\n", poruka.rednibroj);
   
   semop(semid, &PMUTEX, 1);
   nizRezultat[poruka.rednibroj-1]=rezultat;
   semop(semid, &VMUTEX, 1);
    printf("Radni cvor %d: Zavrseno. Prijavljuujem se za novi zadatak\n", poruka.rednibroj);
     semop(semid, &V_ZAVRSENI_ZADACI_RC, 1);
   }
}