#pragma once
#include "MulticastDelegate.hpp"

// Unused, allows T1(T2, T3...) syntax with a specialisation
template<typename T> class Event;

// Specialisation, allows for Event<ReturnType(ArgType1, ArgType2...)> syntax
// e.g void return event with float parameter: Event<void(float)> AnEvent;
template<typename R, typename... Args>
class Event<R(Args...)> {
public:
	Event<R(Args...)>() {
		delegate = MulticastDelegate<R(Args...)>();
	}
	~Event<R(Args...)>() = default;
	// Subscribe a Delegate of the same funciton signature to the event.
	Event& operator += (Delegate<R(Args...)> subscriber) {
		delegate.Subscribe(subscriber);
		return *this;
	}
	// Unsubscribe a Delegate which has been subscribed to the event.
	// Note: No guarantee is made on unsubscribing lambda expressions, à la c#
	Event& operator -= (Delegate<R(Args...)> subscriber) {
		delegate.Unsubscribe(subscriber);
		return *this;
	}
	// Invoke the event. Returns the return value of the last fired Delegate.
	// No specific order of delegates guaranteed. Syntax: MyEvent(argument);
	R operator () (Args... args) {
		return delegate.Invoke(args...);
	}
	bool IsValid() { return delegate.IsValid(); }
private:
	MulticastDelegate<R(Args...)> delegate;
};
