package ru.dbotthepony.mc.otm.core.collect

class ConditionalSupplierSet<T> : AbstractSet<T> {
	// method without boxing
	fun interface Condition {
		fun check(): Boolean
	}

	private val getters: Array<Pair<Condition, () -> T>>

	constructor(vararg getters: Pair<Condition, () -> T>) : super() {
		this.getters = Array(getters.size) { getters[it] }
	}

	constructor(getters: List<Pair<Condition, () -> T>>) : super() {
		this.getters = Array(getters.size) { getters[it] }
	}

	override val size: Int get() {
		var i = 0

		for (pair in getters) {
			if (pair.first.check()) {
				i++
			}
		}

		return i
	}

	override fun iterator(): Iterator<T> {
		return object : Iterator<T> {
			val parent = getters.iterator()
			private var pair: Pair<Condition, () -> T>? = null

			private fun search() {
				for (pair in parent) {
					if (pair.first.check()) {
						this.pair = pair
						return
					}
				}

				this.pair = null
			}

			init {
				search()
			}

			override fun hasNext(): Boolean {
				return pair != null
			}

			override fun next(): T {
				val pair = pair ?: throw NoSuchElementException()
				search()
				return pair.second.invoke()
			}
		}
	}
}
