package ru.dbotthepony.mc.otm.client.render

import net.minecraft.resources.ResourceLocation

fun ResourceLocation.sprite(
	x: Float,
	y: Float,
	width: Float,
	height: Float,
	textureWidth: Float = 256f,
	textureHeight: Float = 256f
) = MatterySprite(this, x, y, width, height, textureWidth, textureHeight)

fun ResourceLocation.pixel(
	x: Float,
	y: Float,
	textureWidth: Float = 256f,
	textureHeight: Float = 256f
) = MatterySprite(this, x, y, 1f, 1f, textureWidth, textureHeight)

fun ResourceLocation.hLine(
	x: Float,
	y: Float,
	width: Float,
	textureWidth: Float = 256f,
	textureHeight: Float = 256f
) = MatterySprite(this, x, y, width, 1f, textureWidth, textureHeight)

fun ResourceLocation.vLine(
	x: Float,
	y: Float,
	height: Float,
	textureWidth: Float = 256f,
	textureHeight: Float = 256f
) = MatterySprite(this, x, y, 1f, height, textureWidth, textureHeight)

@Suppress("unused")
class MatterySprite(
	override val texture: ResourceLocation,
	val x: Float,
	val y: Float,
	override val width: Float,
	override val height: Float,
	val atlasWidth: Float = 256f,
	val atlasHeight: Float = 256f,
	override val winding: UVWindingOrder = UVWindingOrder.NORMAL,
) : AbstractMatterySprite() {
	init {
		require(x >= 0f) { "Invalid x $x" }
		require(y >= 0f) { "Invalid y $y" }
		require(width > 0f) { "Invalid width $width" }
		require(height > 0f) { "Invalid height $height" }
		require(atlasWidth > 0f) { "Invalid image width $atlasWidth" }
		require(atlasHeight > 0f) { "Invalid image height $atlasHeight" }

		require(x + width <= atlasWidth) { "${x + width} <= $atlasWidth" }
		require(y + height <= atlasHeight) { "${y + height} <= $atlasHeight" }
	}

	override val u0 = this.x / atlasWidth
	override val v0 = this.y / atlasHeight
	override val u1 = (this.x + width) / atlasWidth
	override val v1 = (this.y + height) / atlasHeight

	override val type: SpriteType
		get() = SpriteType.SINGLE

	fun copy(
		x: Float = this.x,
		y: Float = this.y,
		width: Float = this.width,
		height: Float = this.height,
		winding: UVWindingOrder = this.winding,
	): MatterySprite {
		return MatterySprite(texture, x, y, width, height, atlasWidth, atlasHeight, winding)
	}

	companion object {
		fun single(texture: ResourceLocation, width: Float, height: Float, winding: UVWindingOrder = UVWindingOrder.NORMAL): MatterySprite {
			return MatterySprite(texture, 0f, 0f, width, height, width, height, winding)
		}
	}
}

