package ru.dbotthepony.mc.otm.network.synchronizer

import it.unimi.dsi.fastutil.booleans.BooleanConsumer
import it.unimi.dsi.fastutil.floats.FloatConsumer
import ru.dbotthepony.mc.otm.core.GetterSetter
import java.util.function.DoubleConsumer
import java.util.function.IntConsumer
import java.util.function.LongConsumer
import kotlin.reflect.KProperty

sealed interface IMutableField<V> : IField<V>, GetterSetter<V> {
	override fun getValue(thisRef: Any?, property: KProperty<*>): V {
		return this.value
	}

	override var value: V

	override fun accept(t: V) {
		value = t
	}

	override fun invoke(): V {
		return this.value
	}
}

interface IMutableFloatProperty : IFloatProperty {
	operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Float)
}

sealed interface IMutableFloatField : IMutableField<Float>, IFloatField, FloatConsumer {
	override var float: Float
	override val property: IMutableFloatProperty

	@Deprecated("Use type specific property", replaceWith = ReplaceWith("this.float"))
	override var value: Float
		get() = float
		set(value) { float = value }

	override fun accept(t: Float) {
		float = t
	}

	@Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property"))
	override fun getValue(thisRef: Any?, property: KProperty<*>): Float {
		return float
	}

	@Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property"))
	override fun setValue(thisRef: Any?, property: KProperty<*>, value: Float) {
		float = value
	}
}

interface IMutableDoubleProperty : IDoubleProperty {
	operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Double)
}

sealed interface IMutableDoubleField : IMutableField<Double>, IDoubleField, DoubleConsumer {
	override var double: Double
	override val property: IMutableDoubleProperty

	@Deprecated("Use type specific property", replaceWith = ReplaceWith("this.double"))
	override var value: Double
		get() = double
		set(value) { double = value }

	override fun accept(t: Double) {
		double = t
	}

	@Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property"))
	override fun getValue(thisRef: Any?, property: KProperty<*>): Double {
		return double
	}

	@Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property"))
	override fun setValue(thisRef: Any?, property: KProperty<*>, value: Double) {
		double = value
	}
}

interface IMutableIntProperty : IIntProperty {
	operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int)
}

sealed interface IMutableIntField : IMutableField<Int>, IIntField, IntConsumer {
	override var int: Int
	override val property: IMutableIntProperty

	@Deprecated("Use type specific property", replaceWith = ReplaceWith("this.int"))
	override var value: Int
		get() = int
		set(value) { int = value }

	override fun accept(t: Int) {
		int = t
	}

	@Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property"))
	override fun getValue(thisRef: Any?, property: KProperty<*>): Int {
		return int
	}

	@Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property"))
	override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
		int = value
	}
}

interface IMutableLongProperty : ILongProperty {
	operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Long)
}

sealed interface IMutableLongField : IMutableField<Long>, ILongField, LongConsumer {
	override var long: Long
	override val property: IMutableLongProperty

	@Deprecated("Use type specific property", replaceWith = ReplaceWith("this.long"))
	override var value: Long
		get() = long
		set(value) { long = value }

	override fun accept(t: Long) {
		long = t
	}

	@Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property"))
	override fun getValue(thisRef: Any?, property: KProperty<*>): Long {
		return long
	}

	@Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property"))
	override fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) {
		long = value
	}
}

interface IMutableBooleanProperty : IBooleanProperty {
	operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean)
}

sealed interface IMutableBooleanField : IMutableField<Boolean>, IBooleanField, BooleanConsumer {
	override var boolean: Boolean
	override val property: IMutableBooleanProperty

	@Deprecated("Use type specific property", replaceWith = ReplaceWith("this.boolean"))
	override var value: Boolean
		get() = boolean
		set(value) { boolean = value }

	override fun accept(t: Boolean) {
		boolean = t
	}

	@Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property"))
	override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean {
		return boolean
	}

	@Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property"))
	override fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) {
		boolean = value
	}
}
