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

import java.util.EnumMap
import java.util.function.BooleanSupplier
import java.util.stream.Stream

class ConditionalEnumSet<T : Enum<T>>private constructor(private val backing: EnumMap<T, BooleanSupplier>, marker: Unit) : Set<T> {
	constructor(clazz: Class<T>) : this(EnumMap(clazz), Unit)
	constructor(map: Map<T, BooleanSupplier>) : this(EnumMap(map), Unit)

	override val size: Int
		get() = backing.values.stream().filter { it.asBoolean }.count().toInt()

	override fun contains(element: T): Boolean {
		return backing[element]?.asBoolean ?: false
	}

	override fun containsAll(elements: Collection<T>): Boolean {
		return elements.all { contains(it) }
	}

	override fun isEmpty(): Boolean {
		return backing.isEmpty() || backing.values.none { it.asBoolean }
	}

	override fun stream(): Stream<T> {
		return backing.entries.stream().filter { it.value.asBoolean }.map { it.key }
	}

	override fun iterator(): Iterator<T> {
		return backing.entries.iterator().filter { it.value.asBoolean }.map { it.key }
	}

	fun add(value: T, condition: BooleanSupplier) {
		backing[value] = condition
	}

	fun remove(value: T): Boolean {
		return backing.remove(value) != null
	}
}
