package ru.dbotthepony.mc.otm.container

import it.unimi.dsi.fastutil.objects.ObjectSpliterator
import it.unimi.dsi.fastutil.objects.ObjectSpliterators
import net.minecraft.world.Container
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.core.collect.AwareItemStack
import ru.dbotthepony.mc.otm.core.collect.ContainerItemStackEntry
import java.util.stream.Stream
import java.util.stream.StreamSupport

class ContainerSpliterator(private val container: Container, offset: Int = 0, private val maxPos: Int = container.containerSize) : ObjectSpliterators.AbstractIndexBasedSpliterator<ItemStack>(offset) {
	init {
		require(offset >= 0) { "Invalid offset $offset" }
		require(offset + maxPos <= container.containerSize) { "$offset -> $maxPos while having only size of ${container.containerSize}!" }
	}

	override fun get(location: Int): ItemStack {
		return container[location]
	}

	override fun getMaxPos(): Int {
		return maxPos
	}

	override fun makeForSplit(pos: Int, maxPos: Int): ObjectSpliterator<ItemStack> {
		return ContainerSpliterator(container, pos, maxPos)
	}
}

class AwareContainerSpliterator(private val container: Container, offset: Int = 0, private val maxPos: Int = container.containerSize) : ObjectSpliterators.AbstractIndexBasedSpliterator<AwareItemStack>(offset) {
	init {
		require(offset >= 0) { "Invalid offset $offset" }
		require(offset + maxPos <= container.containerSize) { "$offset -> $maxPos while having only size of ${container.containerSize}!" }
	}

	override fun get(location: Int): AwareItemStack {
		return ContainerItemStackEntry(location, container)
	}

	override fun getMaxPos(): Int {
		return maxPos
	}

	override fun makeForSplit(pos: Int, maxPos: Int): ObjectSpliterator<AwareItemStack> {
		return AwareContainerSpliterator(container, pos, maxPos)
	}
}

fun Container.spliterator(offset: Int = 0) = ContainerSpliterator(this, offset)
fun Container.awareSpliterator(offset: Int = 0) = AwareContainerSpliterator(this, offset)
fun Container.stream(offset: Int = 0): Stream<out ItemStack> = StreamSupport.stream(spliterator(offset), false)
fun Container.awareStream(offset: Int = 0): Stream<out AwareItemStack> = StreamSupport.stream(awareSpliterator(offset), false)
