package theorycrafter.ui.graphs

import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import compose.widgets.GraphLine
import eve.data.asCapacitorEnergyPerSecond
import eve.data.asHitpointsPerSecond
import eve.data.fractionAsPercentageWithPrecisionAtMost
import theorycrafter.fits.FitHandle
import theorycrafter.fitting.Fit
import theorycrafter.fitting.maxRechargeRate
import theorycrafter.fitting.rechargeRate


/**
 * A graph pane displaying the regeneration of shield/capacitor.
 */
@Composable
private fun RegenerationGraphPane(
    initialFitHandle: FitHandle?,
    totalAmount: (Fit) -> Double,
    rechargeTime: (Fit) -> Double,
    valueFormatter: (Double) -> String,
) {
    FitsGraphPane(
        initialFitHandle = initialFitHandle,
        graph = { fits, modifier ->
            RegenerationGraph(
                fits = fits,
                totalAmount = totalAmount,
                rechargeTime = rechargeTime,
                valueFormatter = valueFormatter,
                modifier = modifier
            )
        }
    )
}


/**
 * A graph displaying the regeneration of shield/capacitor.
 */
@Composable
private fun RegenerationGraph(
    fits: List<GraphFit>,
    totalAmount: (Fit) -> Double,
    rechargeTime: (Fit) -> Double,
    valueFormatter: (Double) -> String,
    modifier: Modifier = Modifier,
) {
    val maxDisplayedValue = fits.maxOfOrNull {
        val fit = it.fit
        maxRechargeRate(
            maxValue = totalAmount(fit),
            rechargeTime = rechargeTime(fit)
        )
    }?.times(1.1) ?: 100.0
    BasicGraph(
        modifier = modifier,
        xRange = 0.0 .. 1.1,
        yRange = 0.0 .. maxDisplayedValue,
        xValueFormatter = { it.fractionAsPercentageWithPrecisionAtMost(1) },
        yValueFormatter = valueFormatter,
        lines = fits.map { graphFit ->
            val fit = graphFit.fit
            val totalAmountValue = totalAmount(fit)
            val rechargeTimeValue = rechargeTime(fit)
            GraphLine(
                name = graphFit.name,
                function = { fraction ->
                    rechargeRate(
                        value = totalAmountValue * fraction,
                        maxValue = totalAmountValue,
                        rechargeTime = rechargeTimeValue,
                    )
                },
                samplingStepPx = DefaultLineSamplingStep,
                lineStyleAtPoint = {
                    val regularStyle = defaultLineStyle(graphFit.color)
                    return@GraphLine { x, _ ->
                        if (x <= 1.0) regularStyle else null
                    }
                }
            )
        }
    )
}


/**
 * A graph pane displaying the capacitor regeneration of fits.
 */
@Composable
fun CapacitorRegenerationGraphPane(initialFitHandle: FitHandle?) {
    RegenerationGraphPane(
        initialFitHandle = initialFitHandle,
        totalAmount = { it.capacitor.capacity.value },
        rechargeTime = { it.capacitor.rechargeTime.value },
        valueFormatter = { it.asCapacitorEnergyPerSecond() }
    )
}


/**
 * A graph pane displaying the shield regeneration of fits.
 */
@Composable
fun ShieldRegenerationGraphPane(initialFitHandle: FitHandle?) {
    RegenerationGraphPane(
        initialFitHandle = initialFitHandle,
        totalAmount = { it.defenses.shield.hp.value },
        rechargeTime = { it.defenses.shield.rechargeTime.value },
        valueFormatter = { it.asHitpointsPerSecond() }
    )
}
