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

import it.unimi.dsi.fastutil.objects.ObjectArrayList
import net.minecraft.util.RandomSource
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.shuffle
import java.util.function.Supplier

class CapabilityListIterator<T>(
	val provider: Supplier<out List<T>>,
	val random: Supplier<RandomSource?>,
) {
	private var shuffleCache = IntArray(0)

	private fun doIterate(values: List<T>, value: Decimal, simulate: Boolean, walker: T.(Decimal, Boolean) -> Decimal, indexProvider: () -> IntIterator): Decimal {
		var leftover = value

		for (index in indexProvider()) {
			val provider = values[index]
			leftover -= walker(provider, leftover, true)
			if (leftover.signum() <= 0) break
		}

		if (simulate) return value - leftover

		leftover = value

		for (index in indexProvider()) {
			val provider = values[index]
			leftover -= walker(provider, leftover, false)
			if (leftover.signum() <= 0) break
		}

		return value - leftover
	}

	fun iterate(value: Decimal, simulate: Boolean, walker: T.(Decimal, Boolean) -> Decimal): Decimal {
		val providers = provider.get()
		if (providers.isEmpty()) return Decimal.ZERO
		val random = random.get()

		if (random == null || providers.size == 1) {
			return doIterate(providers, value, simulate, walker, providers.indices::iterator)
		} else {
			if (shuffleCache.size != providers.size) {
				shuffleCache = IntArray(providers.size) { it }
			}

			shuffleCache.shuffle(random)
			return doIterate(providers, value, simulate, walker, shuffleCache::iterator)
		}
	}
}
