// SPDX-FileCopyrightText: Adam Evyčędo
//
// SPDX-License-Identifier: GPL-3.0-or-later

package xyz.apiote.bimba.czwek.api.responses

import xyz.apiote.bimba.czwek.api.LineV1
import xyz.apiote.bimba.czwek.api.LineV2
import xyz.apiote.bimba.czwek.api.LineV3
import xyz.apiote.bimba.czwek.api.QueryableV1
import xyz.apiote.bimba.czwek.api.QueryableV2
import xyz.apiote.bimba.czwek.api.QueryableV3
import xyz.apiote.bimba.czwek.api.QueryableV4
import xyz.apiote.bimba.czwek.api.StopV1
import xyz.apiote.bimba.czwek.api.StopV2
import xyz.apiote.bimba.czwek.api.UnknownResourceVersionException
import xyz.apiote.fruchtfleisch.Reader
import java.io.InputStream

interface QueryablesResponse {
	companion object {
		fun unmarshal(stream: InputStream): QueryablesResponse {
			val reader = Reader(stream)
			return when (val v = reader.readUInt().toULong()) {
				// 0UL -> QueryablesResponseDev.unmarshal(stream)
				1UL -> QueryablesResponseV1.unmarshal(stream)
				2UL -> QueryablesResponseV2.unmarshal(stream)
				3UL -> QueryablesResponseV3.unmarshal(stream)
				4UL -> QueryablesResponseV4.unmarshal(stream)
				else -> throw UnknownResponseVersion("Queryables", v)
			}
		}
	}
}

data class QueryablesResponseV4(val queryables: List<QueryableV4>) : QueryablesResponse {
	companion object {
		fun unmarshal(stream: InputStream): QueryablesResponseV4 {
			val queryables = mutableListOf<QueryableV4>()
			val reader = Reader(stream)
			val n = reader.readUInt().toULong()
			for (i in 0UL until n) {
				when (val r = reader.readUInt().toULong()) {
					0UL -> {
						queryables.add(StopV2.unmarshal(stream))
					}

					1UL -> {
						queryables.add(LineV3.unmarshal(stream))
					}

					else -> {
						throw UnknownResourceVersionException("Queryable/$r", 0u)
					}
				}
			}
			return QueryablesResponseV4(queryables)
		}
	}
}

data class QueryablesResponseV3(val queryables: List<QueryableV3>) : QueryablesResponse {
	companion object {
		fun unmarshal(stream: InputStream): QueryablesResponseV3 {
			val queryables = mutableListOf<QueryableV3>()
			val reader = Reader(stream)
			val n = reader.readUInt().toULong()
			for (i in 0UL until n) {
				when (val r = reader.readUInt().toULong()) {
					0UL -> {
						queryables.add(StopV2.unmarshal(stream))
					}

					1UL -> {
						queryables.add(LineV2.unmarshal(stream))
					}

					else -> {
						throw UnknownResourceVersionException("Queryable/$r", 0u)
					}
				}
			}
			return QueryablesResponseV3(queryables)
		}
	}
}

data class QueryablesResponseV2(val queryables: List<QueryableV2>) : QueryablesResponse {
	companion object {
		fun unmarshal(stream: InputStream): QueryablesResponseV2 {
			val queryables = mutableListOf<QueryableV2>()
			val reader = Reader(stream)
			val n = reader.readUInt().toULong()
			for (i in 0UL until n) {
				when (val r = reader.readUInt().toULong()) {
					0UL -> {
						queryables.add(StopV2.unmarshal(stream))
					}

					1UL -> {
						queryables.add(LineV1.unmarshal(stream))
					}

					else -> {
						throw UnknownResourceVersionException("Queryable/$r", 2u)
					}
				}
			}
			return QueryablesResponseV2(queryables)
		}
	}
}

data class QueryablesResponseV1(val queryables: List<QueryableV1>) : QueryablesResponse {
	companion object {
		fun unmarshal(stream: InputStream): QueryablesResponseV1 {
			val queryables = mutableListOf<QueryableV1>()
			val reader = Reader(stream)
			val n = reader.readUInt().toULong()
			for (i in 0UL until n) {
				when (val r = reader.readUInt().toULong()) {
					0UL -> {
						queryables.add(StopV1.unmarshal(stream))
					}

					else -> {
						throw UnknownResourceVersionException("Queryable/$r", 1u)
					}
				}
			}
			return QueryablesResponseV1(queryables)
		}
	}
}
