class Map
{
	constructor(expectedKeyClass)
	{
		this.keys = [];
		this.values = [];

		this.expectedKeyClass = expectedKeyClass;
	}
	
	keysIndexOf(key)
	{
		return this.keys.indexOf(key);
	}

	put(key, value)
	{
		if (this.expectedKeyClass !== undefined)
		{
			if (!(key instanceof this.expectedKeyClass))
			{
				Debug.Log("Warning - Key does not match expected type. Expecting: "+this.expectedKeyClass.constructor.name);
			}
		}

	    var index = this.keysIndexOf(key);
	    if(index == -1)
	    {
	        this.keys.push(key);
	        this.values.push(value);
	    }
	    else 
	    {
	        this.values[index] = value;
	    }
	}

	containsKey(key)
	{
	    return this.keysIndexOf(key) != -1;
	}

	get(key)
	{
	    return this.values[this.keysIndexOf(key)];
	}
	
	getValueOrDefault(key, def)
	{
		var index = this.keysIndexOf(key);
		if (index == -1) return def;
		return this.values[index];
	}
	
	removeIndex(index)
	{
		if (index != -1)
		{
	    	this.values.splice(index, 1);
	        this.keys.splice(index, 1);
		}
	}

	remove(key)
	{
		this.removeIndex(this.keysIndexOf(key));
	}

	get count(){
		return this.keys.length;
	}

	get length(){
		return this.keys.length;
	}

	clear()
	{
		this.keys.length = 0;
		this.values.length = 0;
	}
	
	addRange(m)
	{
		for (var i in m.keys)
		{
			this.put(m.keys[i], m.values[i]);
		}
	}
	
	firstIndexOf(v)
	{
		var index = this.values.indexOf(v);
		if (index == -1) return null;
		return this.keys[index];
	}
}

class MapStrEq extends Map
{
	constructor(expectedKeyClass)
	{
		super(expectedKeyClass);
	}
	keysIndexOf(key)
	{
		for (var i = 0; i < this.keys.length; i++)
		{
			if (this.keys[i].toString() == key.toString()) return i;
		}
		return -1;
	}
}

class MapEq extends Map
{
	constructor(expectedKeyClass)
	{
		super(expectedKeyClass);
	}
	keysIndexOf(key)
	{
		for (var i = 0; i < this.keys.length; i++)
		{
			if (this.keys[i].equals(key)) return i;
		}
		return -1;
	}
}

if (typeof module === 'object' && module.exports) module.exports = { Map, MapStrEq, Map };
