#pragma once

#include <iterator>

namespace psemek::util
{

	template <typename Gen>
	struct lazy_range
	{
		Gen generator;

		lazy_range(Gen gen)
			: generator(std::move(gen))
		{}

		using value_type = decltype(generator());

		struct iterator
		{
			using iterator_category = std::input_iterator_tag;

			lazy_range & range;

			value_type value;

			value_type const & operator*()
			{
				return value;
			}

			iterator & operator++()
			{
				value = range.generator();
				return *this;
			}
		};

		iterator begin()
		{
			return {*this, generator()};
		}

		struct sentinel
		{
			using iterator_category = std::input_iterator_tag;
		};

		sentinel end()
		{
			return {};
		}

		friend bool operator == (iterator const &, sentinel)
		{
			return false;
		}

		friend bool operator != (iterator const &, sentinel)
		{
			return true;
		}
	};

}
