#pragma once

#include <cstddef>
#include <iterator>


class Sprite;

namespace container 
{

class DrawQueue
{
	using size_type = size_t;

public:
	class iterator
	{
	public:
		using value_type = Sprite;
		using pointer = Sprite*;
		using reference = Sprite&;
		using difference_type = std::ptrdiff_t;
		using iterator_category = std::random_access_iterator_tag;

		iterator(Sprite*);
		iterator& operator++();
		iterator  operator++(int);
		iterator& operator--();
		iterator  operator--(int);
		iterator  operator+(difference_type) const;
		iterator  operator-(difference_type) const;
		iterator& operator+=(difference_type);
		iterator& operator-=(difference_type);
		difference_type  operator-(iterator) const;
		friend iterator operator+(difference_type, iterator);
		
		Sprite& operator*() const;
		
		Sprite* operator->() const;
		Sprite& operator[](size_type) const;

		bool operator==(iterator) const;
		bool operator!=(iterator) const;
		bool operator>(iterator) const;
		bool operator<(iterator) const;
		bool operator>=(iterator) const;
		bool operator<=(iterator) const;
		private:
		Sprite* m_ptr;
	};

	class const_iterator
	{
	public:
		using value_type = Sprite;
		using difference_type = std::ptrdiff_t;
		using iterator_category = std::random_access_iterator_tag;

		const_iterator(const Sprite*);
		const_iterator& operator++();
		const_iterator  operator++(int);
		const_iterator& operator--();
		const_iterator  operator--(int);

		const Sprite& operator*() const;
		const Sprite* operator->() const;
		const Sprite& operator[](size_type) const;

		bool operator==(const_iterator) const;
		bool operator!=(const_iterator) const;
	private:
		const Sprite* m_ptr;
	};

	DrawQueue() = delete;
	DrawQueue(size_type);
	~DrawQueue();

	Sprite* data() const;

	Sprite* operator->();
	Sprite& operator*();
	Sprite& operator[](size_type);

	const Sprite* cdata() const;

	const Sprite* operator->() const;
	const Sprite& operator*() const;
	const Sprite& operator[](size_type) const;

	inline size_type size() const;

	inline size_type capacity() const;

	void resize(size_type);

	void push(Sprite);

	void pushAndSort(Sprite);

	void sort();

	iterator begin();
	iterator end();

	const_iterator begin() const;
	const_iterator end()   const;

	const_iterator cbegin() const;
	const_iterator cend()   const;
private:
	Sprite* m_data;
	size_type m_size;
	size_type m_capacity;
}; 

}//namespace
