class MinHeap
{

	constructor(initialLayers)
	{
		this.heap = [];
		this.levels = 0;
		this.nextSlot = 0;
		this._size = 0;

		if (initialLayers == 0) initialLayers = 1;
		for (var i = 0; i < Math.pow(2, initialLayers) - 1; i++) this.heap[i] = null;
		//this.heap = new Vector.<Object>(Math.pow(2, initialLayers) - 1, false);
	}

	add(p)
	{
		if (this.heap.length == this.size)
		{
			var l = this.heap.length;
			for (var i = l; i < l * 2 + 1; i++)
			{
				this.heap[i] = null;
			}
		}

		this.heap[this.nextSlot] = p;
		p.position = this.nextSlot;
		if (this.nextSlot != 0)
		{
			this.fixUp(this.nextSlot);
		}
		this.nextSlot++;
		this._size++;
	}
	
	elementAt(i)
	{
		return this.heap[i];
	}
	
	decreaseKey(p)
	{
		this.fixUp(p.position);
	}
	
	fixUp(test)
	{
		var par = Math.floor((test - 1) / 2);
		var p = this.heap[test];
		while (test != 0 && this.heap[par].priority > p.priority)
		{
			var t = this.heap[par];
			this.heap[par] = p;
			this.heap[test] = t;
			t.position = test;
			p.position = par;
			test = par;
			par = Math.floor((test - 1) / 2);
		}
	}
	
	fixDown(test)
	{
		var c1 = 2 * test + 1;
		var c2 = 2 * test + 2;
		var p = this.heap[test];
		while ((c1 < this.size && p.priority > this.heap[c1].priority) || (c2 < this.size && p.priority > this.heap[c2].priority))
		{
			var swap = c1;
			if (c2 < this.size && this.heap[c2].priority < this.heap[c1].priority) swap = c2;
			var t = this.heap[swap];
			this.heap[swap] = p;
			this.heap[test] = t;
			t.position = test;
			p.position = swap;
			test = swap;
			c1 = 2 * test + 1;
			c2 = 2 * test + 2;
		}
	}
	
	pop()
	{
		if (this.size == 0) return null;
		var t = this.heap[0];
		this.heap[0] = this.heap[this.nextSlot - 1];
		this._size--;
		this.fixDown(0);
		this.nextSlot--;			
		return t;
	}

	get size()
	{
		return this._size;
	}
}

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