package theorycrafter.fitting

import androidx.compose.runtime.Stable
import eve.data.Attributes
import eve.data.ModuleType
import eve.data.ShipType


/**
 * An instance of a ship.
 */
@Stable
class Ship internal constructor(


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


    /**
     * The ship type.
     */
    type: ShipType


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


    /**
     * The fit this ship is part of.
     */
    override lateinit var fit: Fit
        internal set


    /**
     * Signature radius, in meters.
     */
    val signatureRadius: AttributeProperty<Double>
        get() = property(attributes.signatureRadius)


    /**
     * CPU output of the ship, in teraflops.
     */
    val cpuOutput: AttributeProperty<Double>
        get() = property(attributes.cpuOutput)


    /**
     * Power output of the ship, in megawatts.
     */
    val powerOutput: AttributeProperty<Double>
        get() = property(attributes.powerOutput)


    /**
     * The calibration amount of the ship.
     */
    val calibration: AttributeProperty<Int>
        get() = property(attributes.calibration)


    /**
     * The number of turret hardpoints on this ship.
     */
    val turretHardpoints: AttributeProperty<Int>
        get() = property(attributes.turretHardpoints)


    /**
     * The number of launcher hardpoints on this ship.
     */
    val launcherHardpoints: AttributeProperty<Int>
        get() = property(attributes.launcherHardpoints)


    /**
     * The ship's cargo capacity, in m^3.
     */
    val cargoCapacity: AttributeProperty<Double>
        get() = property(attributes.capacity)



    /**
     * The drone bay capacity, in m^3.
     */
    val droneCapacity: AttributeProperty<Int>
        get() = property(attributes.droneCapacity)


    /**
     * The drone bandwidth, in megabit/s.
     */
    val droneBandwidth: AttributeProperty<Double>
        get() = property(attributes.droneBandwidth)


    /**
     * The ship's mass.
     */
    val mass: AttributeProperty<Double>
        get() = property(attributes.mass)


    /**
     * The ship's inertia modifier.
     */
    val inertiaModifier: AttributeProperty<Double>
        get() = property(attributes.inertiaModifier)


    /**
     * The ship's radius, in meters.
     */
    val radius: AttributeProperty<Double>
        get() = property(attributes.radius)


    /**
     * The factor of capacitor amount needed to enter warp. Note that this is not the actual amount, as that depends on
     * mass, distance and skills.
     */
    val warpCapacitorNeed: AttributeProperty<Double>
        get() = property(attributes.warpCapacitorNeed)


    /**
     * The maximum number of targets this ship can lock.
     */
    val maxLockedTargets: AttributeProperty<Int>
        get() = property(attributes.maxLockedTargets)


    /**
     * The amount of fuel needed for a jump.
     */
    val jumpDriveConsumptionAmount: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.jumpDriveConsumptionAmount)


    /**
     * The ship's warp speed, in AU/sec.
     *
     * Note that although there is also a "baseWarpSpeed" attribute, its value seems to be 1.0 for all ships, and there
     * are no effects that reference it. All effects on the warp speed affect the warp speed multiplier.
     * Therefore, this value can effectively be used as the warp speed itself, in AU/s.
     */
    val warpSpeed: AttributeProperty<Double>
        get() = property(attributes.warpSpeedMultiplier)


    /**
     * The effectiveness of remote repairs on this ship (a value between 0 and 1).
     */
    val remoteRepairEffectiveness: AttributeProperty<Double>
        get() = property(attributes.remoteRepairImpedance)


    /**
     * The effectiveness of remote assistance (RSBs, RTCs) on this ship (a value between 0 and 1).
     */
    val remoteAssistanceEffectiveness: AttributeProperty<Double>
        get() = property(attributes.remoteAssistanceImpedance)


    /**
     * The pilot's security status, if relevant to the ship.
     */
    val pilotSecurityStatus: AttributeProperty<Double>?
        get() = propertyOrNull(attributes.pilotSecurityStatus)


    /**
     * Sets the pilot's security status.
     */
    context(FittingEngine.ModificationScope)
    fun setPilotSecurityStatus(securityStatus: Double){
        setPinnedPropertyValue(attributes.pilotSecurityStatus, securityStatus)
    }


    /**
     * Returns whether the given module can be fitted onto this ship.
     */
    fun canFit(moduleType: ModuleType): Boolean {
        val shipType = this.type
        if (!shipType.canFit(moduleType))
            return false

        if (moduleType.takesTurretHardpoint && (this.turretHardpoints.value == 0))
            return false
        if (moduleType.takesLauncherHardpoint && (this.launcherHardpoints.value == 0))
            return false

        return true
    }


    /**
     * Returns the list of values that affect the result of [canFit].
     */
    val canFitModuleKeys: Collection<Any>
        get() = listOf(turretHardpoints.value, launcherHardpoints.value)


}