library PPQueue {
  struct Item {
    //    uint idx;
    bool exists;
    uint prev;
    uint next;
  }

  struct Queue {
    uint length;
    uint first;
    uint last;
    uint counter;
    mapping (uint => Item) items;
  }

  /**
   * @dev push item to fifo queue
   */
  function push(Queue storage queue, uint index) internal {
    require(!queue.items[index].exists);
    queue.items[index] = Item({
      exists: true,
      prev: queue.last,
      next: 0
      });

    if (queue.length == 0) {
      queue.first = index;
    } else {
      queue.items[queue.last].next = index;
    }

    //save last item queue idx
    queue.last = index;
    queue.length++;
  }

  /**
  * @dev pop item from fifo queue
  */
  function popf(Queue storage queue) internal returns (uint index) {
    index = queue.first;
    remove(queue, index);
  }

  /**
  * @dev pop item from lifo queue
  */
  function popl(Queue storage queue) internal returns (uint index) {
    index = queue.last;
    remove(queue, index);
  }

  /**
   * @dev remove an item from queue
   */
  function remove(Queue storage queue, uint index) internal {
    require(queue.length > 0);
    require(queue.items[index].exists);


    if (queue.items[index].prev != 0) {
      queue.items[queue.items[index].prev].next = queue.items[index].next;
    } else {
      //assume we delete first item
      queue.first = queue.items[index].next;
    }

    if (queue.items[index].next != 0) {
      queue.items[queue.items[index].next].prev = queue.items[index].prev;
    } else {
      //assume we delete last item
      queue.last = queue.items[index].prev;
    }
    //del from queue
    delete queue.items[index];
    queue.length--;

  }

  /**
  * @dev get queue length
  * @return uint
  */
  function len(Queue storage queue) internal view returns (uint) {
    //auto prevent existing of agents with updated address and same id
    return queue.length;
  }
}
/**
 * @title PPQueue
 */
function push(Queue storage queue, uint index) internal {
  require(!queue.items[index].exists);
  queue.items[index] = Item({
    exists: true,
    prev: queue.last,
    next: 0
    });

  if (queue.length == 0) {
    queue.first = index;
  } else {
    queue.items[queue.last].next = index;
  }

  //save last item queue idx
  queue.last = index;
  queue.length++;
}

/**
 * @dev push item to fifo queue
 */