package ru.dbotthepony.kstarbound.math.matrix

class Matrix3dStack {
	private val stack = ArrayDeque<Matrix3d>()

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

	fun clear(top: Matrix3d): Matrix3dStack {
		stack.clear()
		stack.addLast(top.copy())
		return this
	}

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

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

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

	fun push(matrix: Matrix3d): Matrix3dStack {
		stack.addLast(matrix.copy())
		return this
	}

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

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

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