if (typeof module === 'object' && module.exports)
{
	Debug = {Log:console.log};
}
class Action
{
	constructor()
	{
		this.listeners = new Map();
		this.haveMessaged100 = false;
		this.haveMessaged200 = false;
		this.haveMessaged500 = false;
	}

	addListener(obj, func, multipleListeners /* = false*/)
	{
		if (multipleListeners === undefined) multipleListeners = false;
		if (typeof func !== 'function')
		{
			throw new Error("Bad callback passed to Action");
		}
		
		if (multipleListeners && this.listeners.has(obj))
		{
			var existing = this.listeners.get(obj);
			if (Array.isArray(existing))
			{
				existing.push(func);
			}
			else
			{
				this.listeners.set(obj, [existing, func]);
			}

			if (existing.length > 100 && !this.haveMessaged100)
			{
				Debug.Log("Over 100 function listeners for object!!!" + obj.constructor.name + " func:" + func.name);
				this.haveMessaged100 = true;
			}
			if (existing.length > 200 && !this.haveMessaged200)
			{
				Debug.Log("Over 200 function listeners for object!!!" + obj.constructor.name + " func:" + func.name);
				this.haveMessaged200 = true;
			}
			if (existing.length > 500 && !this.haveMessaged500)
			{
				Debug.Log("Over 500 function listeners for object!!!" + obj.constructor.name + " func:" + func.name);
				this.haveMessaged500 = true;
			}
		}
		else
		{
			this.listeners.set(obj, func);
		}

		if (this.listeners.size > 100 && !this.haveMessaged100)
		{
			Debug.Log("Over 100 object listeners!!! obj:" + obj.constructor.name + " func:" + func.name);
			this.haveMessaged100 = true;
		}
	}

	removeListener(obj, func)
	{
		if (this.listeners.has(obj))
		{
			let potentialListeners = this.listeners.get(obj);
			// multiple listeners
			if (Array.isArray(potentialListeners) && potentialListeners.length > 1 && func !== undefined)
			{
				//if (func !== undefined)
				//{
					potentialListeners.remove(func);
				/*}
				else
				{
					// TODO webgl... tag funcs somehow?
					this.listeners.values[index].shift();
				}*/
			}
			else
			{
				this.listeners.delete(obj);
			}
		}
	}
	
	setListener(obj, func)
	{
		if (!func || !func.apply)
		{
			throw new Error("Bad callback passed to Action");
		}
		this.listeners.clear();
		this.listeners.set(obj, func);
	}
	
	callInternal(objAndFuncs, args)
	{
		for(var i = 0; i < objAndFuncs.length; i++)
        {
        	var obj = objAndFuncs[i][0];
        	var func = objAndFuncs[i][1];
			if (Array.isArray(func))
			{
				for (var j = 0; j < func.length; j++)
				{
					func[j].apply(obj, args);
				}
			}
			else
			{
				func.apply(obj, args);
			}
        }
	}
	
	clearAndCall()
	{
		var tmpListeners = this.listeners;
		this.listeners = new Map();
		this.callInternal(Array.from(tmpListeners.entries()), arguments);
	}

	clear()
	{
		this.listeners = new Map();
	}

	call()
	{
		const tmp = Array.from(this.listeners.entries());
		this.callInternal(tmp, arguments);
	}
	
	clearAndGetCall()
	{
		var tmp = Array.from(this.listeners.entries());

		this.listeners.clear();
		
		var func = (...args) =>
		{
			this.callInternal(tmp, args);
		};
		
		return func;
	}

}

if (typeof module === 'object' && module.exports) module.exports = Action;