package com.infendro.cli.command.context import com.infendro.cli.command.Argument import com.infendro.cli.command.Command import com.infendro.cli.command.Option import kotlin.reflect.KProperty class Context internal constructor( val command: Command, val commands: List, val options: List, val arguments: List, ) { class Cmd( val name: String, ) class Arg( val value: Any, ) class Opt( val name: String, val value: Any, ) internal fun execute() = (command.execute)() operator fun Command.Key.getValue(thisRef: Any?, property: KProperty<*>): String = commands[index].name private val Argument.index: Int get() = command.arguments.indexOf(this) @Suppress("UNCHECKED_CAST") private val Argument.value: T? get() = arguments.getOrNull(index)?.value as? T @Suppress("UNCHECKED_CAST") private val Argument.Variable.values: List get() = arguments.drop(index).map { it.value as T } operator fun Argument.Required.getValue(thisRef: Any?, property: KProperty<*>): T = value!! operator fun Argument.OrElse.getValue(thisRef: Any?, property: KProperty<*>): T = value ?: other operator fun Argument.OrNull.getValue(thisRef: Any?, property: KProperty<*>): T? = value operator fun Argument.Variable.getValue(thisRef: Any?, property: KProperty<*>): List = values @Suppress("UNCHECKED_CAST") private val Option.value: T? get() = options.firstOrNull { it.name in names }?.value as? T @Suppress("UNCHECKED_CAST") private val Option.Variable.values: List get() = options.filter { it.name in names }.map { it.value as T } operator fun Option.Required.getValue(thisRef: Any?, property: KProperty<*>): T = value!! operator fun Option.OrElse.getValue(thisRef: Any?, property: KProperty<*>): T = value ?: other operator fun Option.OrNull.getValue(thisRef: Any?, property: KProperty<*>): T? = value operator fun Option.Variable.getValue(thisRef: Any?, property: KProperty<*>): List = values }