package theorycrafter.ui.fitstats

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.LocalContentColor
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import compose.utils.EasyTooltipPlacement
import compose.utils.EqualRoomCentered
import compose.utils.VerticallyCenteredRow
import compose.widgets.ContentWithScrollbar
import eve.data.ShipType
import theorycrafter.TheorycrafterContext
import theorycrafter.fitting.Fit
import theorycrafter.ui.TheorycrafterTheme
import theorycrafter.ui.fiteditor.ValueWithDescription
import theorycrafter.ui.fiteditor.ValueWithDescriptionTable
import theorycrafter.ui.tooltip
import theorycrafter.utils.AttractAttentionOnValueChange
import theorycrafter.utils.DpOffsetY


/**
 * The UI displaying the fit statistics.
 */
@Composable
fun FitStats(
    fit: Fit,
    modifier: Modifier = Modifier
) {
    FitStatsImpl(
        fit = fit,
        modifier = modifier
    )
}


/**
 * The actual implementation of the fit stats UI.
 */
@Composable
private fun FitStatsImpl(
    fit: Fit,
    modifier: Modifier
) {
    ContentWithScrollbar(modifier = modifier) {
        Column(
            modifier = Modifier
                .verticalScroll(scrollState)
                .padding(vertical = TheorycrafterTheme.spacing.larger),
        ) {
            val spacingModifier = Modifier.padding(bottom = TheorycrafterTheme.spacing.xxlarge)

            StatsSection("Fitting", spacingModifier) {
                FittingResourceStats(fit)
            }

            StatsSection("Defenses", spacingModifier) {
                DefenseStats(fit)
            }

            val totalDps = fit.firepower.totalDps
            val totalReps = fit.remoteRepairs.total
            val isLogistics = fit.ship.type.isLogistics()
            AnimatedVisibility(visible = !isLogistics || (totalDps > 0.0)) {
                StatsSection("Firepower", spacingModifier) {
                    FirepowerStats(fit)
                }
            }
            AnimatedVisibility(visible = isLogistics || (totalReps > 0.0)) {
                StatsSection("Remote Repairs", spacingModifier) {
                    RemoteRepairStats(fit)
                }
            }

            StatsSection("Mobility", spacingModifier) {
                MobilityStats(fit)
            }

            StatsSection("Targeting", spacingModifier) {
                TargetingStats(fit)
            }

            StatsSection("Misc") {
                MiscStats(fit)
            }
        }
    }
}


/**
 * A horizontal line.
 */
@Composable
private fun HorizontalLine(
    modifier: Modifier
) {
    val color = LocalContentColor.current.copy(alpha = 0.2f)
    Box(modifier.drawBehind {
        drawLine(
            color = color,
            start = Offset(0f, size.height/2),
            end = Offset(size.width, size.height/2)
        )
    })
}


/**
 * A title with a horizontal line through it.
 */
@Composable
private fun TitleWithLine(
    text: String,
    modifier: Modifier
) {
    VerticallyCenteredRow(
        modifier = modifier,
        horizontalArrangement = Arrangement.spacedBy(TheorycrafterTheme.spacing.xsmall),
    ) {
        HorizontalLine(
            Modifier
                .width(TheorycrafterTheme.spacing.horizontalEdgeMargin)
        )
        Text(
            text = text,
            style = TheorycrafterTheme.textStyles.mediumHeading
        )
        HorizontalLine(
            Modifier
                .fillMaxWidth(1f)
        )
    }
}


/**
 * A titled section in the stats panel.
 */
@Composable
private fun StatsSection(
    title: String,
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
    Column(
        modifier = modifier.fillMaxWidth(),
        verticalArrangement = Arrangement.spacedBy(TheorycrafterTheme.spacing.medium)
    ) {
        TitleWithLine(
            text = title,
            modifier = Modifier.fillMaxWidth()
        )
        Box(Modifier.padding(horizontal = TheorycrafterTheme.spacing.horizontalEdgeMargin)) {
            content()
        }
    }
}


/**
 * A single fit stat to display.
 */
class Stat(


    /**
     * The label (name) of the state.
     */
    val label: String,


    /**
     * The stat value to display.
     */
    val value: String,


    /**
     * The extra, related, stats to display in the tooltip.
     */
    val tooltipValues: List<ValueWithDescription> = emptyList(),


    /**
     * Extra content to append at the bottom of the tooltip.
     */
    val extraTooltipContent: @Composable (ColumnScope.() -> Unit)? = null


)


/**
 * A table of stats.
 */
@Composable
fun StatsTable(columns: Int, vararg stats: Stat){
    val statsList = stats.asList()
    val rows = (statsList.size + columns - 1) / columns  // Round up to multiple of columns

    Column(
        verticalArrangement = Arrangement.spacedBy(TheorycrafterTheme.spacing.small),
        modifier = Modifier.fillMaxWidth()
    ) {
        for (rowIndex in 0 until rows){
            val statsInRow = statsList.subList(columns*rowIndex, (columns*(rowIndex+1)).coerceAtMost(statsList.size))
            Row(
                modifier = Modifier
                    .padding(bottom = if (rowIndex < rows-1) TheorycrafterTheme.spacing.small else 0.dp)
                    .fillMaxWidth(),
                horizontalArrangement = Arrangement.EqualRoomCentered
            ) {
                for (stat in statsInRow) {
                    Column(
                        horizontalAlignment = Alignment.CenterHorizontally,
                        modifier = Modifier.tooltip(
                            placement = EasyTooltipPlacement.ElementBottomCenter(
                                offset = DpOffsetY(TheorycrafterTheme.spacing.xxsmall)
                            ),
                            content = if (stat.tooltipValues.isEmpty() && stat.extraTooltipContent == null)
                                null
                            else @Composable { ->
                                Column(verticalArrangement = Arrangement.spacedBy(TheorycrafterTheme.spacing.small)) {
                                    if (stat.tooltipValues.isNotEmpty()) {
                                        ValueWithDescriptionTable(stat.tooltipValues)
                                    }
                                    stat.extraTooltipContent?.invoke(this)
                                }
                            }
                        )
                    ) {
                        Text(
                            text = stat.label,
                            textAlign = TextAlign.Center,
                            style = TheorycrafterTheme.textStyles.caption,
                        )

                        val attentionValues: Any =
                            if (stat.tooltipValues.isEmpty())
                                stat.value
                            else buildList {
                                add(stat.value)
                                stat.tooltipValues.forEach {
                                    add(it.value)
                                }
                            }
                        AttractAttentionOnValueChange(value = attentionValues){
                            Text(
                                text = stat.value,
                                textAlign = TextAlign.Center,
                            )
                        }
                    }
                }
            }
        }
    }
}


/**
 * Returns whether the given ship is in general considered a logistics ship, providing remote repairs.
 */
private fun ShipType.isLogistics(): Boolean {
    val eveData = TheorycrafterContext.eveData
    with(eveData.marketGroups) {
        marketGroup?.let {
            if (logistics.isAncestorOf(it) || logisticsFrigates.isAncestorOf(it) || forceAuxiliaries.isAncestorOf(it))
                return true
        }
    }

    return when (name) {
        "Augoror", "Osprey", "Exequror", "Scythe", "Inquisitor", "Bantam", "Navitas", "Burst" -> true
        else -> false
    }
}
