#ifndef EVENT_HANDLER_HPP
#define EVENT_HANDLER_HPP
#include <core/inc.hpp>
#include <core/event/objects/object_events.hpp>

class event_handler
{
public:
	std::mutex entity_mutex{};
	std::mutex spectators_mutex{};
	std::mutex world_mutex{};

	FORCEINLINE event_handler( ) {}

	void update_object_event( std::uint32_t time, std::chrono::steady_clock::time_point& timestamp, std::function<void( )> task ) 
	{
		auto current_time = std::chrono::steady_clock::now( );

		if ( ( current_time - timestamp ) >= std::chrono::milliseconds( time ) ) {
			task( );
			timestamp = current_time;
		}
	}

	auto tick( ) -> void
	{
		constexpr unsigned int pointers_update_interval = 1;
		constexpr unsigned int actors_update_interval = 1;
		constexpr unsigned int spectators_update_interval = 1;

		auto last_pointer_tick = std::chrono::steady_clock::now( );
		auto last_actors_tick = last_pointer_tick;
		auto last_spectators_tick = last_pointer_tick;

		constexpr std::array<unsigned int, 3> intervals = {
			pointers_update_interval, actors_update_interval, spectators_update_interval
		};

		constexpr unsigned int lowest_interval = *std::min_element( intervals.begin( ), intervals.end( ) );

		for ( ;; )
		{
			this->update_object_event( pointers_update_interval, last_pointer_tick, [ & ] ( ) {
	
				game::u_world m_world {};
				g_ctx->get_network( m_world );
			});

			this->update_object_event( actors_update_interval, last_actors_tick, [ & ] ( ) {

				g_ctx->get_objects( );
			});

			this->update_object_event( spectators_update_interval, last_spectators_tick, [ & ] ( ) {

				g_ctx->get_spectators( );
			});

			std::this_thread::sleep_for( std::chrono::milliseconds( lowest_interval ) );
		}
	}

	auto second_tick( ) -> void
	{
		constexpr unsigned int world_update_interval = 1;

		auto last_world_tick = std::chrono::steady_clock::now( );

		constexpr std::array<unsigned int, 1> intervals = {
			world_update_interval
		};

		constexpr unsigned int lowest_interval = *std::min_element( intervals.begin( ), intervals.end( ) );

		for ( ;; )
		{
			this->update_object_event( world_update_interval, last_world_tick, [ & ] ( ) {

				g_ctx->get_levels( );
			});

			std::this_thread::sleep_for( std::chrono::milliseconds( lowest_interval ) );
		}
	}


}; inline auto g_event_guard = std::make_unique<event_handler>( );

#endif // ! guard