// A linked list of Delegates, able to invoke them all together.
#pragma once
#include "Delegate.hpp"
#include "LinkedList.hpp"
// Unused, allows T1(T2, T3...) syntax with a specialisation
template<typename T> class MulticastDelegate;
// Specialisation, allows MulticastDelegate<ReturnType(ArgType1, ArgType2...)>
// syntax e.g void return event with float parameter:
// MulticastDelegate<void(float)> AnEvent;
template<typename R, typename... Args>
class MulticastDelegate <R(Args...)> : private LinkedList<Delegate<R(Args...)>> {
public:
	MulticastDelegate<R(Args...)>() : LinkedList<Delegate<R(Args...)>> () {}

	void Subscribe(Delegate<R(Args...)> subscriber) {
		Add(subscriber);
	}

	void Unsubscribe(Delegate<R(Args...)> subscriber) {
		if(GetLength() > 0) RemoveFirst(subscriber);
	}

	R Invoke(Args... args) {
		for (int i = 0; i < GetLength(); i++) {
			if (i == GetLength() - 1) return (*this)[i](args...);
			(*this)[i](args...);
		}
	}

	bool IsValid() {
		return this->GetLength() > 0;
	}
};
