/**
 * The UI showing the remaining fit stats that don't belong in any of the major sections.
 */

package theorycrafter.ui.fitstats

import androidx.compose.runtime.*
import compose.widgets.SingleLineText
import eve.data.*
import theorycrafter.*
import theorycrafter.fitting.CapacitorStability
import theorycrafter.fitting.Fit
import theorycrafter.ui.TheorycrafterTheme
import theorycrafter.ui.fiteditor.ValueWithDescription


/**
 * UI showing the miscellaneous stats.
 */
@Composable
fun MiscStats(fit: Fit) {
    with(fit) {
        val signatureRadius = ship.signatureRadius.value
        val capacitorStability = capacitor.stability
        val capacitorCapacity = capacitor.capacity.value
        val capacitorPeakRechargeRate = capacitor.peakRechargeRate
        val droneControlRange = fit.drones.controlRange.value
        val energyNeutralizationResonance = fit.electronicWarfare.energyNeutralizationResistance.value

        val energyNeutralizationTooltip = if (energyNeutralizationResonance != 1.0) {
            ValueWithDescription(
                value = energyNeutralizationResonance.resonanceAsResistancePercentageWithPrecisionAtMost(0),
                description = "resistance to energy neutralization"
            )
        } else null

        val priceInfo = fit.fitPriceInfo()
        fun ValueWithDescription(priceInfo: ItemsPriceInfo, description: String): ValueWithDescription {
            return ValueWithDescription(
                value = priceInfo.price.asIsk(withUnits = false),
                description = "$description${priceInfo.uncertaintySuffix}"
            )
        }

        StatsTable(
            columns = 2,
            Stat(label = "Signature", signatureRadius.asSignatureRadius(withUnits = true)),
            Stat(
                label = "Capacitor",
                value = capacitorStability.displayText(),
                tooltipValues = listOfNotNull(
                    ValueWithDescription(value = capacitorCapacity.asCapacitorEnergy(), description = "capacity"),
                    ValueWithDescription(
                        value = (capacitorStability.capGain + capacitorPeakRechargeRate).asCapacitorEnergyPerSecond(),
                        description = "peak gain"
                    ),
                    ValueWithDescription(
                        value = capacitorStability.capDrain.asCapacitorEnergyPerSecond(),
                        description = "average drain"
                    ),
                    ValueWithDescription(
                        value = capacitorPeakRechargeRate.asCapacitorEnergyPerSecond(),
                        description = "peak recharge rate"
                    ),
                    energyNeutralizationTooltip
                )
            ),
            Stat(label = "Drone Control", droneControlRange.asDistance(withUnits = true)),
            Stat(
                label = "Fit Price",
                value = priceInfo?.total?.toDisplayString(withIsk = true) ?: "Fetching…",
                tooltipValues = if (priceInfo == null) emptyList() else listOfNotNull(
                    ValueWithDescription(priceInfo = priceInfo.ship, description = "ship"),
                    priceInfo.subsystems?.let { ValueWithDescription(priceInfo = it, description = "subsystems") },
                    ValueWithDescription(priceInfo = priceInfo.modules, description = "modules and rigs"),
                    ValueWithDescription(priceInfo = priceInfo.charges, description = "charges and scripts"),
                    ValueWithDescription(priceInfo = priceInfo.drones, description = "drones"),
                    ValueWithDescription(priceInfo = priceInfo.implants, description = "implants"),
                    ValueWithDescription(priceInfo = priceInfo.boosters, description = "boosters"),
                    ValueWithDescription(priceInfo = priceInfo.cargo, description = "cargo"),
                ),
                extraTooltipContent = if ((priceInfo != null) && (priceInfo.total.priceIsUnknown || priceInfo.total.priceIsOverride))
                    { ->
                        SingleLineText(
                            text = buildString {
                                if (priceInfo.total.priceIsUnknown)
                                    appendLine("${PriceUnknownSymbol}some prices unknown")
                                if (priceInfo.total.priceIsOverride)
                                    appendLine("${PriceOverrideSymbol}some prices overridden")
                            }.trim(),
                            style = TheorycrafterTheme.textStyles.footnote,
                        )
                    }
                else
                    null
            ),
        )
    }
}


/**
 * Formats the capacitor stability for display.
 */
private fun CapacitorStability.displayText() = when (this) {
    is CapacitorStability.Stable -> {
        "Stable at ${minCapacityRelative.fractionAsPercentage(0)}"
    }
    is CapacitorStability.Unstable -> {
        "Lasts ${(timeUntilDepleted * 1000.0).millisAsTime()}"
    }
}


/**
 * The segregation of fit prices into the parts needed to display it.
 */
private data class FitPriceInfo(
    val total: ItemsPriceInfo,
    val ship: ItemsPriceInfo,
    val subsystems: ItemsPriceInfo?,
    val modules: ItemsPriceInfo,
    val charges: ItemsPriceInfo,
    val drones: ItemsPriceInfo,
    val implants: ItemsPriceInfo,
    val boosters: ItemsPriceInfo,
    val cargo: ItemsPriceInfo,
)


/**
 * Returns the [FitPriceInfo] of the fit, `null` if unknown.
 */
@Composable
private fun Fit.fitPriceInfo(): FitPriceInfo? {
    val prices = TheorycrafterContext.eveItemPrices ?: return null
    val ship = prices.priceInfoOf(ship)
    val subsystems by rememberDerivedPriceComputationState(prices) { subsystemByKind?.values?.priceInfo() }
    val modules by rememberDerivedPriceComputationState(prices) { modules.priceInfo() }
    val charges by rememberDerivedPriceComputationState(prices) { this.modules.chargesPrice() }
    val drones by rememberDerivedPriceComputationState(prices) { drones.priceInfo() }
    val implants by rememberDerivedPriceComputationState(prices) { implants.priceInfo() }
    val boosters by rememberDerivedPriceComputationState(prices) { boosters.priceInfo() }
    val cargo by rememberDerivedPriceComputationState(prices) { cargohold.priceInfo() }
    val total = ship +
            subsystems +
            modules +
            drones +
            implants +
            boosters +
            cargo

    return FitPriceInfo(
        total = total,
        ship = ship,
        subsystems = subsystems,
        modules = modules,
        charges = charges,
        drones = drones,
        implants = implants,
        boosters = boosters,
        cargo = cargo,
    )
}


/**
 * Returns a remembered [derivedStateOf] of the given fit computation
 */
@Composable
private fun <T> Fit.rememberDerivedPriceComputationState(
    prices: EveItemPrices,
    computation: context(EveItemPrices)() -> T
): State<T> {
    return remember(this, prices) {
        derivedStateOf {
            computation(prices)
        }
    }
}
