package ru.dbotthepony.mc.otm.capability.energy

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 CombinedEnergyStorage(
	final override val energyFlow: FlowDirection,
	provider: Supplier<out List<IMatteryEnergyStorage>>,
	random: Supplier<RandomSource?> = Supplier { null }
) : IMatteryEnergyStorage {
	val iterator = CapabilityListIterator(provider, random)

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

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

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

	/*
	final override fun extractEnergyChecked(howMuch: Decimal, simulate: Boolean): Decimal {
		return iterator.iterate(howMuch, simulate, IMatteryEnergyStorage::extractEnergyChecked)
	}

	final override fun receiveEnergyChecked(howMuch: Decimal, simulate: Boolean): Decimal {
		return iterator.iterate(howMuch, simulate, IMatteryEnergyStorage::receiveEnergyChecked)
	}
	 */

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

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

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

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