package ru.dbotthepony.kstarbound.util

import ru.dbotthepony.kstarbound.Starbound

object AssetPathStack {
	private val _stack = object : ThreadLocal<ArrayDeque<String>>() {
		override fun initialValue(): ArrayDeque<String> {
			return ArrayDeque()
		}
	}

	private val _fileStack = object : ThreadLocal<ArrayDeque<String>>() {
		override fun initialValue(): ArrayDeque<String> {
			return ArrayDeque()
		}
	}

	private val folderStack: ArrayDeque<String> get() = _stack.get()
	private val fileStack: ArrayDeque<String> get() = _fileStack.get()

	fun push(value: String) {
		if (value.last() == '/') {
			// already folder, we don't have filename
			folderStack.addLast(value)
			fileStack.addLast(value)
		} else {
			folderStack.addLast(value.substringBeforeLast('/') + "/")
			fileStack.addLast(value)
		}
	}

	fun lastFolder() = folderStack.lastOrNull() ?: "/"
	fun lastFile() = fileStack.lastOrNull() ?: "/"

	fun pop() {
		folderStack.removeLast()
		fileStack.removeLast()
	}

	inline operator fun <T> invoke(path: String, block: (String) -> T): T {
		try {
			push(path)
			return block.invoke(path)
		} finally {
			pop()
		}
	}

	fun remap(path: String): String {
		return relativeTo(lastFolder(), path)
	}

	fun remapSafe(path: String): String {
		return relativeTo(lastFolder(), path)
	}

	fun relativeTo(base: String, path: String): String {
		if (path.isNotEmpty() && path[0] == '/')
			return path

		return if (base.endsWith('/')) "$base$path" else "$base/$path"
	}
}
