const
  capacity = 4;

type
  FIFO = 
    record
      head : integer; { this is the index of the head item }
      size : integer; { this is the number items stored in the FIFO }
      buffer : array [0..capacity - 1] of integer;
    end;

procedure FIFO_initialize(var f : FIFO);
  begin
    f.head := 0;
    f.size := 0
  end;

function FIFO_is_empty(var f : FIFO) : boolean;
  begin
  { if f.size = 0 then
      FIFO_is_empty := true
    else
      FIFO_is_empty := false }

    FIFO_is_empty := (f.size = 0)
  end;

function FIFO_is_full(var f : FIFO) : boolean;
  begin
    FIFO_is_full := (f.size = capacity)
  end;

procedure FIFO_add_item(var f : FIFO; item : integer);
  begin
    { assume FIFO is not full yet }
    f.buffer[(f.head + f.size) mod capacity] := item;

{   if f.head + f.size >= capacity then
      f.buffer[f.head + f.size - capacity] := item
    else
      f.buffer[f.head + f.size] := item; }

    f.size := f.size + 1
  end;

function FIFO_safe_add_item(var f : FIFO; item : integer) : boolean;
  begin
    if FIFO_is_full(f) then
      FIFO_safe_add_item := false
    else
      begin
        FIFO_add_item(f, item);
	FIFO_safe_add_item := true
      end
  end;

procedure FIFO_remove_item(var f : FIFO; var item : integer);
  begin
    { assume FIFO is not empty }
    item := f.buffer[f.head];
{    f.head := (f.head + 1) mod capacity;}

    f.head := f.head + 1;
    if f.head >= capacity then
      f.head := f.head - capacity;
    f.size := f.size - 1
  end;

function FIFO_safe_remove_item(var f : FIFO; var item : integer) : boolean;
  begin
    if FIFO_is_empty(f) then
      FIFO_safe_remove_item := false
    else
      begin
        FIFO_remove_item(f, item);
	FIFO_safe_remove_item := true
      end
  end;

var
  queue : FIFO;
  choice : integer;
  item : integer;

begin
  repeat
    { present choices }
    writeln('select one of the following:');
    writeln('0: exit the program');
    writeln('1: initialize the queue');
    writeln('2: check if the queue is empty');
    writeln('3: check if the queue is full');
    writeln('4: try to add an item to the queue');
    writeln('5: try to remove an item from the queue');

    { accept a valid choice }
    repeat
      write('  enter your choice (0 to 5):');
      readln(choice);
      if (choice > 5) or (choice < 0) then
        writeln('your choice is not valid, please select again')
    until (choice >= 0) and (choice <= 5);

    { perform the chosen operation }
    if choice = 0 then
      writeln('exiting the program')
    else if choice = 1 then
      FIFO_initialize(queue)
    else if choice = 2 then
      writeln('FIFO_is_empty returns ', FIFO_is_empty(queue))
    else if choice = 3 then
      writeln('FIFO_is_full returns ', FIFO_is_full(queue))
    else if choice = 4 then
      begin
        write('enter the value of the item to add to the queue ');
	readln(item);
        if FIFO_safe_add_item(queue,item) then
	  writeln('the operation was successful')
	else
	  writeln('the operation was not successful (queue was full already)')
      end
    else if choice = 5 then
      begin
        if FIFO_safe_remove_item(queue, item) then
	  writeln('the operation was successful, ',item,' is removed.')
	else
	  writeln('the operation was not successful because the queue was empty')
      end
  until choice = 0 { the user wants to exit }
end.

