#ifndef VECTOR_HPP
# define VECTOR_HPP

# include "colors.h"
# include <iostream>
# include <string>
# include <memory>		// std::allocator
# include <algorithm>	// std::min, std::max
# include <stdexcept>	// out_of_range, length_error, logic_error
# include <cstddef>		// NULL, std::size_t, std::ptrdiff_t

# include "enable_if.hpp"
# include "is_integral.hpp"
# include "reverse_iterator.hpp"
# include "equal.hpp"
# include "lexicographical_compare.hpp"

namespace ft {

template <
	class T,
	class Allocator = std::allocator<T> >
class vector {

public:

	typedef T										value_type;
	typedef Allocator								allocator_type;
	typedef std::size_t								size_type;
	typedef std::ptrdiff_t							difference_type;

	typedef T *										iterator;
	typedef T const *								const_iterator;
	typedef ft::reverse_iterator<iterator>			reverse_iterator;
	typedef ft::reverse_iterator<const_iterator>	const_reverse_iterator;

	//	dependent qualified name :
	//	https://en.cppreference.com/w/cpp/keyword/typename
	typedef typename Allocator::reference			reference;
	typedef typename Allocator::const_reference		const_reference;



	/************
	 * copliens :
	 ************/
// constructors ------------------------------
	explicit vector (const allocator_type & alloc = allocator_type());
	explicit vector (size_type n, const value_type& val = value_type(),
			const allocator_type& alloc = allocator_type());
	template <class InputIterator>
		vector (InputIterator first, InputIterator last,
			const allocator_type& alloc = allocator_type());
	vector( vector const & src );
// destructor --------------------------------
	~vector();
// operator= ---------------------------------
	vector &	operator=( vector const & rhs );


	/*************
	 * iterators :
	 *************/
// begin -------------------------------------
	iterator				begin();
	const_iterator			begin() const;
// end ---------------------------------------
	iterator				end();
	const_iterator			end() const;
// rbegin ------------------------------------
	reverse_iterator		rbegin();
	const_reverse_iterator	rbegin() const;
// rend --------------------------------------
	reverse_iterator		rend();
	const_reverse_iterator	rend() const;


	/************
	 * capacity :
	 ************/
// size --------------------------------------
	size_type	size() const;
// max_size ----------------------------------
	size_type	max_size() const;
// resize ------------------------------------
	void		resize(size_type n, value_type val = value_type());
// capacity ----------------------------------
	size_type	capacity() const;
// empty -------------------------------------
	bool		empty() const;
// reserve -----------------------------------
	void		reserve(size_type n);


	/******************
	 * element access :
	 ******************/
// operator[] --------------------------------
	reference		operator[](size_type n);
	const_reference	operator[](size_type n) const;
// at ----------------------------------------
	reference		at(size_type n);
	const_reference	at(size_type n) const;
// front -------------------------------------
	reference		front();
	const_reference	front() const;
// back --------------------------------------
	reference		back();
	const_reference	back() const;


	/*************
	 * modifiers :
	 *************/
// assign ------------------------------------
	template <class InputIterator>
		typename enable_if< !is_integral<InputIterator>::value,void >::type
		assign(InputIterator first, InputIterator last);
	void		assign(size_type n, const value_type& val);
// push_back ---------------------------------
	void		push_back(const value_type & val);
// pop_back ----------------------------------
	void		pop_back();
// insert ------------------------------------
	iterator	insert(iterator position, const value_type& val);
	void		insert(iterator position, size_type n, const value_type& val);
	template <class InputIterator>
		typename enable_if< !is_integral<InputIterator>::value,void >::type
		insert(iterator position, InputIterator first, InputIterator last);
// erase -------------------------------------
	iterator	erase(iterator position);
	iterator	erase(iterator first, iterator last);
// swap --------------------------------------
	void		swap(vector& x);
// clear -------------------------------------
	void		clear();


	/*************
	 * allocator :
	 *************/
// get_allocator -----------------------------
	allocator_type	get_allocator() const;

private:

	size_type		_size;
	size_type		_capacity;
	value_type *	_mem_ptr;
	allocator_type	_allocator;

	void			_destroy(iterator first, iterator last);
	void			_increment_capacity(size_type n);

};


	/************************
	 * non-member functions :
	 ************************/
// operator == -------------------------------
template <class T, class Alloc>
  bool operator== (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
// operator != -------------------------------
template <class T, class Alloc>
  bool operator!= (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
// operator < --------------------------------
template <class T, class Alloc>
  bool operator<  (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
// operator <= -------------------------------
template <class T, class Alloc>
  bool operator<= (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
// operator > --------------------------------
template <class T, class Alloc>
  bool operator>  (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
// operator >= -------------------------------
template <class T, class Alloc>
  bool operator>= (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
// swap (vector) -----------------------------
template <class T, class Alloc>
	void swap (vector<T,Alloc>& x, vector<T,Alloc>& y);


} // namespace ft

# include "vector.tpp"

#endif
