package ru.dbotthepony.kstarbound.math

import kotlin.math.PI
import kotlin.math.absoluteValue

/**
 * Выполняет преобразование [value] типа [Double] в [Int] так,
 * что выходной [Int] всегда будет больше или равен по модулю [value]
 */
fun roundByAbsoluteValue(value: Double): Int {
	if (value > 0.0) {
		if (value % 1.0 != 0.0) {
			return value.toInt() + 1
		}

		return value.toInt()
	} else if (value == 0.0) {
		return 0
	} else {
		if (value % 1.0 != -0.0) {
			return value.toInt() - 1
		}

		return value.toInt()
	}
}

fun roundTowardsNegativeInfinity(value: Double): Int {
	if (value == 0.0)
		return 0

	if (value > 0.0) {
		return value.toInt()
	}

	if (value % 1.0 != -0.0) {
		return value.toInt() - 1
	}

	return value.toInt()
}

fun roundTowardsPositiveInfinity(value: Double): Int {
	if (value == 0.0)
		return 0

	if (value < 0.0) {
		return value.toInt()
	}

	if (value % 1.0 != 0.0) {
		return value.toInt() + 1
	}

	return value.toInt()
}

fun divideUp(a: Int, b: Int): Int {
	return (a + b - 1) / b
}

private const val EPSILON = 0.00000001

fun weakCompare(a: Double, b: Double, epsilon: Double = EPSILON): Int {
	if (a == b || (a - b).absoluteValue < epsilon) {
		return 0
	}

	if (a > b)
		return 1

	return -1
}

fun weakDoubleZeroing(value: Double, epsilon: Double = EPSILON): Double {
	if (weakCompare(value, 0.0, epsilon) == 0)
		return 0.0

	return value
}

fun angleDifference(angle0: Double, angle1: Double): Double {
	var diff = (angle1 - angle0 + PI) % (PI * 2.0)

	if (diff < 0.0)
		diff += PI * 2.0

	return diff
}

fun normalizeAngle(angle: Double): Double {
	var value = (angle + PI) % (PI * 2.0)

	if (value < 0.0)
		value += PI * 2.0

	return value
}

fun approachAngle(target: Double, current: Double, limit: Double): Double {
	return normalizeAngle(current + angleDifference(current, target).coerceIn(-limit, limit))
}

fun quintic2(t: Float, a: Float, b: Float): Float {
	return a + (b - a) * t * t * t * (t * (t * 6f - 15f) + 10f)
}

fun quintic2(t: Double, a: Double, b: Double): Double {
	return a + (b - a) * t * t * t * (t * (t * 6.0 - 15.0) + 10.0)
}
