
#include <iostream>
#include <string>
#include <iomanip>		// std::setw()
#include <iterator>		// std::reverse_iterator
#include <utility>		// std::make_pair
#include <sstream>		// std::stringstream
#include <vector>
#include <map>
#include <stack>

// toogle ft in stl
#ifdef STL
	namespace ft = std;
#else
	#include "vector.hpp"
	#include "map.hpp"
	#include "stack.hpp"
	#include "reverse_iterator.hpp"
#endif

// defines
# define TEST(s)	template <class T> void s ()
# define TITLE(s)	std::cout << "\n" B_PURPLE #s RESET "\n\n";
# define VAL(n)		val<T>(n)
# define TOI(n)		toi<T>(n)
# define PRINT(n)	print<>(n, #n);
# define DELETE		delete_structs();

// colors
# define GRAY "\e[0;30m"
# define RED "\e[0;31m"
# define GREEN "\e[0;32m"
# define YELLOW "\e[0;33m"
# define BLUE "\e[0;34m"
# define PURPLE "\e[0;35m"
# define CYAN "\e[0;36m"
# define WHITE "\e[0;37m"

# define B_GRAY "\e[1;30m"
# define B_RED "\e[1;31m"
# define B_GREEN "\e[1;32m"
# define B_YELLOW "\e[1;33m"
# define B_BLUE "\e[1;34m"
# define B_PURPLE "\e[1;35m"
# define B_CYAN "\e[1;36m"
# define B_WHITE "\e[1;37m"

# define RESET "\e[0m"

// mystruct declaration
struct mystruct {
public:
	mystruct(int data = 0);
	~mystruct();
	int *	get_data() const;
private:
	int *	_val;
};
std::ostream &	operator<<(std::ostream & o, mystruct const * rhs);

// mystruct definition
mystruct::mystruct(int data)
	{_val = new int[2]; _val[0] = data; _val[1] = data;}
mystruct::~mystruct()
	{delete[] _val;}
int * mystruct::get_data() const
	{return _val;}
std::ostream &	operator<<(std::ostream & o, mystruct const * rhs) {
	if (rhs != NULL)
		o << (*rhs).get_data()[0] << "," << (*rhs).get_data()[1];
	else
		o << "NULL";
	return (o);
}

// global variable for mem gestion of mystruct
std::vector< mystruct* >	mem_list;

// template print function
template <class T, class cont>
	void	print(ft::stack<T,cont>& st, std::string name) {

	std::cout << "\n" << name << ":(map)\n";
	for (int i = st.size(); i > 0 ; i--, st.pop())
		std::cout << "[" << i << "]" << st.top() << " ";
	std::cout << "\nsize:" << st.size() << "\n";
}

// template val() for instanciation of values for types :
// int, char, std::string, and mystruct*
template <class T>
	T val(int n) { (void)n; return (T()); }
template <>
	inline	int val(int n) { return (n); }
template <>
	inline	char val(int n) {
	
	if (n <= 126 && n >= 33)
		return n;
	return (n % 94 + 33);
}
template <>
	inline	std::string val(int n) {

	std::string			str;
	std::stringstream	stream;

	stream << n;
	stream >> str;
	stream.clear();
	return (str);
}
template <>
	inline	mystruct* val(int n) {

	mystruct *s = new mystruct(n);
	mem_list.push_back(s);
	return ( s );
}
template <class T>
	T val(std::string str) { (void)str; return (T()); }
template <>
	inline	int val(std::string str) { int i = str[0]; return (val<int>(i)); }
template <>
	inline	char val(std::string str) { int i = str[0]; return (val<char>(i)); }
template <>
	inline	std::string val(std::string str) { return (str); }
template <>
	inline	mystruct* val(std::string str) { int i = str[0]; return (val<mystruct*>(i)); }

// delete function for mem gestion of mystruct*
void	delete_structs() {
	
	std::vector<mystruct*>::iterator it;
	std::vector<mystruct*>::iterator it_end = mem_list.end();

	for (it = mem_list.begin(); it != it_end; ++it)
		delete *it;
	mem_list.clear();
}

// all tests
TEST(tests_stack_constructor)
{
	// title
	TITLE(simple test)

	std::deque<T> mydeque (3,VAL(100));				// deque with 3 elements
	std::vector<T> myvector (2,VAL(200));			// vector with 2 elements

	ft::stack<T> first;								// empty stack
	ft::stack<T> second (mydeque);					// stack initialized to copy of deque

//	ft::stack< T,std::vector<T> > third;			// empty stack using vector
//	ft::stack< T,std::vector<T> > fourth (myvector);
//
//	std::cout << "size of first: " << first.size() << '\n';
//	std::cout << "size of second: " << second.size() << '\n';
//	std::cout << "size of third: " << third.size() << '\n';
//	std::cout << "size of fourth: " << fourth.size() << '\n';
//
//	PRINT(first)
//	PRINT(second)
//	PRINT(third)
//	PRINT(fourth)
//
//	DELETE
}

template <class T>
void	call_tests() {

	tests_stack_constructor<T>();
}

int	main() {

	call_tests<int>();
//	call_tests<char>();
//	call_tests<std::string>();
//	call_tests<mystruct*>();

	return 0;
}


