package ru.dbotthepony.mc.otm.core.util

import net.minecraft.util.Mth
import net.minecraft.util.RandomSource
import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian
import net.minecraft.world.level.levelgen.PositionalRandomFactory
import net.minecraft.world.level.levelgen.RandomSupport
import ru.dbotthepony.kommons.random.PCG32Random
import java.lang.StringBuilder

/**
 * @see PCG32Random
 */
class PCG32RandomSource(seed: Long = RandomSupport.generateUniqueSeed()) : PCG32Random(seed), IRandomSourceGenerator {
	private val gaussian = MarsagliaPolarGaussian(this)

	override fun setSeed(seed: Long) {
		this.seed = seed
		gaussian.reset()
	}

	override fun nextGaussian(): Double {
		return gaussian.nextGaussian()
	}

	override fun fork(): RandomSource {
		return PCG32RandomSource(nextLong())
	}

	override fun forkPositional(): PositionalRandomFactory {
		return Positional(nextLong())
	}

	class Positional(private val seed: Long) : PositionalRandomFactory {
		override fun at(x: Int, y: Int, z: Int): RandomSource {
			return PCG32RandomSource(Mth.getSeed(x, y, z).xor(seed))
		}

		override fun fromHashOf(name: String): RandomSource {
			return PCG32RandomSource(name.hashCode().toLong().xor(seed))
		}

		override fun fromSeed(seed: Long): RandomSource {
			return PCG32RandomSource(seed)
		}

		override fun parityConfigString(builder: StringBuilder) {
			throw UnsupportedOperationException()
		}
	}
}
