package ru.dbotthepony.kstarbound.json.builder

import kotlin.reflect.KClass

/**
 * Strictly prohibits deserializing target field as null from JSON
 */
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class JsonNotNull

/**
 * Заставляет указанное свойство быть проигнорированным при автоматическом создании [BuilderAdapter]
 */
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class JsonIgnore

/**
 * Указывает, что данное свойство или аргумент является компонующим, а не потомственным значением.
 *
 * Заставляет адаптеры распаковать данное свойство или аргумент на том же уровне, что и родителя
 */
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class JsonFlat

@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class JsonAlias(vararg val aliases: String)

/**
 * Указывает, что данное свойство может отсутствовать в структуре
 */
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class JsonOptional

/**
 * Указывает, что данное свойство обязано присутствовать в структуре
 */
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class JsonRequired

/**
 * Указывает, что для данного класса можно автоматически создать [BuilderAdapter] для всех его свойств,
 * которые не указаны как [JsonIgnore]
 */
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class JsonBuilder

/**
 * Указывает, что для данного класса можно автоматически создать [FactoryAdapter]
 *
 * Чаще всего, это используется только для data классов
 *
 * @see JsonIgnore
 */
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class JsonFactory(
	val asList: Boolean = false,
	val logMisses: Boolean = false,
)

/**
 * Позволяет указать, какую реализацию использовать при попытке разобрать JSON структуру
 * с аннотированным типом
 *
 * Пример:
 * ```kotlin
 * @JsonFactory
 * data class Item(val thingDef: IThing, val price: Long)
 *
 * @JsonImplementation(Thing::class)
 * interface IThing { val prop: String }
 *
 * data class Thing(override val prop: String) : IThing
 * ```
 */
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class JsonImplementation(val implementingClass: KClass<*>)

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class JsonSingleton
