package theorycrafter.fitting

import androidx.compose.runtime.Stable
import eve.data.Attributes
import eve.data.SubsystemType
import theorycrafter.fitting.utils.memoize


/**
 * An instance of a strategic cruiser subsystem.
 */
@Stable
class Subsystem internal constructor(


    /**
     * The fit this subsystem is part of.
     */
    override val fit: Fit,


    /**
     * The context [Attributes].
     */
    attributes: Attributes,


    /**
     * The subsystem type.
     */
    type: SubsystemType,


): EveItem<SubsystemType>(attributes, type), FitItem{


    /**
     * The bonus to ship powergrid, as percentage.
     */
    val powerOutputPercentageBonus: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.powerEngineeringOutputBonus)


    /**
     * The bonus to ship CPU, as percentage.
     */
    val cpuOutputPercentageBonus: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.cpuOutputBonus2)


    /**
     * The flat bonus to ship powergrid.
     */
    val powerOutputFlatBonus: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.powerOutput)


    /**
     * The flat bonus to ship CPU.
     */
    val cpuOutputFlatBonus: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.cpuOutput)


    /**
     * The flat bonus to capacitor capacity.
     */
    val capacitorCapacityFlatBonus: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.capacitorCapacity)


    /**
     * The flat bonus to maximum number of locked targets.
     */
    val maxLockedTargetsBonus: AttributeProperty<Int>?
        get() = propertyOrNull(attributes.maxLockedTargetsBonus)


    /**
     * The flat bonus to shield hitpoints.
     */
    val shieldFlatHpBonus: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.shieldHp)


    /**
     * The flat bonus to armor hitpoints.
     */
    val armorHpFlatBonus: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.armorHpBonusAdd)


    /**
     * The flat bonus to structure hitpoints.
     */
    val structureHpFlatBonus: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.structureHpBonusAdd)


    /**
     * The flat bonus to signature radius.
     */
    val signatureRadius: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.signatureRadius)


    /**
     * The reduction in armor plate mass penalty, as percentage.
     */
    val bonusMassAddition: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.subsystemBonusMassAddition)


    /**
     * The reduction in fitting needs (PG and CPU) of energy neutralizers and nosferatus.
     */
    val energyNeutFittingReduction: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.subsystemEnergyNeutFittingReduction)


    /**
     * The reduction in fitting needs (PG and CPU) of cruiser-sized missile launchers.
     */
    val medMissileFittingReduction: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.subsystemMedMissileFittingReduction)


    /**
     * The reduction in fitting needs (PG and CPU) for medium energy turrets.
     */
    val medEnergyTurretFittingReduction: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.subsystemMedEnergyTurretFittingReduction)


    /**
     * The reduction in fitting needs (PG and CPU) for medium hybrid turrets.
     */
    val medHybridTurretFittingReduction: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.subsystemMedHybridTurretFittingReduction)


    /**
     * The reduction in fitting needs (PG and CPU) for medium projectile turrets.
     */
    val medProjectileTurretFittingReduction: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.subsystemMedProjectibeTurretFittingReduction)


    /**
     * The reduction in fitting needs (PG and CPU) for medium remote shield boosters.
     */
    val medRsbFittingReduction: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.subsystemMedRemoteShieldBoosterFittingReduction)


    /**
     * The reduction in fitting needs (PG and CPU) for medium remote armor repairers.
     */
    val medRarFittingReduction: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.subsystemMedRemoteArmorRepairerFittingReduction)


    /**
     * The reduction in fitting needs (PG and CPU) for command bursts.
     */
    val commandBurstFittingReduction: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.subsystemCommandBurstFittingReduction)


    /**
     * The fraction of CPU required to fit cloaking devices with this subsystem.
     */
    val cloakingCpuNeedBonus: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.cloakingCpuNeedBonus)


    /**
     * The cloak reactivation delay, in milliseconds.
     */
    val covertOpsAndReconOpsCloakModuleDelay: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.covertOpsAndReconOpsCloakModuleDelay)


    /**
     * The amount of cargo capacity added by this subsystem.
     */
    val cargoCapacityAdd: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.cargoCapacityAdd)


    /**
     * The flat bonus to drone capacity.
     */
    val droneCapacityBonus: AttributeProperty<Int>?
        get() = propertyOrNull(attributes.droneCapacity)


    /**
     * The flat bonus to drone bandwidth.
     */
    val droneBandwidthBonus: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.droneBandwidth)


    /**
     * The bonus to remote armor repairer optimal range.
     */
    val remoteArmorRepairerOptimalBonus: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.remoteArmorRepairerOptimalBonus)


    /**
     * The bonus to remote armor repairer falloff.
     */
    val remoteArmorRepairerFalloffBonus: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.remoteArmorRepairerFalloffBonus)


    /**
     * The bonus to remote shield booster falloff.
     */
    val remoteShieldBoosterFalloffBonus: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.remoteShieldBoosterFalloffBonus)


    /**
     * The bonus to command burst area of effect range.
     */
    val commandBurstRange: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.roleBonusCommandBurstAoERange)


    /**
     * The bonus (or penalty) to maximum targeting range.
     */
    val maxTargetRangeBonus: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.targetingRange)


    /**
     * The bonus (or penalty) to ship agility.
     */
    val agilityBonusAdd: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.agilityBonusAdd)


    /**
     * The 1st role bonus property.
     */
    val shipBonusRole1: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.shipBonusRole1)


    /**
     * The 2nd role bonus property.
     */
    val shipBonusRole2: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.shipBonusRole2)



    /**
     * The Legion Core Subsystem bonus properties.
     */
    private val bonusAmarrCore: List<AttributeProperty<Double>?> = attributes.subsystems.bonusAmarrCore.map {
        propertyOrNull(it)
    }


    /**
     * The Tengu Core Subsystem bonus property.
     */
    private val bonusCaldariCore: List<AttributeProperty<Double>?> = attributes.subsystems.bonusCaldariCore.map {
        propertyOrNull(it)
    }


    /**
     * The Loki Core Subsystem bonus property.
     */
    private val bonusMinmatarCore: List<AttributeProperty<Double>?> = attributes.subsystems.bonusMinmatarCore.map {
        propertyOrNull(it)
    }


    /**
     * The Proteus Core Subsystem bonus property.
     */
    private val bonusGallenteCore: List<AttributeProperty<Double>?> = attributes.subsystems.bonusGallenteCore.map {
        propertyOrNull(it)
    }


    /**
     * The Legion Defensive Subsystem bonus properties.
     */
    private val bonusAmarrDefensive: List<AttributeProperty<Double>?> = attributes.subsystems.bonusAmarrDefensive.map {
        propertyOrNull(it)
    }


    /**
     * The Tengu Defensive Subsystem bonus property.
     */
    private val bonusCaldariDefensive: List<AttributeProperty<Double>?> = attributes.subsystems.bonusCaldariDefensive.map {
        propertyOrNull(it)
    }


    /**
     * The Loki Defensive Subsystem bonus property.
     */
    private val bonusMinmatarDefensive: List<AttributeProperty<Double>?> = attributes.subsystems.bonusMinmatarDefensive.map {
        propertyOrNull(it)
    }


    /**
     * The Proteus Defensive Subsystem bonus property.
     */
    private val bonusGallenteDefensive: List<AttributeProperty<Double>?> = attributes.subsystems.bonusGallenteDefensive.map {
        propertyOrNull(it)
    }


    /**
     * The Legion Offensive Subsystem bonus properties.
     */
    private val bonusAmarrOffensive: List<AttributeProperty<Double>?> = attributes.subsystems.bonusAmarrOffensive.map {
        propertyOrNull(it)
    }


    /**
     * The Tengu Offensive Subsystem bonus property.
     */
    private val bonusCaldariOffensive: List<AttributeProperty<Double>?> = attributes.subsystems.bonusCaldariOffensive.map {
        propertyOrNull(it)
    }


    /**
     * The Loki Offensive Subsystem bonus property.
     */
    private val bonusMinmatarOffensive: List<AttributeProperty<Double>?> = attributes.subsystems.bonusMinmatarOffensive.map {
        propertyOrNull(it)
    }


    /**
     * The Proteus Offensive Subsystem bonus property.
     */
    private val bonusGallenteOffensive: List<AttributeProperty<Double>?> = attributes.subsystems.bonusGallenteOffensive.map {
        propertyOrNull(it)
    }


    /**
     * The Legion Propulsion Subsystem bonus properties.
     */
    private val bonusAmarrPropulsion: List<AttributeProperty<Double>?> = attributes.subsystems.bonusAmarrPropulsion.map {
        propertyOrNull(it)
    }


    /**
     * The Tengu Propulsion Subsystem bonus property.
     */
    private val bonusCaldariPropulsion: List<AttributeProperty<Double>?> = attributes.subsystems.bonusCaldariPropulsion.map {
        propertyOrNull(it)
    }


    /**
     * The Loki Propulsion Subsystem bonus property.
     */
    private val bonusMinmatarPropulsion: List<AttributeProperty<Double>?> = attributes.subsystems.bonusMinmatarPropulsion.map {
        propertyOrNull(it)
    }


    /**
     * The Proteus Propulsion Subsystem bonus property.
     */
    private val bonusGallentePropulsion: List<AttributeProperty<Double>?> = attributes.subsystems.bonusGallentePropulsion.map {
        propertyOrNull(it)
    }


    /**
     * Returns the `n`-th Core Subsystem property.
     */
    val coreBonusProperty: (index: Int) -> AttributeProperty<Double>? = memoize { index ->
        bonusAmarrCore.getOrNull(index)
            ?: bonusCaldariCore.getOrNull(index)
            ?: bonusGallenteCore.getOrNull(index)
            ?: bonusMinmatarCore.getOrNull(index)
    }


    /**
     * Returns the `n`-th Defensive Subsystem property.
     */
    val defensiveBonusProperty: (index: Int) -> AttributeProperty<Double>? = memoize { index ->
        bonusAmarrDefensive.getOrNull(index)
            ?: bonusCaldariDefensive.getOrNull(index)
            ?: bonusGallenteDefensive.getOrNull(index)
            ?: bonusMinmatarDefensive.getOrNull(index)
    }


    /**
     * Returns the `n`-th Offensive Subsystem property.
     */
    val offensiveBonusProperty: (index: Int) -> AttributeProperty<Double>? = memoize { index ->
        bonusAmarrOffensive.getOrNull(index)
            ?: bonusCaldariOffensive.getOrNull(index)
            ?: bonusGallenteOffensive.getOrNull(index)
            ?: bonusMinmatarOffensive.getOrNull(index)
    }


    /**
     * Returns the `n`-th Propulsion Subsystem property.
     */
    val propulsionBonusProperty: (index: Int) -> AttributeProperty<Double>? = memoize { index ->
        bonusAmarrPropulsion.getOrNull(index)
            ?: bonusCaldariPropulsion.getOrNull(index)
            ?: bonusGallentePropulsion.getOrNull(index)
            ?: bonusMinmatarPropulsion.getOrNull(index)
    }


}
