package ru.dbotthepony.kstarbound.world.terrain

import ru.dbotthepony.kstarbound.defs.PerlinNoiseParameters
import ru.dbotthepony.kstarbound.defs.world.TerrainSelectorParameters
import ru.dbotthepony.kstarbound.json.builder.JsonAlias
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.util.random.AbstractPerlinNoise

class PerlinTerrainSelector(data: Data, parameters: TerrainSelectorParameters) : AbstractTerrainSelector<PerlinTerrainSelector.Data>(data, parameters) {
	@JsonFactory
	data class Data(
		@JsonAlias("type")
		val function: PerlinNoiseParameters.Type,
		val octaves: Int,
		@JsonAlias("frequency")
		val freq: Double,
		@JsonAlias("amplitude")
		val amp: Double,
		val bias: Double = 0.0,
		val alpha: Double = 2.0,
		val beta: Double = 2.0,
		val xInfluence: Double = 1.0,
		val yInfluence: Double = 1.0,
	)

	private val seed = parameters.random().nextLong()
	private val perlin by lazy {
		AbstractPerlinNoise.of(
			PerlinNoiseParameters(
			type = data.function,
			octaves = data.octaves,
			frequency = data.freq,
			amplitude = data.amp,
			bias = data.bias,
			alpha = data.alpha,
			beta = data.beta,
		)).also {
			it.init(seed)
		}
	}

	override fun get(x: Int, y: Int): Double {
		return perlin[x * data.xInfluence, y * data.yInfluence]
	}

	override val type: TerrainSelectorType
		get() = TerrainSelectorType.PERLIN
}