package ru.dbotthepony.kstarbound.util.random

import ru.dbotthepony.kstarbound.defs.PerlinNoiseParameters
import kotlin.math.absoluteValue

class RidgedNoise(parameters: PerlinNoiseParameters) : AbstractPerlinNoise(parameters) {
	init {
		require(parameters.type == PerlinNoiseParameters.Type.RIDGED_MULTI)
	}

	override fun get(x: Double): Double {
		checkInit()
		var sum = 0.0
		var p = x * parameters.frequency
		var scale = 1.0
		var weight = 1.0

		for (i in 0 until parameters.octaves) {
			var value = noise1(p)
			value = parameters.offset - value.absoluteValue
			value *= value
			value *= weight

			weight = (value * parameters.gain).coerceIn(0.0, 1.0)

			sum += value / scale
			scale *= parameters.alpha
			p *= parameters.beta
		}

		return ((sum * 1.25) - 1.0) * parameters.amplitude + parameters.bias
	}

	override fun get(x: Double, y: Double): Double {
		checkInit()
		var sum = 0.0
		var px = x * parameters.frequency
		var py = y * parameters.frequency
		var scale = 1.0
		var weight = 1.0

		for (i in 0 until parameters.octaves) {
			var value = noise2(px, py)
			value = parameters.offset - value.absoluteValue
			value *= value
			value *= weight

			weight = (value * parameters.gain).coerceIn(0.0, 1.0)

			sum += value / scale
			scale *= parameters.alpha
			px *= parameters.beta
			py *= parameters.beta
		}

		return ((sum * 1.25) - 1.0) * parameters.amplitude + parameters.bias
	}

	override fun get(x: Double, y: Double, z: Double): Double {
		checkInit()
		var sum = 0.0
		var px = x * parameters.frequency
		var py = y * parameters.frequency
		var pz = z * parameters.frequency
		var scale = 1.0
		var weight = 1.0

		for (i in 0 until parameters.octaves) {
			var value = noise3(px, py, pz)
			value = parameters.offset - value.absoluteValue
			value *= value
			value *= weight

			weight = (value * parameters.gain).coerceIn(0.0, 1.0)

			sum += value / scale
			scale *= parameters.alpha
			px *= parameters.beta
			py *= parameters.beta
			pz *= parameters.beta
		}

		return ((sum * 1.25) - 1.0) * parameters.amplitude + parameters.bias
	}
}