package me.eater.threedom.utils.joml

import org.joml.*
import org.joml.Vector2d
import org.joml.Vector2f
import org.joml.Vector3d
import org.joml.Vector3f
import org.joml.Vector4d
import org.joml.Vector4f

fun <T : Number> Matrix4dc.setTranslation(x: T, y: T, z: T): Matrix4d =
    Matrix4d(this).setTranslation(x.toDouble(), y.toDouble(), z.toDouble())

val Matrix4dc.translation: Vector3d
    get() = getTranslation(Vector3d())

fun Matrix4dc.mutable(): Matrix4d = if (this is Matrix4d) this else Matrix4d(this)

operator fun Matrix4dc.times(rhs: Matrix4dc) = mul(rhs, Matrix4d())
operator fun Matrix4d.times(rhs: Matrix4dc) = mul(rhs)

@Suppress("FunctionName")
fun Vector2f(x: Number, y: Number) = Vector2f(x.toFloat(), y.toFloat())

@Suppress("FunctionName")
fun Vector2d(x: Number, y: Number) = Vector2d(x.toDouble(), y.toDouble())

fun vec2(x: Number, y: Number) = Vector2f(x, y)
fun vec2d(x: Number, y: Number) = Vector2d(x, y)

@Suppress("FunctionName")
fun Vector3f(x: Number, y: Number, z: Number) = Vector3f(x.toFloat(), y.toFloat(), z.toFloat())

@Suppress("FunctionName")
fun Vector3d(x: Number, y: Number, z: Number) = Vector3d(x.toDouble(), y.toDouble(), z.toDouble())

fun vec3(x: Number, y: Number, z: Number) = Vector3f(x, y, z)
fun vec3d(x: Number, y: Number, z: Number) = Vector3d(x, y, z)

@Suppress("FunctionName")
fun Vector4f(x: Number, y: Number, z: Number, w: Number) =
    Vector4f(x.toFloat(), y.toFloat(), z.toFloat(), w.toFloat())

@Suppress("FunctionName")
fun Vector4d(x: Number, y: Number, z: Number, w: Number) =
    Vector4d(x.toDouble(), y.toDouble(), z.toDouble(), w.toDouble())

fun vec4(x: Number, y: Number, z: Number, w: Number) = Vector4f(x, y, z, w)
fun vec4d(x: Number, y: Number, z: Number, w: Number) = Vector4d(x, y, z, w)

fun Vector2d.toFloat() = vec2(x, y)
fun Vector3d.toFloat() = vec3(x, y, z)
fun Vector4d.toFloat() = vec4(x, y, z, w)

fun Vector2f.toDouble() = vec2d(x, y)
fun Vector3f.toDouble() = vec3d(x, y, z)
fun Vector4f.toDouble() = vec4d(x, y, z, w)

fun Matrix4dc.toFloat() = Matrix4f(this)
fun Matrix3dc.toFloat() =
    Matrix3f(
        m00().toFloat(),
        m01().toFloat(),
        m02().toFloat(),
        m10().toFloat(),
        m11().toFloat(),
        m12().toFloat(),
        m20().toFloat(),
        m21().toFloat(),
        m22().toFloat()
    )


fun Matrix2dc.toFloat() =
    Matrix2f(this.m00().toFloat(), this.m01().toFloat(), this.m10().toFloat(), this.m11().toFloat())

operator fun Vector3dc.compareTo(rhs: Vector3dc): Int {
    for (i in 0 until 3) {
        val c = this[i].compareTo(rhs[i])
        if (c != 0) {
            return c
        }
    }

    return 0
}
