#pragma once

/**
 * \file ObjectNotifier.h
 * \brief File containing the blitz::ObjectNotifier class
 */

#include <algorithm>
#include <functional>
#include <vector>

namespace blitz {
namespace utils {

/**
 * \class ObjectNotifier
 * \brief Class used to notify listeners
 */
template <typename Listener>
class ObjectNotifier {
  protected:
	std::vector<Listener*> m_Listeners;

  public:
	/**
	 * \brief Binds a listener to notify later
	 */
	void BindListener(Listener* listener) {
		m_Listeners.push_back(listener);
	}

	/**
	 * \brief Unbinds a listener (in case the listener is destroyed for example)
	 */
	void UnbindListener(Listener* listener) {
		auto iter = std::find(m_Listeners.begin(), m_Listeners.end(), listener);

		if (iter == m_Listeners.end())
			return;

		m_Listeners.erase(iter);
	}

	/**
	 * \brief Notify listeners that were bound
	 */
	template <typename Func, typename... Args>
	void NotifyListeners(Func function, Args... args) {
		for (Listener* listener : m_Listeners)
			std::bind(function, listener, args...)();
	}
};

}  // namespace utils
}  // namespace blitz
