package ru.dbotthepony.mc.otm.storage.powered

import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.storage.IStorageEventConsumer
import ru.dbotthepony.mc.otm.storage.IStorageProvider
import ru.dbotthepony.mc.otm.storage.StorageStack
import ru.dbotthepony.mc.otm.storage.optics.ListenerProxy
import java.math.BigInteger
import java.util.*
import java.util.function.Supplier

class PoweredStorageProvider<T : StorageStack<T>>(val parent: IStorageProvider<T>, val energy: Supplier<IMatteryEnergyStorage>) : IStorageProvider<T> by parent {
	override fun equals(other: Any?): Boolean {
		return other is PoweredStorageProvider<*> && other.parent == parent
	}

	override fun hashCode(): Int {
		return parent.hashCode()
	}

	override fun toString(): String {
		return "PoweredStorageProvider[$parent]"
	}

	override fun addListener(listener: IStorageEventConsumer<T>): Boolean {
		return parent.addListener(ListenerProxy(listener, this))
	}

	override fun removeListener(listener: IStorageEventConsumer<T>): Boolean {
		return parent.removeListener(ListenerProxy(listener, this))
	}

	override fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): T {
		val extracted = parent.extractStack(id, amount, true)
		if (extracted.isEmpty) return extracted

		val energy = energy.get()
		val required = storageType.energyPerExtract(extracted)

		if (energy.extractEnergy(required, true) == required) {
			if (!simulate) {
				val extracted2 = parent.extractStack(id, amount, false)

				if (extracted.count != extracted2.count) {
					energy.extractEnergy(storageType.energyPerExtract(extracted2), false)
				} else {
					energy.extractEnergy(required, false)
				}

				return extracted2
			}

			return extracted
		}

		return storageType.empty
	}
}
