#pragma once

#include <psemek/bt/node.hpp>

#include <optional>

namespace psemek::bt
{

	template <typename Tree, typename EventFn>
	struct on_event_node;

	template <typename Time, typename Event, typename ... Args, typename EventFn>
	struct on_event_node<tree<Time, Event, Args...>, EventFn>
		: node<tree<Time, Event, Args...>>
	{
		using tree_type = tree<Time, Event, Args...>;
		using node_type = node<tree_type>;
		using typename node_type::status;

		on_event_node(EventFn && event_fn, node_ptr<tree_type> child)
			: event_fn_(std::move(event_fn))
			, child_(std::move(child))
		{}

		void start(Args ... args) override
		{
			child_->start(args...);
		}

		status update(Time dt, Args ... args) override
		{
			if (cached_status_)
			{
				auto result = *cached_status_;
				cached_status_ = std::nullopt;
				return result;
			}

			return child_->update(dt, args...);
		}

		bool event(Event const & e, Args ... args) override
		{
			cached_status_ = event_fn_(e, args...);
			if (cached_status_)
				return true;
			return child_->event(e, args...);
		}


	private:
		EventFn event_fn_;
		node_ptr<tree_type> child_;
		std::optional<status> cached_status_;
	};

	template <typename Tree, typename EventFn>
	node_ptr<Tree> on_event(EventFn && event_fn, node_ptr<Tree> child)
	{
		return std::make_unique<on_event_node<Tree, EventFn>>(std::move(event_fn), std::move(child));
	}

}
