package ObjectRecycler
import Stack
import TypeCasting
import MapBounds
import Table
import ErrorHandling

Table objectLists = new Table()

public function unit.recycle()
	let id = GetUnitTypeId(this)
	if objectLists.hasInt(id)
		let stack = objectLists.loadInt(id) castTo Stack<unit>
		stack.push(this)
		this.hide()
		this.setPos(1, 2)
	else
		error("trying to recycle a unit not created by 'getUnit'!")
	

public function getUnit(player p, int id, vec2 pos, angle facing) returns unit
	if objectLists.hasInt(id)
		let stack = objectLists.loadInt(id) castTo Stack<unit>
		return stack.pop()..setFacing(facing)..show()
	else
		objectLists.saveInt(id, (new Stack<unit>() )castTo int)
		return createUnit(p, id, pos, facing)
		
init
	unit u = getUnit(Player(0), 0, vec2(0,0), angle(0))
	u.recycle()

endpackage
package Stack

public class Stack<T>
	private SEntry<T> dummy
	private SEntry<T> top
	private int size = 0

	construct()
		dummy = new SEntry<T>(null, null)
		top = dummy

	// add an element to the end of the list
	function push(T elem)
		top = new SEntry(elem, top)
		size++

	// get & remove the top element
	function pop() returns T
		let val = top
		top = top.prev
		size--
		return val.elem


	// look at the top element
	function peek() returns T
		return top.elem

	// add all elements from elems to this stack
	function addAll(Stack<T> elems)
		for T elem in elems
			push(elem)


	// gets the size of the stack
	function getSize() returns int
		return size

	// get an iterator for this stack
	function iterator() returns SIterator<T>
		return new SIterator(dummy, top)

	ondestroy
		SEntry<T> current = top
		while current != dummy
			let temp = current
			current = current.prev
			destroy temp
		destroy dummy

class SEntry<S>
	S elem
	SEntry<S> prev

	construct(S elem, SEntry<S> prev)
		this.elem = elem
		this.prev = prev

class SIterator<Q>
	SEntry<Q> dummy
	SEntry<Q> current

	construct(SEntry<Q> dummy, SEntry<Q> top)
		this.dummy = dummy
		this.current = top

	// remove the current element from the list
	function remove()
		if current != dummy
			let cp = current.prev
			destroy current
			current = cp


	function hasNext() returns boolean
		return current.prev != dummy

	function next() returns Q
		current = current.prev
		return current.elem

	function close()
		destroy this
endpackage