#include <stdio.h>
#define SIZE 10

typedef struct
{
	int rear;
	int front;
	int arr[SIZE];
} cque;

void init_queue(cque *queue);
int is_full(cque *queue);
int is_empty(cque *queue);
int queue_first(cque *queue);
int queue_last(cque *queue);
int enqueue(cque *queue, int val);
int dequeue(cque *queue);
int queue_size(cque *queue);
void print_queue(cque *queue);


int main(void)
{
    cque queue;
    init_queue(&queue);
    enqueue(&queue, 3);
    enqueue(&queue, 4);
    enqueue(&queue, 5);
    printf("Size: %d\n", queue_size(&queue));
    print_queue(&queue);
    enqueue(&queue, 6);
    enqueue(&queue, 7);
    enqueue(&queue, 8);
    enqueue(&queue, 9);
    enqueue(&queue, 10);
    enqueue(&queue, 11);
    enqueue(&queue, 12);
    dequeue(&queue);
	dequeue(&queue);
	dequeue(&queue);
	printf("Size: %d\n", queue_size(&queue));
    print_queue(&queue);
    enqueue(&queue, 13);
	enqueue(&queue, 14);
    print_queue(&queue);
	dequeue(&queue);
	dequeue(&queue);
	dequeue(&queue);
	dequeue(&queue);
	dequeue(&queue);
	dequeue(&queue);
	dequeue(&queue);
	dequeue(&queue);
	dequeue(&queue);
	dequeue(&queue);
	printf("Size: %d\n", queue_size(&queue));
    print_queue(&queue);
    dequeue(&queue);
	dequeue(&queue);
	
    return 0;

}

void init_queue(cque *queue)
{
	queue->front = queue->rear = -1;
}

int is_full(cque *queue)
{
	if((queue->front == 0 && queue->rear == SIZE-1) || (queue->rear == (queue->front)-1))
	{
		printf("Queue is full!\n");
		return 1;
	}
	return 0;
}

int is_empty(cque *queue)
{
	if(queue->front == -1)
	{
		printf("Queue is empty!\n");
		return 1;
	}
	return 0;
}

int queue_first(cque *queue)
{
	if (is_empty(queue))
	{
		printf("Queue is empty!\n");
		return -1;
	}
	return queue->arr[queue->front];
}

int queue_last(cque *queue)
{
	if (is_empty(queue))
	{
		printf("Queue is empty!\n");
		return -1;
	}
	return queue->arr[queue->rear];
}

int enqueue(cque *queue, int val)
{
	if (is_full(queue))
	{
		printf("Queue is Full!\n");
        return -1;
	}
	else if (is_empty(queue))
	{
        queue->front = queue->rear = 0;
        queue->arr[queue->rear] = val;
        return 1;
    }
	else if (queue->rear == SIZE-1 && queue->front != 0)
    {
        queue->rear = 0;
        queue->arr[queue->rear] = val;
        return 1;
    }
    else
    {
        (queue->rear)++;
        queue->arr[queue->rear] = val;
        return 1;
    }
}

int dequeue(cque *queue)
{
	if (is_empty(queue))
    {
        printf("Queue is Empty\n");
        return -1;
    }
    int data = queue->arr[queue->front];
    
    
    if (queue->front == queue->rear)
    {
		queue->front = -1;
		queue->rear = -1;
	}
	else if(queue->front == SIZE-1)
		queue->front = 0;
	else
		(queue->front)++;
	
	return data;
}

int queue_size(cque *queue)
{
	if (queue->rear >= queue->front)
        return queue->rear - queue->front + 1;
    else
		return (SIZE-queue->front+1)+(queue->rear+1);
}

void print_queue(cque *queue)
{
	int i;
	if(is_empty(queue))
		printf("Queue is empty!\n");
	if (queue->rear >= queue->front)
    {
        printf("Queue: ");
		for (i = queue->front; i <= queue->rear; i++)
            printf("%d\t",queue->arr[i]);
        printf("\n");
    }
	else
	{
		printf("Queue: ");
		for (i = queue->front; i < SIZE; i++)
			printf("%d\t", queue->arr[i]);
		for (i = 0; i <= queue-> rear; i++)
			printf("%d\t", queue->arr[i]);
		printf("\n");
	}
}
