package ru.dbotthepony.mc.otm.tests

import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer
import ru.dbotthepony.mc.otm.network.synchronizer.IMutableField
import java.io.ByteArrayInputStream

object FieldSynchronizerTests {
	@Test
	@DisplayName("Field Synchronizer full read/write test")
	fun test() {
		val a = FieldSynchronizer()
		val b = FieldSynchronizer()

		val boolA = a.bool()
		val boolB = b.bool()

		val intA = a.int()
		val intB = b.int()

		val intA2 = a.int()
		val intB2 = b.int()

		val intA3 = a.int()
		val intB3 = b.int()

		boolA.value = true
		intA.value = 8384
		intA2.value = 348488
		intA3.value = -4

		b.read(a.collectNetworkPayload()!!.let { ByteArrayInputStream(it.array, 0, it.length) })

		assertEquals(boolA.value, boolB.value)
		assertEquals(intA.value, intB.value)
		assertEquals(intA2.value, intB2.value)
		assertEquals(intA3.value, intB3.value)
	}

	@Test
	@DisplayName("Field Synchronizer partial read/write test")
	fun testPartial() {
		val a = FieldSynchronizer()
		val b = FieldSynchronizer()

		val boolA = a.bool()
		val boolB = b.bool()

		val intA = a.int()
		val intB = b.int()

		val intA2 = a.int()
		val intB2 = b.int()

		val intA3 = a.int()
		val intB3 = b.int()

		boolA.value = true
		//intA.setValue(8384)
		//intA2.setValue(348488)
		intA3.value = -4

		b.read(a.collectNetworkPayload()!!.let { ByteArrayInputStream(it.array, 0, it.length) })

		assertEquals(boolA.value, boolB.value)
		assertEquals(intA.value, intB.value)
		assertEquals(intA2.value, intB2.value)
		assertEquals(intA3.value, intB3.value)
	}

	@Test
	@DisplayName("Field Synchronizer multiple endpoints")
	fun multipleEndpoints() {
		val a = FieldSynchronizer()
		val b = FieldSynchronizer()
		val c = FieldSynchronizer()

		val f1 = a.bool()
		val f2 = a.bool()
		val f3 = a.int()
		val f4 = a.long()

		val aFields = listOf(f1, f2, f3, f4)
		val bFields = listOf(b.bool(), b.bool(), b.int(), b.long())
		val cFields = listOf(c.bool(), c.bool(), c.int(), c.long())

		val bEndpoint = a.Endpoint()

		f2.value = true
		f3.value = -15

		val cEndpoint = a.Endpoint()

		f4.value = 80L

		b.read(bEndpoint.collectNetworkPayload()!!.let { ByteArrayInputStream(it.array, 0, it.length) })
		c.read(cEndpoint.collectNetworkPayload()!!.let { ByteArrayInputStream(it.array, 0, it.length) })

		for ((i, field) in bFields.withIndex()) {
			assertEquals(aFields[i].value, field.value)
		}

		for ((i, field) in cFields.withIndex()) {
			assertEquals(aFields[i].value, field.value)
		}
	}

	@Test
	@DisplayName("Field Synchronizer Lotta fields")
	fun lottaFields() {
		val a = FieldSynchronizer()
		val b = FieldSynchronizer()

		val fieldsa = ArrayList<IMutableField<Int>>()
		val fieldsb = ArrayList<IMutableField<Int>>()

		for (i in 0 .. 900) {
			fieldsa.add(a.int())
			fieldsb.add(b.int())
		}

		for (i in 0 .. 900) {
			fieldsa[i].value = i
		}

		b.read(a.collectNetworkPayload()!!.let { ByteArrayInputStream(it.array, 0, it.length) })

		for (i in 0 .. 900) {
			assertEquals(fieldsa[i].value, fieldsb[i].value)
		}
	}
}
