package ru.dbotthepony.mc.otm.graph.storage

import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.entity.BlockEntity
import ru.dbotthepony.mc.otm.addTickerPre
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.graph.Abstract6Graph
import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.core.orNull
import ru.dbotthepony.mc.otm.storage.*
import java.util.LinkedList

class StorageGraph : Abstract6Graph<StorageNode, StorageGraph>() {
	private val virtualComponents = Object2ObjectArrayMap<StorageStackType<*>, VirtualComponent<*>>()
	val powerDemandingNodes = LinkedList<IMatteryEnergyStorage>()

	/**
	 * Returns a [VirtualComponent] representing [type] storage
	 */
	fun <T : IStorageStack> getVirtualComponent(type: StorageStackType<T>): VirtualComponent<T> {
		return virtualComponents.computeIfAbsent(type, Object2ObjectFunction { VirtualComponent(type) }) as VirtualComponent<T>
	}

	/**
	 * Returns a [VirtualComponent] representing [type] storage
	 */
	fun <T : IStorageStack> getVirtualComponent(type: Class<T>): VirtualComponent<T> {
		return virtualComponents.computeIfAbsent(StorageRegistry.get(type), Object2ObjectFunction { VirtualComponent(type) }) as VirtualComponent<T>
	}

	fun <T : IStorageStack> add(storage: IStorage<T>) {
		getVirtualComponent(storage.storageType).add(storage)
	}

	fun <T : IStorageStack> remove(storage: IStorage<T>) {
		getVirtualComponent(storage.storageType).remove(storage)
	}

	fun <T : IStorageStack> contains(storage: IStorage<T>): Boolean {
		val virtual = virtualComponents[storage.storageType] ?: return false
		return (virtual as VirtualComponent<T>).contains(storage)
	}

	override fun onNodeAdded(node: StorageNode) {
		//node.attachComponents(this)
	}

	override fun onNodeRemoved(node: StorageNode) {
		//node.removeComponents(this)
	}

}
