#pragma once

#include <psemek/util/clock.hpp>
#include <psemek/log/level.hpp>

#include <string_view>

namespace psemek::prof
{

	void dump(log::level level = log::level::info);

	struct profiler
	{
		profiler(std::string_view name);
		profiler(profiler && other);
		profiler(profiler const & other) = delete;

		profiler & operator = (profiler && other);
		profiler & operator = (profiler const & other) = delete;

		~profiler();

		static void start_frame(std::string_view name);
		static void push(std::string_view name, std::chrono::duration<double> duration, std::size_t count = 1);
		static void end_frame(std::chrono::duration<double> duration);

		template <typename Duration>
		static void push(std::string_view name, Duration duration, std::size_t count = 1)
		{
			push(name, std::chrono::duration_cast<std::chrono::duration<double>>(duration), count);
		}

		double duration() const
		{
			return clock_.count();
		}

	private:
		util::clock<std::chrono::duration<double>, std::chrono::high_resolution_clock> clock_;
		bool moved_out_ = false;

		void report();
	};

}

#define profile_function [[maybe_unused]] ::psemek::prof::profiler prof ## __LINE__ (__PRETTY_FUNCTION__)
