package ru.dbotthepony.kstarbound.world.terrain

import com.google.gson.JsonObject
import ru.dbotthepony.kommons.gson.set
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.defs.world.TerrainSelectorParameters

abstract class AbstractTerrainSelector<D : Any>(val data: D, val parameters: TerrainSelectorParameters) {
	// Returns a float signifying the "solid-ness" of a block, >= 0.0 should be
	// considered solid, < 0.0 should be considered open space.
	abstract operator fun get(x: Int, y: Int): Double

	abstract val type: TerrainSelectorType

	fun toJson(): JsonObject {
		val result = JsonObject()
		result["type"] = type.jsonName
		result["config"] = Starbound.gson.toJsonTree(data)
		result["parameters"] = Starbound.gson.toJsonTree(parameters)
		return result
	}

	fun toJsonPlain(): JsonObject {
		val result = Starbound.gson.toJsonTree(data) as JsonObject
		result["type"] = type.jsonName
		return result
	}

	override fun equals(other: Any?): Boolean {
		if (this === other)
			return true

		if (other == null || this::class.java != other::class.java)
			return false

		other as AbstractTerrainSelector<*>
		return data == other.data && parameters == other.parameters
	}

	private val hash by lazy {
		var h = data.hashCode()
		h = h * 31 + parameters.hashCode()
		h
	}

	override fun hashCode(): Int {
		return hash
	}

	override fun toString(): String {
		return "${this::class.simpleName}[config=$data, parameters=$parameters]"
	}
}
