#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

/*
 * Insercao de processos em NPRI Ready Queues, uma por prioridade
 * lidos a partir de um ficheiro
 * Remocao por ordem de prioridade decrescente
 *
 * Jose Rogado
 */

#define NPRI 10

// Estrutura para armazenar os processos
typedef struct proc {
  int pid;
  int pri;
  time_t time;
  struct proc *next;
  struct proc *prev;
} proc_t;

// Estrutura Inicio de Lista
typedef struct queue_head {
  struct proc *next;
  struct proc *last;
} queue_t;

// Tabela das Ready Queues
queue_t array_queue[NPRI];

void selecao(void);

int main(int argc, char *argv[])
{
  int i, pri, ret, nprocs=0, pid;
  proc_t *p,*r;
  queue_t *q;
  FILE *file = NULL;

  if (argc != 2) {
    printf("Usage: %s file\n", argv[0]);
    exit(1);
  }
  file = fopen(argv[1], "r");
  if (file == 0) {
    perror("open file");
    exit(1);
  }
  // Inicializacao a zero dos elementos da tabela
  memset(array_queue, 0, NPRI * sizeof(queue_t));

  while(1){
    ret = fscanf(file, "%d", &pri);
    if (ret == EOF) { // Ctrl-D
      printf("Fim de Ficheiro\n");
      break;
    }
    if(pri>9) pri=9;

    if(pri<0) pri=0;

    p = (proc_t *) calloc(1, sizeof( struct proc ) );

    p->pri = pri;
    p->pid = nprocs++;
    p->time = time(NULL);

    q = &array_queue[pri];

    if (q->next == 0) {
      q->next = p;
      q->last = p;
    } else {
      r = q->last;
      r->next = p;
      q->last = p;
    }
    printf("Processo Inserido pid: %d pri: %d time: %d\n", p->pid, p->pri, p->time);
   }

  // Seleccionar todos os processos inseridos por ordem de prioridade
  for (i = 0; i < nprocs; i++)
    selecao();
}

void selecao(){

  int k = 0;
  proc_t *p;
  queue_t *q;

  /*
   * Procurar o processo de maior prioridade nas ready queues
   */
  for (k = 0; k < NPRI; k++) {
    q = &array_queue[k];
    if (q->next != NULL)
      // O processo seleccionado e o primeiro
      // da queue de maior prioridade
      break;
  }
  // Retirar o processo de maior prioridade da lista
  p = q->next;
  q->next = p->next;
  printf ("\nProcesso Seleccionado: pid: %d  pri: %d\n", p->pid , p->pri);
  free(p);
}

