package theorycrafter.fits

import eve.data.*


/**
 * Returns the prefix prepended to the name of the item the mutaplasmid is applied to.
 *
 * It should be relatively short.
 */
val Mutaplasmid.itemNamePrefix: String
    get() = when (type) {
        Mutaplasmid.Type.Decayed -> "Decayed"
        Mutaplasmid.Type.Gravid -> "Gravid"
        Mutaplasmid.Type.Unstable -> "Unstable"
        Mutaplasmid.Type.Radical -> "Radical"
        Mutaplasmid.Type.GlorifiedDecayed -> "Gl. Decayed"
        Mutaplasmid.Type.GlorifiedGravid -> "Gl. Gravid"
        Mutaplasmid.Type.GlorifiedUnstable -> "Gl. Unstable"
        Mutaplasmid.Type.GlorifiedRadical -> "Gl. Radical"
        Mutaplasmid.Type.ExigentNavigation -> "Exigent Navigation"
        Mutaplasmid.Type.ExigentFirepower -> "Exigent Firepower"
        Mutaplasmid.Type.ExigentDurability -> "Exigent Durability"
        Mutaplasmid.Type.ExigentProjection -> "Exigent Projection"
        Mutaplasmid.Type.ExigentPrecision -> "Exigent Precision"
        Mutaplasmid.Type.ExigentMiningDrone -> "Exigent"
        Mutaplasmid.Type.ExigentIceHarvestingDrone -> "Exigent"
        Mutaplasmid.Type.GlorifiedExigentNavigation -> "Gl. Exigent Navigation"
        Mutaplasmid.Type.GlorifiedExigentFirepower -> "Gl. Exigent Firepower"
        Mutaplasmid.Type.GlorifiedExigentDurability -> "Gl. Exigent Durability"
        Mutaplasmid.Type.GlorifiedExigentProjection -> "Gl. Exigent Projection"
        Mutaplasmid.Type.GlorifiedExigentPrecision -> "Gl. Exigent Precision"
    }


/**
 * Returns the name of the mutaplasmid.
 *
 * This is used when, e.g., selecting a mutaplasmid in a dropdown.
 */
val Mutaplasmid.mediumName: String
    get() = when (type) {
        Mutaplasmid.Type.Decayed -> "Decayed"
        Mutaplasmid.Type.Gravid -> "Gravid"
        Mutaplasmid.Type.Unstable -> "Unstable"
        Mutaplasmid.Type.Radical -> "Radical"
        Mutaplasmid.Type.GlorifiedDecayed -> "Glorified Decayed"
        Mutaplasmid.Type.GlorifiedGravid -> "Glorified Gravid"
        Mutaplasmid.Type.GlorifiedUnstable -> "Glorified Unstable"
        Mutaplasmid.Type.GlorifiedRadical -> "Glorified Radical"
        Mutaplasmid.Type.ExigentNavigation -> "Exigent Navigation"
        Mutaplasmid.Type.ExigentFirepower -> "Exigent Firepower"
        Mutaplasmid.Type.ExigentDurability -> "Exigent Durability"
        Mutaplasmid.Type.ExigentProjection -> "Exigent Projection"
        Mutaplasmid.Type.ExigentPrecision -> "Exigent Precision"
        Mutaplasmid.Type.ExigentMiningDrone -> "Exigent Mining"
        Mutaplasmid.Type.ExigentIceHarvestingDrone -> "Exigent Ice Harvesting"
        Mutaplasmid.Type.GlorifiedExigentNavigation -> "Glorified Exigent Navigation"
        Mutaplasmid.Type.GlorifiedExigentFirepower -> "Glorified Exigent Firepower"
        Mutaplasmid.Type.GlorifiedExigentDurability -> "Glorified Exigent Durability"
        Mutaplasmid.Type.GlorifiedExigentProjection -> "Glorified Exigent Projection"
        Mutaplasmid.Type.GlorifiedExigentPrecision -> "Glorified Exigent Precision"
    }


/**
 * Returns the default name of a newly mutated module type.
 */
fun ModuleType.mutatedName(mutaplasmid: Mutaplasmid) = "${mutaplasmid.itemNamePrefix} $name"


/**
 * Returns a mutation of the given module with the given mutaplasmid.
 */
context(EveData)
fun ModuleType.mutatedWith(
    mutaplasmid: Mutaplasmid,
    valueByAttribute: Map<Attribute<*>, Double> = attributeValuesForInitialMutationWith(mutaplasmid)
): ModuleType {
    return mutated(
        mutaplasmid = mutaplasmid,
        name = mutatedName(mutaplasmid),
        valueByAttribute = valueByAttribute
    )
}


/**
 * Returns the default name of a newly mutated drone type.
 */
fun DroneType.mutatedName(mutaplasmid: Mutaplasmid) = "${mutaplasmid.itemNamePrefix} $name"


/**
 * Returns the initial mutation of the given module with the given mutaplasmid.
 */
context(EveData)
fun DroneType.mutatedWith(
    mutaplasmid: Mutaplasmid,
    valueByAttribute: Map<Attribute<*>, Double> = attributeValuesForInitialMutationWith(mutaplasmid)
): DroneType {
    return mutated(
        mutaplasmid = mutaplasmid,
        name = mutatedName(mutaplasmid),
        valueByAttribute = valueByAttribute
    )
}


/**
 * Returns the attribute values (mapped by attribute id) for the initial item type mutation.
 */
context(EveData)
private fun EveItemType.attributeValuesForInitialMutationWith(mutaplasmid: Mutaplasmid): Map<Attribute<*>, Double> {
    val attributes = attributes
    return mutaplasmid.attributeMutations.entries.associate { (attrId, attrMutation) ->
        val attribute = attributes[attrId]
        val baseValue = attributeValues.getDoubleValue(attrId)
        val attrValueRange = attrMutation.attributeValueRange(baseValue)
        attribute to baseValue.coerceIn(attrValueRange)
    }
}
