package theorycrafter.tournaments

import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.toMutableStateList
import eve.data.EveData
import org.jetbrains.compose.resources.DrawableResource


/**
 * The information about a tournament that is available statically, without loading any data from disk.
 */
@Immutable
class TournamentDescriptor(


    /**
     * The id of the tournament; must be unique among all tournaments, but should preferably be short.
     */
    val id: String,


    /**
     * The full name of the tournament.
     *
     * This is displayed to the user.
     */
    val name: String,


    /**
     * The short name of the tournament.
     *
     * This is displayed to the user.
     */
    val shortName: String,


    /**
     * The icon for the tournament, if any.
     */
    val icon: DrawableResource? = null,


    /**
    * The tag to suggest for fits in this tournament.
     */
    val suggestedFitTag: String? = id,


    /**
     * The rules of the tournament.
     */
    val rulesFactory: (EveData) -> TournamentRules,


    /**
     * The title of the compositions window.
     */
    val compositionsWindowTitle: String = "Compositions",


    /**
     * The name of the winning team.
     */
    val winner: String? = null


)


/**
 * Bundles all the information of a single tournament.
 */
@Stable
class Tournament(


    /**
     * The context [EveData].
     */
    val eveData: EveData,


    /**
     * The descriptor of this tournament.
     */
    val descriptor: TournamentDescriptor,


    /**
     * The repository of this tournament.
     */
    val repository: TournamentRepository,


) {


    /**
     * The tournament rules.
     */
    val rules: TournamentRules = descriptor.rulesFactory(eveData)


    /**
     * The mutable list of compositions for the tournament, as Compose state, for internal use.
     */
    private val mutableCompositions: MutableList<Composition> = repository.compositions
        .map { Composition.fromStored(this, it) }
        .toMutableStateList()


    /**
     * The list of compositions for the tournament. This is Compose state.
     */
    val compositions: List<Composition>
        get() = mutableCompositions


    /**
     * Adds a new, empty, composition.
     */
    fun addEmptyComposition(name: String): Composition {
        return addComposition(StoredComposition(name = name, ships = emptyList()))
    }


    /**
     * Adds a new composition.
     */
    fun addComposition(composition: StoredComposition): Composition {
        repository.addComposition(composition)
        return Composition.fromStored(this, composition).also {
            mutableCompositions.add(it)
        }
    }


    /**
     * Adds a new composition that is a copy of the given one, except it has the given name.
     */
    fun duplicateComposition(composition: Composition, name: String): Composition {
        return addComposition(composition.toStoredCompositionDuplicate(name = name))
    }


    /**
     * Deletes the given list of compositions.
     */
    fun deleteCompositions(compositions: Collection<Composition>) {
        val deletedIds = compositions.mapTo(mutableSetOf()) { it.id }
        repository.deleteCompositions(deletedIds)

        val iterator = mutableCompositions.iterator()
        while (iterator.hasNext()) {
            val comp = iterator.next()
            if (comp.id in deletedIds) {
                comp.deleted = true
                iterator.remove()
            }
        }
    }


    /**
     * Moves a composition from [fromIndex] to [toIndex].
     */
    fun moveComposition(fromIndex: Int, toIndex: Int) {
        val composition = mutableCompositions.removeAt(fromIndex)
        mutableCompositions.add(toIndex, composition)
    }


}