#include "imgui_sdl.h"

#include "SDL.h"

#include "imgui.h"

#include <map>
#include <list>
#include <cmath>
#include <array>
#include <vector>
#include <memory>
#include <iostream>
#include <algorithm>
#include <functional>
#include <unordered_map>

namespace
{
	// make_unique is C++14
	template<typename T, typename... Args>
	std::unique_ptr<T> make_unique(Args&&... args)
	{
		return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
	}

	struct Device* CurrentDevice = nullptr;

	namespace TupleHash
	{
		template <typename T> struct Hash
		{
			std::size_t operator()(const T& value) const
			{
				return std::hash<T>()(value);
			}
		};

		template <typename T> void CombineHash(std::size_t& seed, const T& value)
		{
			seed ^= TupleHash::Hash<T>()(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
		}

		template <typename Tuple, std::size_t Index = std::tuple_size<Tuple>::value - 1> struct Hasher
		{
			static void Hash(std::size_t& seed, const Tuple& tuple)
			{
				Hasher<Tuple, Index - 1>::Hash(seed, tuple);
				CombineHash(seed, std::get<Index>(tuple));
			}
		};

		template <typename Tuple> struct Hasher<Tuple, 0>
		{
			static void Hash(std::size_t& seed, const Tuple& tuple)
			{
				CombineHash(seed, std::get<0>(tuple));
			}
		};

		template <typename... T> struct Hash<std::tuple<T...>>
		{
			std::size_t operator()(const std::tuple<T...>& value) const
			{
				std::size_t seed = 0;
				Hasher<std::tuple<T...>>::Hash(seed, value);
				return seed;
			}
		};
	}

	template <typename Key, typename Value, std::size_t Size> class LRUCache
	{
	public:
		bool Contains(const Key& key) const
		{
			return Container.find(key) != Container.end();
		}

		const Value& At(const Key& key)
		{
			assert(Contains(key));

			const auto location = Container.find(key);
			Ord