// Template class for a stack.
// By DreamVB 23:30 01/11/2016

#include <iostream>
#include <string>

using namespace std;
using std::cout;
using std::endl;

#define MAX_STACK 256

template<typename T> class TStack{
	private:
		int tos = -1;
		T sItem;
		T _Items[MAX_STACK];
	public:
		TStack(){
			this->tos = -1;
		}

		template<typename T> TStack::TStack(const TStack& thestack){
			copy(thestack);
		}

		const bool IsFull()const{
			return tos == MAX_STACK - 1;
		}
		const bool IsEmpty() const{
			return tos == -1;
		}
		void Push(T item){
			this->tos++;
			this->_Items[tos] = item;
		}
		T Pop(){
			T _item = this->_Items[tos];
			this->tos--;
			return _item;
		}
		T Peek(){
			return this->_Items[tos];
		}
};

int main(int argc, char *argv[]){
	int i = 1;
	string strline = "";
	char *words[] = { "This", "Can", "World", "Night", "Sunrise", "Fields" };
	TStack<int>stk;
	TStack<char*>wstack;
	TStack<char>letters;

	cout << "Stack for numbers :" << endl;
	//Add 5 times table to the stack.
	while (i <= 12){
		stk.Push(i * 5);
		i++;
	}

	//Print numbers out
	while (!stk.IsEmpty()){
		cout << "Number : " << stk.Pop() << endl;
	}
	cout << endl;

	//Retset i
	i = 0;

	cout << "Stack showing words :" << endl;
	//Push words onto stack
	for (auto word : words){
		wstack.Push(word);
	}

	//Print out words.
	while (!wstack.IsEmpty()){
		cout << "Word : " << wstack.Pop() << endl;
	}
	
	cout << "Enter a string of text : ";
	std::getline(cin, strline);

	//Push chars onto the letters stack.
	while (i < strline.length()){
		letters.Push(strline[i]);
		i++;
	}
	cout << endl;

	TStack<char>temp(letters);
	
	i = 0;
	//Show letters reverse order
	cout << "Reverse order" << endl;
	while (!letters.IsEmpty()){
		cout << "Char : [" << (i + 1) << "] " << letters.Pop() << endl;
		i++;
	}

	while (!temp.IsEmpty()){
		letters.Push(temp.Pop());
	}

	cout << endl;

	i = 0;
	//Show letters original order
	cout << "Original order" << endl;
	while (!letters.IsEmpty()){
		cout << "Char : " << (i + 1) << " " << letters.Pop() << endl;
		i++;
	}

	system("pause");
	return 0;
}