#include <stdio.h>
#include <stdlib.h>

typedef struct deque {
  int capacity;
  int front;
  int rear;
  int* arr;
} deque;

deque* new_deque(int capacity) {
  // capacity > 1
  deque* res = malloc(sizeof(deque));
  int* arrray = malloc(sizeof(int) * capacity);

  res->arr = arrray;
  res->rear = 0;
  res->front = 1;
  res->capacity = capacity;

  return res;
}

void remove_deque(deque *de) {
  free(de->arr);
  free(de);
}

int front_it (deque *de, int step) {
  int after = (de->front + step + de->capacity) % de->capacity;
  // check for after
  if (after == de->rear) {
    if (step == 1) {
      printf("ERROR: capacity overload\n");
      exit(1);
    } else {
      printf("ERROR: The array is already empty\n");
      exit(2);
    }
  }
  de->front = after;
  return after;
}

void push (int x, deque* de) {
  // insert item x to the front end of deque
  de->arr[front_it(de, 1)] = x;
}

int pop (deque* de) {
  // remove the front item and return it.
  int val = de->arr[de->front];
  front_it(de, -1);
  return val;
}

int rear_it (deque *de, int step) {
  int after = (de->rear + step + de->capacity) % de->capacity;
  // check for after
  if (after == de->front) {
    if (step == -1) {
      printf("ERROR: capacity overload\n");
      exit(1);
    } else {
      printf("ERROR: The array is already empty\n");
      exit(2);
    }
  }
  de->rear = after;
  return after;
}

void inject (int x, deque* de) {
  // rear end
  de->arr[rear_it(de, -1)] = x;
}

int eject (deque *de) {
  // rear end
  int val = de->arr[de->rear];
  rear_it(de, 1);
  return val;
}

int main(void) {
  deque* test = new_deque(5);
  push(1, test);
  push(2, test);
  push(3, test);
  printf("%d\n", pop(test));
  printf("%d\n", pop(test));
  printf("%d\n", pop(test));
  inject(4, test);
  inject(5, test);
  printf("REAR: %d\n", eject(test));
  printf("REAR: %d\n", eject(test));

  remove_deque(test);
  return 0;
}