#pragma once

#include <psemek/bt/node.hpp>

#include <vector>

namespace psemek::bt
{

	template <typename Tree>
	struct selector_node;

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

		selector_node(std::vector<node_ptr<tree_type>> children)
			: children_(std::move(children))
		{}

		void start(Args ...) override
		{
			current_index_ = 0;
			current_started_ = false;
		}

		status update(Time dt, Args ... args) override
		{
			while (current_index_ < children_.size())
			{
				if (!current_started_)
				{
					children_[current_index_]->start(args...);
					current_started_ = true;
				}

				auto result = children_[current_index_]->update(dt, args...);
				dt = Time{};
				if (auto f = std::get_if<finished>(&result))
				{
					if (f->result)
						return finished{true};
					++current_index_;
					current_started_ = false;
					continue;
				}
				else
					return result;
			}
			return finished{false};
		}

		bool event(Event const & event, Args ... args) override
		{
			if (current_index_ < children_.size())
				return children_[current_index_]->event(event, args...);
			return false;
		}

	private:
		std::vector<node_ptr<tree<Time, Event, Args...>>> children_;
		std::size_t current_index_ = 0;
		bool current_started_ = false;
	};

	template <typename Tree, typename ... Children>
	node_ptr<Tree> selector(node_ptr<Tree> child, Children ... other_children)
	{
		std::vector<node_ptr<Tree>> children;
		children.push_back(std::move(child));
		(children.push_back(std::move(other_children)), ...);
		return std::make_unique<selector_node<Tree>>(std::move(children));
	}

}
