#include "stdafx.h"
#include "CArray.h"

using namespace std;

using namespace std;

//коструктор по замовчуванню
template <typename TData>
CArray<TData>::CArray()
{
	m_Size = 1;
	m_Array = new TData[m_Size];
	for (int i = 0; i < m_Size; i++)
		m_Array[i] = 0;
}

//конструктор з 1 параметром
template <typename TData>
CArray<TData>::CArray(size_t size)
{
	m_Size = size;
	m_Array = new TData[m_Size];
	m_Top = -1; // масив порожній
	for (int i = 0; i < m_Size; i++)
		m_Array[i] = 0 || ' ';
}

//конструктор копіювання
template <typename TData>
CArray<TData>::CArray(const CArray & _array)
{
	m_Array = new CArray<TData>(*(_array.m_Array));
	m_Size = _array.m_Size;
}

//деструктор
template <typename TData>
CArray<TData>::~CArray()
{
	delete[] m_Array;
}

//добавити елемент в кінець масиву
template <typename TData>
void CArray<TData>::push_back(const TData& _value)
{
	m_Top += 1;
	if (m_Array[m_Top] != 0) // чи існує останній елемент
	{
		cout << "> push_back(): Array is fullest. You can't add new element. But you can set new data instead first element." << endl;
		while (true)
		{
			cout << "Do that? (y/n) - ";
			char choose;
			cin >> choose;
			if (choose == 'y')
			{
				m_Array[m_Top] = _value;
				cout << "> push_back(): Element added instead first." << endl;
				break;
			}
			else if (choose == 'n')
			{
				cout << "> push_back(): peration is denied." << endl;
				break;
			}
			else
				cout << "> push_back(): Illegal symbol." << endl;
		}
	}
	else
	{
		cout << "> push_back(): Element added succesfully." << endl;
		m_Array[m_Top] = _value; // записуємо елемент в масив
	}
}

//вставити елемент по індексу
template <typename TData>
void CArray<TData>::insert(unsigned int  _index,const TData& _value)
{
	char choose;
	do
	{
		cout << "Warning! If array is full the last element will be uninstalled. Continue? (y/n) - ";
		cin >> choose;
		if (choose == 'y')
		{
			for (int i = m_Size; i >= _index; i--)
			{
				m_Array[i] = m_Array[i - 1]; //зсуваємо
			}
			m_Array[_index] = _value; //записуємо задані дані
			break;
		}
		else if (choose == 'n')
		{
			cout << "> insert(): Operation is denied." << endl;
			break;
		}
		else
			cout << "> insert(): Illegal symbol." << endl;
	} while (choose != 'n');
}

//видалити елемент по індексу
template <typename TData>
void CArray<TData>::erase(unsigned int _index)
{
	if (m_Array[_index] != 0) //якщо елемент існує
	{
		for (long i = _index; i < m_Size; ++i)
		{
			m_Array[i] = m_Array[i + 1]; //зсуваємо
		}
		m_Array[m_Size - 1] = 0 || '0'; //останній - 0
		cout << "> erase(): Element indexed " << _index << " was erased" << endl;
	}
	else
		cout << "> erase(): Element is not exist." << endl;
}

//очистити масив
template <typename TData>
void CArray<TData>::clear()
{
	char choose;
	do
	{
	cout << "Warning! All items are deleted. Continue? (y/n) - ";
	cin >> choose;
	if (choose == 'y')
	{
		memset(m_Array, 0, m_Size * sizeof(*m_Array));//видаляємо всі елементи
		cout << "> clear(): Array is empty." << endl;
		break;
	}
	else if (choose == 'n')
	{
		cout << "> clear(): Operation is denied." << endl;
		break;
	}
	else
		cout << "> insert(): Illegal symbol." << endl;
	} while (choose != 'n');
}

//повернення розміру масиву
template <typename TData>
unsigned int CArray<TData>::size() const
{
	cout << "> size(): Size of array is ";
	return m_Size;
}

//перевантаження оператора індексування
template <typename TData>
TData& CArray<TData>::operator[](
	unsigned int _index
	)
{
	return m_Array[_index - m_Size];
}

//заповнення масиву
template <typename TData>
void CArray<TData>::SetIntArray()
{
	srand(static_cast<unsigned int>(time(NULL)));
	char choose;
	cout << "Warning! The size of the array is limited. If you do not want to completely fill an array write list the rest of the data as 0." << endl;
	cout << "Do you want to enter data manually or randomly? (m/r) - ";
	cin >> choose;
	while (true)
	{
		if (choose == 'm')
		{
			cout << "Input " << m_Size << " data through space: ";
			for (int i = 0; i < m_Size; i++)
			{
				cin >> m_Array[i]; //заповнити вручну
			}
			break;
		}
		else if (choose == 'r')
		{
			cout << "> SetArray(): Entering data randomly... " << endl;
			for (int i = 0; i < m_Size; i++)
			{
				int val = rand() % 100;
				m_Array[i] = val; //заповнити рандомно
			}
			cout << "> SetArray(): Entered." << endl;
			break;
		}
		else
		{
			cout << "> SetArray(): Illegal symbol.\nDo you want to enter data manually or randomly? (m/r) - ";
			cin >> choose;
		}
	}
}

template <typename TData>
void CArray<TData>::SetStrArray()
{
	srand(static_cast<unsigned int>(time(NULL)));
	char choose;
	cout << "Warning! The size of the array is limited. If you do not want to completely fill an array write list the rest of the data as 0." << endl;
	cout << "Do you want to enter data manually or randomly? (m/r) - ";
	cin >> choose;
	while (true)
	{
		if (choose == 'm')
		{
			cout << "Input " << m_Size << " data through space: ";
			for (int i = 0; i < m_Size; i++)
			{
				cin >> m_Array[i]; //заповнити вручну
			}
			break;
		}
		else if (choose == 'r')
		{
			cout << "> SetArray(): Entering data randomly... " << endl;
			string words[32] = { "cat ", "dog ", "bike ", "moon ", "file ", "language ", "cake ", "resource ",
				"low ", "find ", "break ", "alpha ", "cpp ", "scope ", "target ", "write ", "read ", "test ", "window ", "array ",
				"hight ", "left ", "rigth ", "new ", "old ", "dad ", "mum ", "car ", "plane ", "table ", "computer ", "programming " };
			random_shuffle(begin(words), end(words));
			for (int i = 0; i < m_Size; i++)
				m_Array[i] = words[i]; //заповнити рандомно
			cout << "> SetArray(): Entered." << endl;
			break;
		}
		else
		{
			cout << "> SetArray(): Illegal symbol.\nDo you want to enter data manually or randomly? (m/r) - ";
			cin >> choose;
		}
	}
}

//сортування по зростанню
template <typename TData>
void CArray<TData>::sort()
{
	TData temp;
	int i;
	cout << "> sort(): Sorting array..." << endl;
	for (int x = 1; x < m_Size; x++)
	{
		temp = m_Array[x];
		for (i = x; temp < m_Array[i - 1] && i != 0; i--)
			m_Array[i] = m_Array[i - 1];
		m_Array[i] = temp;
	}
	cout << "> sort(): Sorted." << endl;
}

template <typename TData>
void CArray<TData>::GetArray()
{
	cout << "Array is: ";
	for (int i = 0; i < m_Size; i++)
		cout << setw(4) << m_Array[i];
	cout << endl;
}

//main
//
void intArr();
void stringArr();

int main()
{
	int chooseArr;
	do
	{
		cout << "Main menu:" << endl;
		cout << "0 - Exit." << endl;
		cout << "1 - Create new int array." << endl;
		cout << "2 - Create new string array." << endl;
		cout << "Choose: ";
		cin >> chooseArr;
		switch (chooseArr)
		{
		case 0:
			break;
		case 1:
			intArr();
			break;
		case 2:
			stringArr();
			break;
		default:
			cout << "Illegal symbol." << endl;
			break;
		}
	} while (chooseArr != 0);
	
	return 0;
}

void intArr()
{
	int size, newData, index;
	cout << "Enter size: ";
	cin >> size;

	CArray<int> myIntArray(size);

	int chooseMenu;
	cout << "intArr() function menu:" << endl;
	cout << "0 - Exit." << endl;
	cout << "1 - Put data of array." << endl;
	cout << "2 - Find out array size." << endl;
	cout << "3 - View array." << endl;
	cout << "4 - Push new data." << endl;
	cout << "5 - Insert data." << endl;
	cout << "6 - Erase data." << endl;
	cout << "7 - Clean." << endl;
	cout << "8 - Sort." << endl;
	do
	{
		cout << "Choose: ";
		cin >> chooseMenu;
		switch (chooseMenu)
		{
		case 0:
			break;
		case 1:
			myIntArray.SetIntArray();
			break;
		case 2:
			cout << myIntArray.size() << endl;
			break;
		case 3:
			myIntArray.GetArray();
			break;
		case 4:
			cout << "Enter new data - ";
			cin >> newData;
			myIntArray.push_back(newData);
			break;
		case 5:
			cout << "Enter data - ";
			cin >> newData;
			cout << "Enter index - ";
			cin >> index;
			myIntArray.insert(index, newData);
			break;
		case 6:
			cout << "Enter index to erase - ";
			cin >> index;
			myIntArray.erase(index);
			break;
		case 7:
			myIntArray.clear();
			break;
		case 8:
			myIntArray.sort();
			break;
		default:
			cout << "Illegal symbol." << endl;
			break;
		}
	} while (chooseMenu != 0);
}

void stringArr()
{
	int size, index;
	string newData;
	cout << "Enter size: ";
	cin >> size;

	CArray<string> myStrArray(size);

	int chooseMenu;
	cout << "intArr() function menu:" << endl;
	cout << "0 - Exit." << endl;
	cout << "1 - Put data of array." << endl;
	cout << "2 - Find out array size." << endl;
	cout << "3 - View array." << endl;
	cout << "4 - Insert data." << endl;
	cout << "5 - Clean." << endl;
	cout << "6 - Sort." << endl;
	do
	{
		cout << "Choose: ";
		cin >> chooseMenu;
		switch (chooseMenu)
		{
		case 0:
			break;
		case 1:
			myStrArray.SetStrArray();
			break;
		case 2:
			cout << myStrArray.size() << endl;
			break;
		case 3:
			myStrArray.GetArray();
			break;
		case 4:
			cout << "Enter data - ";
			cin >> newData;
			cout << "Enter index - ";
			cin >> index;
			myStrArray.insert(index, newData);
			break;
		case 5:
			myStrArray.clear();
			break;
		case 6:
			myStrArray.sort();
			break;
		default:
			cout << "Illegal symbol." << endl;
			break;
		}
	} while (chooseMenu != 0);
}