package theorycrafter.ui.fiteditor.effectcolumn

import androidx.compose.runtime.Composable
import eve.data.DamageType
import eve.data.asIntNumber
import eve.data.asPercentage
import eve.data.fractionAsPercentage
import eve.data.typeid.*
import theorycrafter.TheorycrafterContext
import theorycrafter.fitting.AppliedEffect
import theorycrafter.fitting.AttributeProperty
import theorycrafter.fitting.Environment
import theorycrafter.fitting.Fit
import theorycrafter.ui.widgets.TextAndTooltip
import theorycrafter.utils.with


/**
 * All the information we need to display an [Environment] effect.
 */
private class EnvironmentInfo(
    override val fit: Fit,
    val environment: Environment,
): AffectingItemInfo {

    override val appliedEffects: Map<AttributeProperty<*>, Collection<AppliedEffect>>
        get() = emptyMap()

}


/**
 * Returns the displayed effect for the given booster.
 */
@Composable
fun displayedEnvironmentEffect(fit: Fit, environment: Environment): TextAndTooltip? {
    val envType = environment.type
    val envInfo = EnvironmentInfo(fit, environment)

    return with(
        TheorycrafterContext.eveData,
        EnvironmentEffectSources,
        envInfo
    ) {
        when {
            envType.isPulsarWormhole() -> withCellText(
                text = "Pulsar",
                SHIELD_HP_MULTIPLIER_PROPERTY,
                ARMOR_RESISTANCES_PENALTY_PROPERTY,
                CAPACITOR_RECHARGE_TIME_MULTIPLIER_PROPERTY,
                SIGNATURE_RADIUS_MULTIPLIER_PROPERTY,
                NEUT_AMOUNT_MULTIPLIER_PROPERTY
            )
            envType.isBlackHoleWormhole() -> withCellText(
                text = "Black Hole",
                MISSILE_VELOCITY_MULTIPLIER_PROPERTY,
                EXPLOSION_VELOCITY_MULTIPLIER_PROPERTY,
                MAX_VELOCITY_MULTIPLIER_PROPERTY,
                STASIS_WEB_STRENGTH_MULTIPLIER_PROPERTY,
                AGILITY_MULTIPLIER_PROPERTY,
                MAX_TARGETING_RANGE_MULTIPLIER_PROPERTY
            )
            envType.isCataclysmicVariableWormhole() -> withCellText(
                text = "Cataclysmic",
                LOCAL_SHIELD_BOOST_AMOUNT_MULTIPLIER_PROPERTY,
                LOCAL_ARMOR_REPAIR_AMOUNT_MULTIPLIER_PROPERTY,
                REMOTE_SHIELD_BOOST_AMOUNT_MULTIPLIER_PROPERTY,
                REMOTE_ARMOR_REPAIR_AMOUNT_MULTIPLIER_PROPERTY,
                CAPACITOR_CAPACITY_MULTIPLIER_PROPERTY,
                CAP_TRANSFERRED_MULTIPLIER_PROPERTY
            )
            envType.isMagnetarWormhole() -> withCellText(
                text = "Magnetar",
                WEAPON_DAMAGE_MULTIPLIER_PROPERTY,
                MISSILE_AND_VORTON_PROJECTOR_EXPLOSION_RADIUS_MULTIPLIER,
                MAX_TARGETING_RANGE_MULTIPLIER_PROPERTY,
                TRACKING_SPEED_MULTIPLIER_PROPERTY,
                TARGET_PAINTER_EFFECTIVENESS_MULTIPLIER,
            )
            envType.isRedGiantWormhole() -> withCellText(
                text = "Red Giant",
                HEAT_DAMAGE_MULTIPLIER_PROPERTY,
                OVERLOAD_BONUS_MULTIPLIER_PROPERTY,
                SMARTBOMB_RANGE_MULTIPLIER_PROPERTY,
                SMARTBOMB_DAMAGE_MULTIPLIER_PROPERTY,
                BOMB_EFFECTIVENESS_MULTIPLIER_PROPERTY,
            )
            envType.isWolfRayetWormhole() -> withCellText(
                text = "Wolf Rayet",
                ARMOR_HP_MULTIPLIER_PROPERTY,
                SHIELD_RESISTANCES_MULTIPLIER_PROPERTY,
                SMALL_WEAPONS_DAMAGE_MULTIPLIER_PROPERTY,
                SIGNATURE_RADIUS_MULTIPLIER_PROPERTY,
            )
            envType.isGammaRayMetaliminalStorm() -> withCellText(
                text = "Gamma Storm",
                EXPLOSIVE_RESISTANCE_BONUS_PROPERTY,
                SHIELD_HP_MULTIPLIER_PROPERTY,
                REMOTE_SHIELD_BOOST_AMOUNT_MULTIPLIER_PROPERTY,
                REMOTE_ARMOR_REPAIR_AMOUNT_MULTIPLIER_PROPERTY,
                CAPACITOR_CAPACITY_MULTIPLIER_PROPERTY,
                SIGNATURE_RADIUS_MULTIPLIER_PROPERTY
            )
            envType.isElectricalMetaliminalStorm() -> withCellText(
                text = "Electric Storm",
                EM_RESISTANCE_BONUS_PROPERTY,
                CAPACITOR_RECHARGE_TIME_MULTIPLIER_PROPERTY,
                VIRUS_COHERENCE_BONUS_PROPERTY,
                SCAN_PROBE_STRENGTH_MULTIPLIER_PROPERTY,
                CLOAKING_DISALLOWED_PROPERTY
            )
            envType.isPlasmaMetaliminalStorm() -> withCellText(
                text = "Plasma Storm",
                THERMAL_RESISTANCE_BONUS_PROPERTY,
                ARMOR_HP_MULTIPLIER_PROPERTY,
                WEAPON_DAMAGE_MULTIPLIER_PROPERTY,
                TRACKING_SPEED_MULTIPLIER_PROPERTY,
                MISSILE_AND_FIGHTER_EXPLOSION_RADIUS_MULTIPLIER
            )
            envType.isExoticMatterMetaliminalStorm() -> withCellText(
                text = "Exotic Storm",
                KINETIC_RESISTANCE_BONUS_PROPERTY,
                SCAN_RESOLUTION_BONUS_PROPERTY,
                MINING_LASER_DURATION_MULTIPLIER_PROPERTY,
                WARP_SPEED_BONUS_PROPERTY,
                LOCAL_SHIELD_BOOSTER_DURATION_BONUS_PROPERTY,
                LOCAL_ARMOR_REPAIRER_DURATION_BONUS_PROPERTY
            )
            envType.isAbyssalElectricalStorm() -> withSeparateMainSource(
                ABYSSAL_ELECTRICAL_STORM_PROPERTIES,
                EM_RESISTANCE_BONUS_PROPERTY,
                CAPACITOR_RECHARGE_TIME_BONUS_PROPERTY
            )
            envType.isAbyssalExoticParticleStorm() -> withSeparateMainSource(
                ABYSSAL_EXOTIC_PARTICLE_STORM_PROPERTIES,
                KINETIC_RESISTANCE_BONUS_PROPERTY,
                SCAN_RESOLUTION_BONUS_PROPERTY
            )
            envType.isAbyssalPlasmaFirestorm() -> withSeparateMainSource(
                ABYSSAL_PLASMA_FIRESTORM_PROPERTIES,
                THERMAL_RESISTANCE_BONUS_PROPERTY,
                ARMOR_HP_BONUS_PROPERTY
            )
            envType.isAbyssalGammaRayAfterglowStorm() -> withSeparateMainSource(
                ABYSSAL_GAMMA_RAY_AFTERGLOW_PROPERTIES,
                EXPLOSIVE_RESISTANCE_BONUS_PROPERTY,
                SHIELD_HP_BONUS_PROPERTY
            )
            envType.isAbyssalDarkMatterFieldStorm() -> withSeparateMainSource(
                ABYSSAL_DARK_MATTER_FIELD_PROPERTIES,
                TURRET_OPTINAL_RANGE_BONUS_PROPERTY,
                TURRET_FALLOFF_BONUS_PROPERTY,
                MAX_VELOCITY_BONUS_PROPERTY
            )
            else -> null
        }
    }
}


/**
 * A [DisplayedEffectSource] for displaying the value of an environment property.
 */
private class EnvironmentPropertyEffectSource<T: Any>(


    /**
     * Returns the property.
     */
    val property: (Environment) -> AttributeProperty<T>?,


    /**
     * A very short description of the property.
     */
    description: String,


    /**
     * Formats the property's value.
     */
    private val formatValue: (T, isCellDisplay: Boolean) -> String?


): DisplayedEffectSource<EnvironmentInfo>(description = description) {


    @Composable
    override fun valueOrMissingText(
        fit: Fit,
        affectingItemInfo: EnvironmentInfo,
        isCellDisplay: Boolean
    ): ValueOrMissing? {
        val environment = affectingItemInfo.environment

        val property = property(environment) ?: return null
        val value = property.value
        val valueText = formatValue(value, isCellDisplay)
        return valueText.valueOr(null)
    }


}


/**
 * Returns the text to display for a multiplier value.
 */
private fun Double.multiplierAsPercentage() = (this-1).fractionAsPercentage(precision = 0, withSign = true)


/**
 * Returns the text to display for a resistance multiplier value.
 */
private fun Double.asResistanceMultiplier() = (-this).asPercentage(precision = 0, withSign = true)


/**
 * The sources of environment effects.
 */
private object EnvironmentEffectSources {


    /**
     * Returns an [EnvironmentPropertyEffectSource] for a multiplier property.
     */
    fun multiplierProperty(
        property: (Environment) -> AttributeProperty<Double>?,
        isInverted: Boolean = false,
        description: String,
    ) = EnvironmentPropertyEffectSource(
        property = property,
        description = description,
        formatValue = { value, _ ->
            (if (isInverted) (2-value) else value).multiplierAsPercentage()
        }
    )


    /**
     * Returns an [EnvironmentPropertyEffectSource] for a percentage bonus property.
     */
    fun percentageBonusProperty(
        property: (Environment) -> AttributeProperty<Double>?,
        description: String,
    ) = EnvironmentPropertyEffectSource(
        property = property,
        description = description,
        formatValue = { value, _ -> value.asPercentage(precision = 0, withSign = true) }
    )


    /**
     * The bonus (or penalty) to shield hitpoints.
     */
    val SHIELD_HP_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::shieldHitpointsMultiplier,
        description = "shield hitpoints"
    )


    /**
     * The bonus (or penalty) to armor hitpoints.
     */
    val ARMOR_HP_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::armorHitpointsMultiplier,
        description = "armor hitpoints"
    )


    /**
     * The bonus (or penalty) to shield resistances.
     */
    val SHIELD_RESISTANCES_MULTIPLIER_PROPERTY = EnvironmentPropertyEffectSource(
        property = { it.shieldResistanceBonus[DamageType.EM] },  // Assume they're all the same
        description = "shield resistances",
        formatValue = { value, _ -> value.asResistanceMultiplier() }
    )


    /**
     * The bonus (or penalty) to armor resistances.
     */
    val ARMOR_RESISTANCES_PENALTY_PROPERTY = EnvironmentPropertyEffectSource(
        property = { it.armorResistanceBonus[DamageType.EM] }, // Assume they're all the same
        description = "armor resistances",
        formatValue = { value, _ -> value.asResistanceMultiplier() }
    )


    /**
     * The bonus (or penalty) to capacitor recharge time.
     */
    val CAPACITOR_RECHARGE_TIME_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::rechargeRateMultiplier,
        description = "capacitor recharge time",
    )


    /**
     * The bonus (or penalty) to signature radius.
     */
    val SIGNATURE_RADIUS_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::signatureRadiusMultiplier,
        description = "signature radius",
    )


    /**
     * The bonus (or penalty) to amount of capacitor neutralized.
     */
    val NEUT_AMOUNT_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::energyWarfareStrengthMultiplier,
        description = "energy neutralized",
    )


    /**
     * The bonus (or penalty) to missile velocity.
     */
    val MISSILE_VELOCITY_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::missileVelocityMultiplier,
        description = "missile velocity",
    )


    /**
     * The bonus (or penalty) to explosion velocity.
     */
    val EXPLOSION_VELOCITY_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::explosionVelocityMultiplier,
        description = "explosion velocity",
    )


    /**
     * The bonus (or penalty) to maximum ship velocity.
     */
    val MAX_VELOCITY_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::maxVelocityMultiplier,
        description = "max. velocity",
    )


    /**
     * The bonus (or penalty) to stasis webifier strength.
     */
    val STASIS_WEB_STRENGTH_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::stasisWebStrengthMultiplier,
        description = "stasis webifier velocity factor",
    )


    /**
     * The bonus (or penalty) to agility.
     */
    val AGILITY_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::agilityMultiplier,
        isInverted = true,
        description = "agility",
    )


    /**
     * The bonus (or penalty) to maximum targeting range.
     */
    val MAX_TARGETING_RANGE_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::maxTargetRangeMultiplier,
        description = "targeting range",
    )


    /**
     * The bonus (or penalty) to local armor repair amount.
     */
    val LOCAL_ARMOR_REPAIR_AMOUNT_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::armorRepairAmountMultiplier,
        description = "local armor repaired"
    )


    /**
     * The bonus (or penalty) to remote armor repair amount.
     */
    val REMOTE_ARMOR_REPAIR_AMOUNT_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::armorRemoteRepairAmountMultiplier,
        description = "remote armor repaired"
    )


    /**
     * The bonus (or penalty) to local shield boost amount.
     */
    val LOCAL_SHIELD_BOOST_AMOUNT_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::shieldBoostAmountMultiplier,
        description = "local shield boosted"
    )


    /**
     * The bonus (or penalty) to remote armor repair amount.
     */
    val REMOTE_SHIELD_BOOST_AMOUNT_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::shieldRemoteBoostAmountMultiplier,
        description = "remote shield boosted"
    )


    /**
     * The bonus (or penalty) to capacitor capacity.
     */
    val CAPACITOR_CAPACITY_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::capacitorCapacityMultiplier,
        description = "capacitor capacity",
    )


    /**
     * The bonus (or penalty) to amount of capacitor transferred to a remote ship.
     */
    val CAP_TRANSFERRED_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::energyTransferAmountMultiplier,
        description = "capacitor transferred",
    )


    /**
     * The bonus (or penalty) to weapon damage.
     */
    val WEAPON_DAMAGE_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::damageMultiplierMultiplier,
        description = "weapon and drone damage",
    )


    /**
     * The bonus (or penalty) to missile and vorton projector explosion radius.
     */
    val MISSILE_AND_VORTON_PROJECTOR_EXPLOSION_RADIUS_MULTIPLIER = multiplierProperty(
        property = Environment::explosionRadiusMultiplier,
        description = "missile and Vorton projector explosion radius"
    )


    /**
     * The bonus (or penalty) to tracking speed.
     */
    val TRACKING_SPEED_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::trackingSpeedMultiplier,
        description = "turret and drone tracking speed"
    )


    /**
     * The bonus (or penalty) to target painter effectiveness.
     */
    val TARGET_PAINTER_EFFECTIVENESS_MULTIPLIER = multiplierProperty(
        property = Environment::targetPainterEffectivenessMultiplier,
        description = "targe painter effectiveness",
    )


    /**
     * The bonus (or penalty) to heat damage taken by overloaded modules.
     */
    val HEAT_DAMAGE_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::heatDamageMultiplier,
        description = "heat damage taken by overheated modules"
    )


    /**
     * The bonus (or penalty) to the effects of overloading modules.
     */
    val OVERLOAD_BONUS_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::overloadBonusMultiplier,
        description = "to effect of overheating modules"
    )


    /**
     * The bonus (or penalty) to smartbomb range.
     */
    val SMARTBOMB_RANGE_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::smartbombRangeMultiplier,
        description = "smartbomb range"
    )


    /**
     * The bonus (or penalty) to smartbomb damage.
     */
    val SMARTBOMB_DAMAGE_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::bombEffectivenessMultiplier,
        description = "smartbomb damage"
    )


    /**
     * The bonus (or penalty) to bomb effectiveness.
     */
    val BOMB_EFFECTIVENESS_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::bombEffectivenessMultiplier,
        description = "bomb damage and effectiveness"
    )


    /**
     * The bonus (or penalty) to small weapons damage.
     */
    val SMALL_WEAPONS_DAMAGE_MULTIPLIER_PROPERTY = multiplierProperty(
        property = Environment::smallWeaponsDamageMultiplier,
        description = "small weapons damage"
    )


    /**
     * Returns an [EnvironmentPropertyEffectSource] for the bonus (or penalty) to the given type of resistance.
     */
    private fun resistanceBonusProperty(damageType: DamageType) = EnvironmentPropertyEffectSource(
        property = { it.shieldResistanceBonus[damageType] },  // Assume shield/armor/structure are all the same
        description = "${damageType.displayNameLowercase} resistances",
        formatValue = { value, _ -> value.asResistanceMultiplier() }
    )


    /**
     * The bonus (or penalty) to EM resistances.
     */
    val EM_RESISTANCE_BONUS_PROPERTY = resistanceBonusProperty(DamageType.EM)


    /**
     * The bonus (or penalty) to thermal resistances.
     */
    val THERMAL_RESISTANCE_BONUS_PROPERTY = resistanceBonusProperty(DamageType.THERMAL)


    /**
     * The bonus (or penalty) to kinetic resistances.
     */
    val KINETIC_RESISTANCE_BONUS_PROPERTY = resistanceBonusProperty(DamageType.KINETIC)


    /**
     * The bonus (or penalty) to explosive resistances.
     */
    val EXPLOSIVE_RESISTANCE_BONUS_PROPERTY = resistanceBonusProperty(DamageType.EXPLOSIVE)


    /**
     * The bonus (or penalty) to virus coherence.
     */
    val VIRUS_COHERENCE_BONUS_PROPERTY = EnvironmentPropertyEffectSource(
        property = Environment::virusCoherenceBonus,
        description = "virus coherence",
        formatValue = { value, _ -> value.asIntNumber(withSign = true) }
    )


    /**
     * The bonus (or penalty) to scan probe strength.
     */
    val SCAN_PROBE_STRENGTH_MULTIPLIER_PROPERTY = percentageBonusProperty(
        property = Environment::scanProbeStrengthBonus,
        description = "scan probe strength",
    )


    /**
     * Indicates cloaking is disallowed.
     */
    val CLOAKING_DISALLOWED_PROPERTY = object: DisplayedEffectSource<EnvironmentInfo>("disallowed") {
        @Composable
        override fun valueOrMissingText(fit: Fit, affectingItemInfo: EnvironmentInfo, isCellDisplay: Boolean): ValueOrMissing? {
            return if (affectingItemInfo.environment.isCloakingDisallowed)
                Value("Cloaking")
            else
                null
        }
    }


    /**
     * The bonus (or penalty) to missile and fighter explosion radius.
     */
    val MISSILE_AND_FIGHTER_EXPLOSION_RADIUS_MULTIPLIER = multiplierProperty(
        property = Environment::explosionRadiusMultiplier,
        description = "missile and fighter explosion radius"
    )


    /**
     * The bonus (or penalty) to scan resolution.
     */
    val SCAN_RESOLUTION_BONUS_PROPERTY = percentageBonusProperty(
        property = Environment::scanResolutionBonus,
        description = "scan resolution"
    )


    /**
     * The bonus (or penalty) to mining laser duration.
     */
    val MINING_LASER_DURATION_MULTIPLIER_PROPERTY = percentageBonusProperty(
        property = Environment::miningDurationMultiplier,
        description = "mining laser duration"
    )


    /**
     * The bonus (or penalty) to warp speed.
     */
    val WARP_SPEED_BONUS_PROPERTY = percentageBonusProperty(
        property = Environment::warpSpeedBonus,
        description = "warp speed"
    )


    /**
     * The bonus (or penalty) to local shield booster cycle duration.
     */
    val LOCAL_SHIELD_BOOSTER_DURATION_BONUS_PROPERTY = percentageBonusProperty(
        property = Environment::shieldBoosterDurationBonus,
        description = "local shield booster duration"
    )


    /**
     * The bonus (or penalty) to local armor repairer cycle duration.
     */
    val LOCAL_ARMOR_REPAIRER_DURATION_BONUS_PROPERTY = percentageBonusProperty(
        property = Environment::armorRepairerDurationBonus,
        description = "local armor repairer duration"
    )


    /**
     * The bonus (or penalty) to turret optimal range.
     */
    val TURRET_OPTINAL_RANGE_BONUS_PROPERTY = percentageBonusProperty(
        property = Environment::turretOptimalRangeBonus,
        description = "turret optimal range"
    )


    /**
     * The bonus (or penalty) to turret falloff range.
     */
    val TURRET_FALLOFF_BONUS_PROPERTY = percentageBonusProperty(
        property = Environment::turretFalloffBonus,
        description = "turret falloff"
    )


    /**
     * The bonus (or penalty) to ship maximum velocity.
     */
    val MAX_VELOCITY_BONUS_PROPERTY = percentageBonusProperty(
        property = Environment::maxVelocityBonus,
        description = "max. velocity"
    )


    /**
     * The bonus (or penalty) to capacitor recharge time.
     */
    val CAPACITOR_RECHARGE_TIME_BONUS_PROPERTY = percentageBonusProperty(
        property = Environment::capRechargeBonus,
        description = "capacitor recharge time"
    )


    /**
     * The bonus (or penalty) to armor HP.
     */
    val ARMOR_HP_BONUS_PROPERTY = percentageBonusProperty(
        property = Environment::armorHitpointsBonus,
        description = "armor hitpoints"
    )


    /**
     * The bonus (or penalty) to shield HP.
     */
    val SHIELD_HP_BONUS_PROPERTY = percentageBonusProperty(
        property = Environment::shieldHitpointsBonus,
        description = "shield hitpoints"
    )


    /**
     * Returns an effect source for abyssal weather environments.
     */
    fun abyssalEnvironmentProperties(
        penaltyProperty: (Environment) -> AttributeProperty<Double>?,
        isPenaltyResistance: Boolean,
        bonusProperty: (Environment) -> AttributeProperty<Double>?
    ) = object: DisplayedEffectSource<EnvironmentInfo>(description = "") {

        @Composable
        override fun valueOrMissingText(
            fit: Fit,
            affectingItemInfo: EnvironmentInfo,
            isCellDisplay: Boolean,
        ): ValueOrMissing {
            val env = affectingItemInfo.environment
            val penaltyValue = penaltyProperty(env)
            val bonusValue = bonusProperty(env)

            val bonuses = buildList {
                if (penaltyValue != null) {
                    add(
                        if (isPenaltyResistance)
                            penaltyValue.doubleValue.asResistanceMultiplier()
                        else
                            penaltyValue.doubleValue.asPercentage(precision = 0, withSign = true)
                    )
                }
                if (bonusValue != null)
                    add(bonusValue.doubleValue.asPercentage(precision = 0, withSign = true))
            }
            return Value(bonuses.joinToString(separator = MULTIPLE_VALUES_SEPARATOR ))
        }

    }


    /**
     * The effect source for the cell display of an abyssal electrical storm.
     */
    val ABYSSAL_ELECTRICAL_STORM_PROPERTIES = abyssalEnvironmentProperties(
        penaltyProperty = { it.shieldResistanceBonus[DamageType.EM] },
        isPenaltyResistance = true,
        bonusProperty = Environment::capRechargeBonus
    )


    /**
     * The effect source for the cell display of an abyssal plasma firestorm.
     */
    val ABYSSAL_PLASMA_FIRESTORM_PROPERTIES = abyssalEnvironmentProperties(
        penaltyProperty = { it.shieldResistanceBonus[DamageType.THERMAL] },
        isPenaltyResistance = true,
        bonusProperty = Environment::armorHitpointsBonus
    )


    /**
     * The effect source for the cell display of an abyssal gamma-ray afterglow.
     */
    val ABYSSAL_GAMMA_RAY_AFTERGLOW_PROPERTIES = abyssalEnvironmentProperties(
        penaltyProperty = { it.shieldResistanceBonus[DamageType.EXPLOSIVE] },
        isPenaltyResistance = true,
        bonusProperty = Environment::shieldHitpointsBonus
    )


    /**
     * The effect source for the cell display of an abyssal exotic particle storm.
     */
    val ABYSSAL_EXOTIC_PARTICLE_STORM_PROPERTIES = abyssalEnvironmentProperties(
        penaltyProperty = { it.shieldResistanceBonus[DamageType.KINETIC] },
        isPenaltyResistance = true,
        bonusProperty = Environment::scanResolutionBonus
    )


    /**
     * The effect source for the cell display of an abyssal dark matter field.
     */
    val ABYSSAL_DARK_MATTER_FIELD_PROPERTIES = abyssalEnvironmentProperties(
        penaltyProperty = Environment::turretOptimalRangeBonus,
        isPenaltyResistance = false,
        bonusProperty = Environment::maxVelocityBonus
    )


}
