package ru.dbotthepony.mc.otm.menu.input

import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import java.util.function.BooleanSupplier
import java.util.function.Consumer
import java.util.function.Supplier
import kotlin.reflect.KMutableProperty0

class BooleanInputWithFeedback(menu: MatteryMenu, allowSpectators: Boolean = false) : AbstractPlayerInputWithFeedback<Boolean>() {
	override val input = menu.booleanInput(allowSpectators) { consumer?.invoke(it) }
	override val field = menu.mSynchronizer.computedBoolean(BooleanSupplier { supplier?.invoke() ?: false })

	constructor(menu: MatteryMenu, allowSpectators: Boolean, state: KMutableProperty0<Boolean>?) : this(menu, allowSpectators) {
		if (state != null)
			with(state)
	}

	constructor(menu: MatteryMenu, allowSpectators: Boolean, state: Delegate<Boolean>?) : this(menu, allowSpectators) {
		if (state != null)
			with(state)
	}

	constructor(menu: MatteryMenu, state: KMutableProperty0<Boolean>?) : this(menu) {
		if (state != null)
			with(state)
	}

	constructor(menu: MatteryMenu, state: Delegate<Boolean>?) : this(menu) {
		if (state != null)
			with(state)
	}

	fun switchValue() {
		accept(!value)
	}

	companion object {
		fun <T> dispatch(menu: MatteryMenu, property: Delegate<T>, getter: (T) -> Boolean, setter: (T, Boolean) -> T): BooleanInputWithFeedback {
			return BooleanInputWithFeedback(
				menu,

				Delegate.Of(
					{ getter(property.get()) },
					{ property.accept(setter(property.get(), it)) }
				)
			)
		}

		fun <T> dispatch(menu: MatteryMenu, property: KMutableProperty0<T>, getter: (T) -> Boolean, setter: (T, Boolean) -> T): BooleanInputWithFeedback {
			return BooleanInputWithFeedback(
				menu,

				Delegate.Of(
					{ getter(property.get()) },
					{ property.set(setter(property.get(), it)) }
				)
			)
		}
	}
}
