/**
 * Utilities related to fonts.
 */

package theorycrafter.utils

import androidx.compose.material.LocalTextStyle
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalFontFamilyResolver
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontSynthesis
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.platform.FontLoadResult
import androidx.compose.ui.text.platform.toSkFontStyle
import androidx.compose.ui.text.resolveDefaults
import androidx.compose.ui.unit.Density
import org.jetbrains.skia.FontMetrics


/**
 * Returns a remembered font metrics for the current text style, density and font family resolver.
 */
@Composable
fun rememberLocalFontMetrics(textStyle: TextStyle = LocalTextStyle.current): FontMetrics {
    val fontFamilyResolver = LocalFontFamilyResolver.current
    val density = LocalDensity.current
    val layoutDirection = LocalLayoutDirection.current
    return remember(textStyle, density, layoutDirection, fontFamilyResolver) {
        val resolvedStyle = resolveDefaults(textStyle, layoutDirection)
        resolvedStyle.fontMetrics(density, fontFamilyResolver)
    }
}


/**
 * Returns the font metrics for the [TextStyle].
 */
fun TextStyle.fontMetrics(
    density: Density,
    fontFamilyResolver: FontFamily.Resolver,
): FontMetrics {
    val skiaStyle = org.jetbrains.skia.paragraph.TextStyle()

    fontStyle?.let {
        skiaStyle.fontStyle = it.toSkFontStyle()
    }

    fontWeight?.let {
        skiaStyle.fontStyle = skiaStyle.fontStyle.withWeight(it.weight)
    }

    skiaStyle.fontSize = with(density) { fontSize.toPx() }

    fontFamily?.let {
        val resolved = fontFamilyResolver.resolve(
            it,
            fontWeight ?: FontWeight.Normal,
            fontStyle ?: FontStyle.Normal,
            fontSynthesis ?: FontSynthesis.None
        ).value as FontLoadResult
        skiaStyle.fontFamilies = resolved.aliases.toTypedArray()
        skiaStyle.typeface = resolved.typeface
    }

    return skiaStyle.fontMetrics
}
