package ru.dbotthepony.mc.otm.capability.matter

import net.minecraft.util.RandomSource
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.core.collect.map
import ru.dbotthepony.mc.otm.core.collect.reduce
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.util.CapabilityListIterator
import java.util.function.Supplier

open class CombinedMatterStorage(
	final override val matterFlow: FlowDirection,
	provider: Supplier<out List<IMatterStorage>>,
	random: Supplier<RandomSource?> = Supplier { null }
) : IMatterStorage {
	val iterator = CapabilityListIterator(provider, random)

	val provider get() = iterator.provider
	val random get() = iterator.random

	final override var storedMatter: Decimal
		get() = provider.get().iterator().map { it.storedMatter }.reduce(Decimal.ZERO, Decimal::plus)
		set(value) {
			throw UnsupportedOperationException()
		}
	final override val maxStoredMatter: Decimal
		get() = provider.get().iterator().map { it.maxStoredMatter }.reduce(Decimal.ZERO, Decimal::plus)

	final override fun receiveMatter(howMuch: Decimal, simulate: Boolean): Decimal {
		return iterator.iterate(howMuch, simulate, IMatterStorage::receiveMatter)
	}

	final override fun extractMatter(howMuch: Decimal, simulate: Boolean): Decimal {
		return iterator.iterate(howMuch, simulate, IMatterStorage::extractMatter)
	}

	final override val canSetMatterLevel: Boolean
		get() = false

	final override fun drainMatter(): Boolean {
		var any = false
		provider.get().forEach { any = it.drainMatter() || any }
		return any
	}

	final override fun fillMatter(): Boolean {
		var any = false
		provider.get().forEach { any = it.fillMatter() || any }
		return any
	}

	/*
	final override fun receiveMatterChecked(howMuch: Decimal, simulate: Boolean): Decimal {
		return provider.iterateProviders(random.get(), howMuch, simulate, IMatterStorage::receiveMatterChecked)
	}

	final override fun extractMatterChecked(howMuch: Decimal, simulate: Boolean): Decimal {
		return provider.iterateProviders(random.get(), howMuch, simulate, IMatterStorage::extractMatterChecked)
	}
	 */

	final override val missingMatter: Decimal
		get() = provider.get().iterator().map { it.missingMatter }.reduce(Decimal.ZERO, Decimal::plus)
}
