/**
 * Determines the value to be displayed in the "Effect" column for implants.
 */

package theorycrafter.ui.fiteditor.effectcolumn

import androidx.compose.runtime.Composable
import eve.data.*
import eve.data.typeid.*
import theorycrafter.TheorycrafterContext
import theorycrafter.fitting.*
import theorycrafter.ui.fiteditor.effectcolumn.CommonEffectSources.anyAffectedChargeProperty
import theorycrafter.ui.fiteditor.effectcolumn.CommonEffectSources.anyAffectedModuleProperty
import theorycrafter.ui.fiteditor.effectcolumn.CommonEffectSources.cpuNeed
import theorycrafter.ui.fiteditor.effectcolumn.CommonEffectSources.filteredCapacitorNeed
import theorycrafter.ui.fiteditor.effectcolumn.CommonEffectSources.filteredModuleDuration
import theorycrafter.ui.fiteditor.effectcolumn.CommonEffectSources.missileDamage
import theorycrafter.ui.fiteditor.effectcolumn.CommonEffectSources.turretDamage
import theorycrafter.ui.widgets.TextAndTooltip
import theorycrafter.utils.with


/**
 * All the information we need to display an [Implant] effect
 */
private class ImplantInfo(
    override val fit: Fit,
    override val appliedEffects: Map<AttributeProperty<*>, Collection<AppliedEffect>>,
    @Suppress("unused") val implant: Implant,
): AffectingItemInfo


/**
 * Returns the [ImplantInfo] for the given module.
 */
@Composable
private fun implantInfo(fit: Fit, implant: Implant): ImplantInfo {
    val appliedEffects = implant.appliedEffectsByTargetProperty()
    return ImplantInfo(fit, appliedEffects, implant)
}


/**
 * Returns the displayed effect for the given implant.
 */
@Composable
fun displayedImplantEffect(fit: Fit, implant: Implant): TextAndTooltip? {
    val implantType = implant.type
    val implantInfo = implantInfo(fit, implant)

    return with(TheorycrafterContext.eveData, ImplantEffectSources, CommonEffectSources, implantInfo) {
        when {
            implantType.isRepairSystemsImplant() || implantType.isNumonFamilyHeirloomImplant() ->
                withoutMainSource(
                    allSourcesMissingText = "No armor or structure repairers fitted",
                    ARMOR_REPAIRER_DURATION,
                    STRUCTURE_REPAIRER_DURATION
                )
            implantType.isRemoteArmorRepairSystemsImplant() ->
                withMergedMainSource(REMOTE_ARMOR_REPAIRER_CAPACITOR_NEED)
            implantType.isMechanicImplant() ->
                withMergedMainSource(STRUCTURE_HP)
            implantType.isRepairProficiencyImplant() ->
                withMergedMainSource(ARMOR_REPAIR_AMOUNT)
            implantType.isHullUpgradesImplant() ->
                withMergedMainSource(ARMOR_HP)
            implantType.isImperialNavyNobleImplant() ->
                withMergedMainSource(
                    mainSource = ARMOR_HP,
                    ARMOR_REPAIR_AMOUNT
                )
            implantType.isDroneNavigationImplant() ->
                withMergedMainSource(DRONE_SPEED)  // TODO: Fighters
            implantType.isGoliathDroneTunerImplant() ->
                withMergedMainSource(DRONE_DURABILITY, DRONE_SPEED)
            implantType.isHawkmothDroneTunerImplant() ->
                withMergedMainSource(DRONE_SPEED, DRONE_DURABILITY)
            implantType.isDroneSharpshootingImplant() ->
                withMergedMainSource(DRONE_OPTIMAL_RANGE)
            implantType.isRepairDroneOperationImplant() ->
                withMergedMainSource(DRONE_REPAIR_AMOUNT)
            implantType.isBumblebeeDroneTunerImplant() ->
                withMergedMainSource(
                    mainSource = DRONE_DURABILITY,
                    DRONE_DAMAGE_MULTIPLIER
                )
            implantType.isYellowjacketDroneTunerImplant() ->
                withMergedMainSource(
                    mainSource = DRONE_DAMAGE_MULTIPLIER,
                    DRONE_DURABILITY
                )
            implantType.isDroneDurabilityImplant() ->
                withMergedMainSource(DRONE_DURABILITY) // TODO: Fighters
            implantType.isStasisWebifierImplant() ->
                withMergedMainSource(STASIS_WEBIFIER_RANGE)
            implantType.isEntanglementOptimizerImplant() ->
                withoutMainSource(
                    allSourcesMissingText = "No warp scramblers or stasis webifiers fitted",
                    WARP_SCRAMBLER_RANGE,
                    STASIS_WEBIFIER_RANGE,
                )
            implantType.isPropulsionJammingImplant() ->
                withMergedMainSource(PROPULSION_JAMMING_CAPACITOR_NEED)
            implantType.isElectronicWarfareImplant() ->
                withoutMainSource(
                    allSourcesMissingText = "No ECM or ECM burst modules fitted",
                    ECM_CAPACITOR_NEED,
                    BURST_JAMMER_CAPACITOR_NEED
                )
            implantType.isSensorLinkingImplant() ->
                withMergedMainSource(SENSOR_LINKING_CAPACITOR_NEED)
            implantType.isTargetPaintingImplant() ->
                withMergedMainSource(TARGET_PAINTING_CAPACITOR_NEED)
            implantType.isWeaponDisruptionImplant() ->
                withMergedMainSource(WEAPON_DISRUPTION_CAPACITOR_NEED)
            implantType.isCapacitorSystemsOperationImplant() ->
                withMergedMainSource(CAPACITOR_RECHARGE_TIME)
            implantType.isPowerGridManagementImplant() ->
                withMergedMainSource(POWER_OUTPUT)
            implantType.isCpuManagementImplant() ->
                withMergedMainSource(CPU_OUTPUT)
            implantType.isElectronicsUpgradesImplant() ->
                withMergedMainSource(ELECTRONICS_UPGRADES_CPU_NEED)
            implantType.isCapacitorEmissionSystemsImplant() ->
                withMergedMainSource(CAPACITOR_EMISSION_CAPACITOR_NEED)
            implantType.isEnergyGridUpgradesImplant() ->
                withMergedMainSource(ENERGY_GRID_UPGRADES_CPU_NEED)
            implantType.isEnergyPulseWeaponsImplant() ->
                withMergedMainSource(SMARTBOMB_DURATION)
            implantType.isCapacitorManagementImplant() ->
                withMergedMainSource(CAPACITOR_CAPACITY)
            implantType.isSmallProjectileTurretImplant() ->
                withMergedMainSource(SMALL_PROJECTILE_WEAPONS_DAMAGE)
            implantType.isSmallEnergyTurretImplant() ->
                withMergedMainSource(SMALL_ENERGY_WEAPONS_DAMAGE)
            implantType.isSmallHybridTurretImplant() ->
                withMergedMainSource(SMALL_HYBRID_WEAPONS_DAMAGE)
            implantType.isMotionPredictionTurretImplant() || implantType.isOgdinsEyeCoordinationEnhancerImplant() ->
                withMergedMainSource(TURRET_TRACKING_SPEED)
            implantType.isControlledBurstsImplant() ->
                withMergedMainSource(TURRET_CAPACITOR_NEED)
            implantType.isTrajectoryAnalysisImplant() ->
                withMergedMainSource(TURRET_FALLOFF)
            implantType.isMediumProjectileTurretImplant() ->
                withMergedMainSource(MEDIUM_PROJECTILE_WEAPONS_DAMAGE)
            implantType.isMediumEnergyTurretImplant() ->
                withMergedMainSource(MEDIUM_ENERGY_WEAPONS_DAMAGE)
            implantType.isMediumHybridTurretImplant() ->
                withMergedMainSource(MEDIUM_HYBRID_WEAPONS_DAMAGE)
            implantType.isSurgicalStrikeImplant() ->
                withMergedMainSource(TURRET_DAMAGE)
            implantType.isGunneryImplant() || implantType.isPashansTurretCustomizationMindlinkImplant() ->
                withMergedMainSource(TURRET_RATE_OF_FIRE)
            implantType.isTurretSharpshooterImplant() ->
                withMergedMainSource(TURRET_OPTIMAL_RANGE)
            implantType.isLargeProjectileTurretImplant() ->
                withMergedMainSource(LARGE_PROJECTILE_WEAPONS_DAMAGE)
            implantType.isLargeEnergyTurretImplant() || implantType.isPashansTurretHandlingMindlinkImplant() ->
                withMergedMainSource(LARGE_ENERGY_WEAPONS_DAMAGE)
            implantType.isLargeHybridTurretImplant() ->
                withMergedMainSource(LARGE_HYBRID_WEAPONS_DAMAGE)
            implantType.isWeaponUpgradesImplant() ->
                withMergedMainSource(TURRET_CPU_NEED)
            implantType.isXlTorpedoSharpshooterImplant() ->
                withMergedMainSource(XL_TORPEDO_DAMAGE)
            implantType.isLauncherCpuEfficiencyImplant() ->
                withMergedMainSource(MISSILE_LAUNCHER_CPU_NEED)
            implantType.isCruiseMissilesImplant() ->
                withMergedMainSource(CRUISE_MISSILE_DAMAGE)
            implantType.isTorpedoesImplant() ->
                withMergedMainSource(TORPEDO_DAMAGE)
            implantType.isMissileBombardmentImplant() ->
                withMergedMainSource(MISSILE_FLIGHT_TIME)
            implantType.isMissileProjectionImplant() ->
                withMergedMainSource(MISSILE_VELOCITY)
            implantType.isHeavyAssaultMissilesImplant() ->
                withMergedMainSource(HEAVY_ASSAULT_MISSILE_DAMAGE)
            implantType.isHeavyMissilesImplant() ->
                withMergedMainSource(HEAVY_MISSILE_DAMAGE)
            implantType.isGuidedMissilePrecisionImplant() ->
                withMergedMainSource(MISSILE_EXPLOSION_RADIUS)
            implantType.isDefenderMissilesImplant() ->
                withMergedMainSource(DEFENDER_MISSILE_VELOCITY)
            implantType.isTargetNavigationPredictionImplant() ->
                withMergedMainSource(MISSILE_EXPLOSION_VELOCITY)
            implantType.isLightMissilesImplant() ->
                withMergedMainSource(LIGHT_MISSILE_DAMAGE)
            implantType.isRocketsImplant() ->
                withMergedMainSource(ROCKET_DAMAGE)
            implantType.isRapidLaunchImplant() || implantType.isWhelanMachorinsBallisticSmartlinkImplant() ->
                withMergedMainSource(MISSILE_LAUNCHER_RATE_OF_FIRE)
            implantType.isAutoTargetingExplosionRadiusImplant() ->
                withMergedMainSource(AUTO_TARGETING_MISSILES_EXPLOSION_RADIUS)
            implantType.isAccelerationControlImplant() || implantType.isZorsCustomNavigationHyperLinkImplant() ->
                withMergedMainSource(PROPMOD_SPEED_FACTOR_BONUS)
            implantType.isAfterburnerImplant() || implantType.isZorsCustomNavigationLinkImplant() ->
                withMergedMainSource(AFTERBURNER_DURATION)
            implantType.isNavigationImplant() || implantType.isShaqilsSpeedEnhancerImplant() ->
                withMergedMainSource(MAX_VELOCITY)
            implantType.isWarpDriveOperationImplant() ->
                withMergedMainSource(WARP_CAPACITOR_NEED)
            implantType.isWarpDriveSpeedImplant() ->
                withMergedMainSource(WARP_SPEED)
            implantType.isEvasiveManeuveringImplant() ->
                withMergedMainSource(INERTIA_MODIFIER)
            implantType.isFuelConservationImplant() ->
                withMergedMainSource(AFTERBURNER_CAPACITOR_NEED)
            implantType.isHighSpeedManeuveringImplant() ->
                withMergedMainSource(MICROWARPDRIVE_CAPACITOR_NEED)
            implantType.isAstrometricPinpointingImplant() ->
                withMergedMainSource(SCAN_DEVIATION_EFFECT)
            implantType.isAstrometricAcquisitionImplant() ->
                withMergedMainSource(SCAN_TIME_EFFECT)
            implantType.isAstrometricRangefindingImplant() ->
                withMergedMainSource(SCAN_SENSOR_STRENGTH_EFFECT)
            implantType.isNetIntrusionImplant() ->
                withoutMainSource(
                    allSourcesMissingText = "No data analyzers fitted",
                    DATA_ANALYSER_VIRUS_STRENGTH,
                    DATA_ANALYZER_VIRUS_COHERENCE,
                    DATA_ANALYZER_ACCESS_DIFFICULTY_BONUS,
                )
            implantType.isArchaeologyImplant() ->
                withMergedMainSource(
                    RELIC_ANALYZER_VIRUS_COHERENCE,
                    RELIC_ANALYZER_ACCESS_DIFFICULTY_BONUS
                )
            implantType.isHackingImplant() ->
                withMergedMainSource(
                    DATA_ANALYZER_VIRUS_COHERENCE,
                    DATA_ANALYZER_ACCESS_DIFFICULTY_BONUS
                )
            implantType.isSalvagingImplant() ->
                withMergedMainSource(SALVAGER_ACCESS_DIFFICULTY_BONUS)
            implantType.isEnvironmentalAnalysisImplant() ->
                withoutMainSource(
                    allSourcesMissingText = "No salvagers or data/relic analyzers fitted",
                    SALVAGER_CYCLE_DURATION,
                    DATA_AND_RELIC_ANALYZER_CYCLE_DURATION,
                    DATA_AND_RELIC_ANALYZER_VIRUS_COHERENCE,
                )
            implantType.isShieldUpgradesImplant() ->
                withMergedMainSource(SHIELD_UPGRADES_POWER_NEED)
            implantType.isSanshaModifiedGnomeImplant() ->
                withoutMainSource(
                    SHIELD_HP,
                    SHIELD_RECHARGE_TIME
                )
            implantType.isShieldManagementImplant() ->
                withMergedMainSource(SHIELD_HP)
            implantType.isShieldEmissionSystemsImplant() ->
                withMergedMainSource(SHIELD_EMISSION_CAPACITOR_NEED)
            implantType.isShieldOperationImplant() ->
                withMergedMainSource(SHIELD_RECHARGE_TIME)
            implantType.isSignatureAnalysisImplant() ->
                withMergedMainSource(SCAN_RESOLUTION)
            implantType.isLongRangeTargetingImplant() ->
                withMergedMainSource(TARGETING_RANGE)
            implantType.isMindlinkImplant() ->
                withoutMainSource(
                    allSourcesMissingText = "No relevant command bursts fitted",
                    MINDLINK_SHIELD_BONUS,
                    MINDLINK_ARMOR_BONUS,
                    MINDLINK_SKIRMISH_BONUS,
                    MINDLINK_INFORMATION_BONUS,
                )
            else -> null
        }
    }
}


/**
 * The sources of implant effects.
 */
private object ImplantEffectSources{


    /**
     * The effect on the capacitor need of modules requiring the Propulsion Jamming skill.
     */
    val PROPULSION_JAMMING_CAPACITOR_NEED = filteredCapacitorNeed(
        description = "capacitor need of propulsion jamming modules",
        missingText = "No propulsion jamming modules fitted",
        filter = { it.isSkillRequired(PROPULSION_JAMMING_SKILL_ID) }
    )


    /**
     * The effect on the capacitor need of modules requiring the Sensor Linking skill.
     */
    val SENSOR_LINKING_CAPACITOR_NEED = filteredCapacitorNeed(
        description = "capacitor need of sensor linking modules",
        missingText = "No sensor linking modules fitted",
        filter = { it.isSkillRequired(SENSOR_LINKING_SKILL_ID) }
    )


    /**
     * The effect on the capacitor need of modules requiring the Target Painting skill.
     */
    val TARGET_PAINTING_CAPACITOR_NEED = filteredCapacitorNeed(
        description = "capacitor need of target painting modules",
        missingText = "No target painting modules fitted",
        filter = { it.isSkillRequired(TARGET_PAINTING_SKILL_ID) }
    )


    /**
     * The effect on the capacitor need of modules requiring the Weapon Disruption skill.
     */
    val WEAPON_DISRUPTION_CAPACITOR_NEED = filteredCapacitorNeed(
        description = "capacitor need of weapon disruption modules",
        missingText = "No weapon disruption modules fitted",
        filter = { it.isSkillRequired(WEAPON_DISRUPTION_SKILL_ID) }
    )


    /**
     * The effect on the CPU requirements of modules requiring the Energy Grid Upgrades skill.
     */
    val ENERGY_GRID_UPGRADES_CPU_NEED = cpuNeed(
        description = "cpu need of energy grid upgrades modules",
        missingText = "No energy grid upgrades modules fitted"
    )


    /**
     * The effect on the activation duration of modules requiring the Energy Pulse Weapons skill (smartbombs).
     */
    val SMARTBOMB_DURATION = filteredModuleDuration(
        description = "smartbomb duration",
        missingText = "No smartbombs fitted",
        filter = ModuleType::isSmartbomb
    )


    /**
     * The effect on small projectile weapon damage.
     */
    val SMALL_PROJECTILE_WEAPONS_DAMAGE = turretDamage("small projectile weapon")


    /**
     * The effect on small laser weapon damage.
     */
    val SMALL_ENERGY_WEAPONS_DAMAGE = turretDamage("small energy weapon")


    /**
     * The effect on small hybrid weapon damage.
     */
    val SMALL_HYBRID_WEAPONS_DAMAGE = turretDamage("small hybrid weapon")


    /**
     * The effect on medium projectile weapon damage.
     */
    val MEDIUM_PROJECTILE_WEAPONS_DAMAGE = turretDamage("medium projectile weapon")


    /**
     * The effect on medium laser weapon damage.
     */
    val MEDIUM_ENERGY_WEAPONS_DAMAGE = turretDamage("medium energy weapon")


    /**
     * The effect on medium hybrid weapon damage.
     */
    val MEDIUM_HYBRID_WEAPONS_DAMAGE = turretDamage("medium hybrid weapon")


    /**
     * The effect on large projectile weapon damage.
     */
    val LARGE_PROJECTILE_WEAPONS_DAMAGE = turretDamage("large projectile weapon")


    /**
     * The effect on large laser weapon damage.
     */
    val LARGE_ENERGY_WEAPONS_DAMAGE = turretDamage("large energy weapon")


    /**
     * The effect on large hybrid weapon damage.
     */
    val LARGE_HYBRID_WEAPONS_DAMAGE = turretDamage("large hybrid weapon")


    /**
     * The effect on XL torpedo damage.
     */
    val XL_TORPEDO_DAMAGE = missileDamage(
        description = "XL torpedo volley damage",
        missingText = "No XL torpedoes fitted"
    )


    /**
     * The effect on cruise missile damage.
     */
    val CRUISE_MISSILE_DAMAGE = missileDamage(
        description = "cruise missile volley damage",
        missingText = "No cruise missiles fitted"
    )


    /**
     * The effect on torpedo damage.
     */
    val TORPEDO_DAMAGE = missileDamage(
        description = "torpedo volley damage",
        missingText = "No torpedoes fitted"
    )


    /**
     * The effect on heavy assault missile damage.
     */
    val HEAVY_ASSAULT_MISSILE_DAMAGE = missileDamage(
        description = "heavy assault missile volley damage",
        missingText = "No heavy assault missiles fitted"
    )


    /**
     * The effect on heavy missile damage.
     */
    val HEAVY_MISSILE_DAMAGE = missileDamage(
        description = "heavy missile volley damage",
        missingText = "No heavy missiles fitted"
    )


    /**
     * The effect on light missile damage.
     */
    val LIGHT_MISSILE_DAMAGE = missileDamage(
        description = "light missile volley damage",
        missingText = "No light missiles fitted"
    )


    /**
     * The effect on rocket damage.
     */
    val ROCKET_DAMAGE = missileDamage(
        description = "rocket volley damage",
        missingText = "No rockets fitted"
    )


    /**
     * The effect on missile velocity.
     */
    val DEFENDER_MISSILE_VELOCITY = AppliedEffectSource.fromOptionalProperty(
        property = { fit, affectedProperties ->
            fit.anyAffectedChargeProperty(affectedProperties, Charge::missileVelocity)
        },
        description = "defender missile velocity",
        absoluteValue = { value, withSign -> value.asSpeed(withSign = withSign) },
        missingText = "No defender missiles fitted"
    )


    /**
     * The effect on the explosion radius of auto-targeting missiles.
     */
    val AUTO_TARGETING_MISSILES_EXPLOSION_RADIUS = AppliedEffectSource.fromOptionalProperty(
        property = { fit, affectedProperties ->
            fit.anyAffectedChargeProperty(affectedProperties, Charge::missileExplosionRadius)
        },
        description = "auto-targeting missile explosion radius",
        absoluteValue = { value, withSign -> value.asDistance(withSign = withSign) },
        missingText = "No auto-targeting missiles fitted"
    )


    /**
     * The effect on the speed factor bonus of propulsion modules.
     */
    val PROPMOD_SPEED_FACTOR_BONUS = AppliedEffectSource.fromOptionalProperty(
        property = { fit, affectedProperties ->
            fit.anyAffectedModuleProperty(affectedProperties, Module::speedFactorBonus)
        },
        description = "propulsion module speed factor",
        absoluteValue = { value, withSign -> value.asSpeed(withSign = withSign) },
        missingText = "No propulsion modules fitted"
    )


    /**
     * The effect on the duration of afterburners.
     */
    val AFTERBURNER_DURATION = filteredModuleDuration(
        description = "afterburner duration",
        missingText = "No afterburner fitted",
        filter = { it.isSkillRequired(AFTERBURNER_SKILL_ID) }
    )


    /**
     * The effect on the capacitor need of afterburners.
     */
    val AFTERBURNER_CAPACITOR_NEED = filteredCapacitorNeed(
        description = "capacitor need of afterburners",
        missingText = "No afterburner fitted",
        filter = { it.isSkillRequired(AFTERBURNER_SKILL_ID) }
    )


    /**
     * The effect on the capacitor need of microwarpdrives.
     */
    val MICROWARPDRIVE_CAPACITOR_NEED = filteredCapacitorNeed(
        description = "capacitor need of microwarpdrives",
        missingText = "No microwarpdrives fitted",
        filter = { it.isSkillRequired(HIGH_SPEED_MANEUVERING_SKILL_ID) }
    )


    /**
     * The effect on the cycle time of salvagers.
     */
    val SALVAGER_CYCLE_DURATION = filteredModuleDuration(
        description = "cycle time of salvagers",
        missingText = "No salvagers fitted",
        filter = ModuleType::isSalvager
    )


    /**
     * The effect on the cycle time of data/relic analyzers.
     */
    val DATA_AND_RELIC_ANALYZER_CYCLE_DURATION = filteredModuleDuration(
        description = "cycle time of data/relic analyzers",
        missingText = "No data/relic analyzers fitted",
        filter = ModuleType::isDataMiner
    )


    /**
     * The effect on the virus coherence of data/relic analyzers.
     */
    val DATA_AND_RELIC_ANALYZER_VIRUS_COHERENCE = filteredModuleDuration(
        description = "data/relic analyzer virus coherence",
        missingText = "No data/relic analyzers fitted",
        filter = ModuleType::isDataMiner
    )


    /**
     * The effect on the capacitor need of shield emission modules (remote shield boosters).
     */
    val SHIELD_EMISSION_CAPACITOR_NEED = filteredCapacitorNeed(
        description = "capacitor need of remote shield boosters",
        missingText = "No remote shield boosters fitted",
        filter = {
            it.isSkillRequired(SHIELD_EMISSION_SYSTEMS_SKILL_ID) ||
            it.isSkillRequired(CAPITAL_SHIELD_EMISSION_SYSTEMS_SKILL_ID)
        }
    )


    /**
     * Returns the mindlink bonus effect with the given name.
     */
    private fun mindlinkBonus(
        name: String,
        moduleFilter: EveData.(ModuleType) -> Boolean,
    ) = AppliedEffectSource.fromOptionalProperty(
        property = { fit, affectedProperties ->
            // Just use the effect on buff duration because the other effects have the same value
            fit.anyAffectedModuleProperty(
                affectedProperties = affectedProperties,
                filter = moduleFilter,
                selector = Module::buffDuration
            )
        },
        description = "$name burst effect strength & duration",
        absoluteValue = { value, withSign -> value.asPercentage(withSign = withSign, precision = 1) },
        missingText = "No $name command bursts fitted"
    )


    /**
     * The mindlink effect on shield command bursts.
     */
    val MINDLINK_SHIELD_BONUS = mindlinkBonus("shield", moduleFilter = ModuleType::isShieldCommandBurst)


    /**
     * The mindlink effect on armor command bursts.
     */
    val MINDLINK_ARMOR_BONUS = mindlinkBonus("armor", moduleFilter = ModuleType::isArmorCommandBurst)


    /**
     * The mindlink effect on skirmish command bursts.
     */
    val MINDLINK_SKIRMISH_BONUS = mindlinkBonus("skirmish", moduleFilter = ModuleType::isSkirmishCommandBurst)


    /**
     * The mindlink effect on information command bursts.
     */
    val MINDLINK_INFORMATION_BONUS = mindlinkBonus("information", moduleFilter = ModuleType::isInformationCommandBurst)


}
