package ru.dbotthepony.kstarbound.math.matrix

class Matrix4dStack {
	private val stack = ArrayDeque<Matrix4d>()

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

	fun clear(top: Matrix4d): Matrix4dStack {
		stack.clear()
		stack.addLast(top.copy())
		return this
	}

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

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

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

	fun push(matrix: Matrix4d): Matrix4dStack {
		stack.addLast(matrix.copy())
		return this
	}

	fun identity() = push(Matrix4d.identity())
	fun zero() = push(Matrix4d.all(0.0))
	fun all(value: Double) = push(Matrix4d.all(value))

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

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