/*
* Copyright 2023, Ali Arya
* Anyone Can Code: Algorithmic Thinking
* Example 5.8c
*/

//simple program demonstrating queues
//source (with modifications):
//https://www.tutorialspoint.com/data_structures_algorithms/queue_program_in_c.htm

#include <stdio.h>
#include <iostream>
using namespace std;

#define MAX 6

/////////////////////////////////////////////////////////////////
// array processing functions 
/////////////////////////////////////////////////////////////////

//shifting up the members from index1 to index2 (inclusive)
void ShiftUp(int Data[], int index1, int index2)
{
	for (int i = index2; i >= index1; i--)
	{
		Data[i + 1] = Data[i];	//possible error if index2 is the last member of the array
	}
}
//shifting down the members from index1 to index2 (inclusive)
void ShiftDown(int Data[], int index1, int index2)
{
	for (int i = index1; i <= index2; i++)
	{
		Data[i - 1] = Data[i];	//possible error if index1 is the first member of the array
	}
}
void Insert(int Data[], int len, int index, int value)
{
	//move up all members from insertion point
	//this copies the member at index to index+1
	ShiftUp(Data, index, len - 1);
	//now add the new value
	Data[index] = value;
}
void Delete(int Data[], int len, int index)
{
	//move down all members after insertion point
	//this overwrites the member at index by index+1
	ShiftDown(Data, index + 1, len - 1);
}
void Print(int Data[], int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << Data[i];
		cout << " ";
	}
	cout << "\n";
}
/////////////////////////////////////////////////////////////////
// queue functions and struct
/////////////////////////////////////////////////////////////////

struct Queue
{
	int data[MAX]; 
	int count;
	int max; 
};

void InitQueue(Queue* q)
{
	q->max = MAX;
	q->count = 0;
	for (int i = 0; i < MAX; i++)
		q->data[i] = -1; //not really necessary but let's assume -1 means unused
}

bool PeekQueue(Queue* q, int* result)
{
	if (q->count > 0)
	{
		*result = q->data[0];
		return true;
	}
	else
	{
		printf("Queue is empty.\n");
		return false;
	}
}

bool DeQueue(Queue* q, int* result) 
{
	if (q->count != 0) 
	{
		*result = q->data[0];
		ShiftDown(q->data, 1, q->count);
		q->count--;
		return true;
	}
	else 
	{
		printf("Could not remove data. Queue is empty.\n");
		return false;
	}
}

bool EnQueue(Queue* q, int newdata)
{
	if (q->count != q->max)
	{
		q->data[q->count] = newdata;
		q->count++;
		return true;
	}
	else
	{
		printf("Could not add data. Queue is full.\n");
		return false;
	}
}

///////////////////////////////////////////////////////////
//main function

int main()
{
	Queue q;
	InitQueue(&q);

	bool quit = false;
	while (quit == false)
	{
		int command;
		cout << "\n >> 0-exit 1-add 2-remove 3-show: ";
		cin >> command;
		if (command == 0)
			quit = true;
		else if (command == 1)
		{
			cout << "enter new data: ";
			cin >> command;
			EnQueue(&q,command);
			Print(q.data, q.count);
		}
		else if (command == 2)
		{
			DeQueue(&q,&command);
			Print(q.data, q.count);
		}
		else if (command == 3)
		{
			Print(q.data,q.count);
		}
	}
}