package ru.dbotthepony.kstarbound.math.matrix

class Matrix4fStack {
	private val stack = ArrayDeque<Matrix4f>()

	init {
		stack.addLast(Matrix4f.identity())
	}

	fun clear(top: Matrix4f): Matrix4fStack {
		stack.clear()
		stack.addLast(top.copy())
		return this
	}

	fun push(): Matrix4fStack {
		stack.addLast(stack.last().copy())
		return this
	}

	fun pop(): Matrix4f {
		return stack.removeLast()
	}

	fun last(): Matrix4f {
		return stack.last()
	}

	fun push(matrix: Matrix4f): Matrix4fStack {
		stack.addLast(matrix.copy())
		return this
	}

	fun identity() = push(Matrix4f.identity())
	fun zero() = push(Matrix4f.all(0f))
	fun all(value: Float) = push(Matrix4f.all(value))

	inline fun <T> with(block: Matrix4f.() -> T): T {
		return try {
			push()
			block(last())
		} finally {
			pop()
		}
	}

	inline fun <T> with(matrix: Matrix4f, block: Matrix4f.() -> T): T {
		return try {
			push(matrix)
			block(last())
		} finally {
			pop()
		}
	}
}
