package theorycrafter.ui.widgets

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
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.clip
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import eve.data.fractionAsPercentage
import theorycrafter.ui.TheorycrafterTheme
import theorycrafter.utils.darker


/**
 * A horizontal box displaying a percentage value.
 */
@Composable
fun PercentageView(


    /**
     * The value to display; a number between 0 and 1, inclusive.
     */
    value: Float,


    /**
     * The number of decimal digits to display.
     */
    decimals: Int,


    /**
     * Whether to animate value changes.
     */
    animate: Boolean = true,


    /**
     * The widget colors.
     */
    colors: PercentageViewColors,


    /**
     * A modifier to apply to the top-level element.
     */
    modifier: Modifier = Modifier


) {
    if (value.isNaN() || value.isInfinite())
        throw IllegalArgumentException("Illegal value: $value")

    val displayedValue = if (animate)
        animateFloatAsState(
            targetValue = value,
            animationSpec = tween()
        ).value
    else
        value

    Box(
        contentAlignment = Alignment.Center,
        modifier = modifier
            .border(
                width = Dp.Hairline,
                color = LocalContentColor.current.copy(alpha = 0.25f),
                shape = RoundedCornerShape(2.dp)
            )
            .clip(
                RoundedCornerShape(2.dp)
            )
            .drawBehind {
                drawRect(colors.unfilled)
                drawRect(colors.filled,
                    topLeft = Offset.Zero,
                    size = Size(
                        width = (size.width * displayedValue).coerceAtMost(size.width),
                        height = size.height
                    )
                )
            }
    ) {
        // The percentage text
        Text(
            text = displayedValue.toDouble().let {
                if (it > 9.99)
                    ">999%"
                else
                    it.fractionAsPercentage(decimals)
            }.withShadow(colors.textShadowColor),
            maxLines = 1,
            overflow = TextOverflow.Visible,
            textAlign = TextAlign.Center,
            style = TheorycrafterTheme.textStyles.percentageView,
            color = colors.textColor,
            modifier = Modifier
                .padding(4.dp)
                .fillMaxWidth()
        )
    }
}


/**
 * Encapsulates the colors used for [PercentageView]
 */
data class PercentageViewColors(
    val textColor: Color,
    val textShadowColor: Color,
    val filled: Color,
    val unfilled: Color = filled.darker(0.3f),
)


/**
 * Returns an [AnnotatedString] of the given string with a shadow of the given color.
 */
private fun String.withShadow(shadowColor: Color) = AnnotatedString(
    text = this,
    spanStyle = SpanStyle(
        shadow = Shadow(
            color = shadowColor,
            offset = Offset(x = 1f, y = 1f)
        )
    )
)