#include <psemek/ui/container_impl.hpp>

namespace psemek::ui
{

	element::children_range container_impl::children() const
	{
		return element::children_range{children_range_.data(), children_range_.data() + children_range_.size()};
	}

	bool container_impl::empty() const
	{
		return children_.empty();
	}

	std::size_t container_impl::size() const
	{
		return children_.size();
	}

	void container_impl::resize(std::size_t new_size)
	{
		auto old_size = children_.size();
		for (std::size_t i = new_size; i < old_size; ++i)
			remove(i);
		children_.resize(new_size);
		children_range_.resize(new_size);
		for (std::size_t i = old_size; i < new_size; ++i)
			children_range_[i] = nullptr;
	}

	std::size_t container_impl::add(std::shared_ptr<element> c)
	{
		std::size_t index = 0;
		while (index < children_.size() && children_[index]) ++index;
		add(std::move(c), index);
		return index;
	}

	void container_impl::add(std::shared_ptr<element> c, std::size_t index)
	{
		if (index >= children_.size())
			resize(index + 1);

		children_[index] = std::move(c);
		if (children_[index]) children_[index]->set_parent(parent_);
		children_range_[index] = children_[index].get();
	}

	std::shared_ptr<element> container_impl::get(std::size_t index) const
	{
		if (index < children_.size())
			return children_[index];
		return nullptr;
	}

	std::optional<std::size_t> container_impl::find(element * c) const
	{
		for (std::size_t i = 0; i < children_.size(); ++i)
		{
			if (children_[i].get() == c)
				return i;
		}
		return std::nullopt;
	}

	std::shared_ptr<element> container_impl::remove(element * c)
	{
		if (auto i = find(c))
			return remove(*i);
		return nullptr;
	}

	std::shared_ptr<element> container_impl::remove(std::size_t index)
	{
		if (index >= children_.size())
			return nullptr;

		auto c = std::move(children_[index]);
		children_range_[index] = nullptr;
		if (c) c->set_parent(nullptr);
		return c;
	}

	void container_impl::clear()
	{
		for (std::size_t i = 0; i < children_.size(); ++i)
			remove(i);

		children_.clear();
		children_range_.clear();
	}

}
