package app.furmeet.events.system.helper

import kotlin.math.*

private enum class LuminanceCoefficients(val r: Double, val g: Double, val b: Double) {
    CCIR601(0.299, 0.587, 0.114),
    BT709(0.2126, 0.7152, 0.0722),
    SMPTE240M(0.212, 0.701, 0.087)
}

private val lumaCoefficientsInUse = LuminanceCoefficients.BT709
private val relativeLuminance = Triple(
        lumaCoefficientsInUse.r,
        lumaCoefficientsInUse.g,
        lumaCoefficientsInUse.b
)
private val Int.asRGBTriple
    get() = Triple(
            this.and(0x00FF0000).shr(16),
            this.and(0x0000FF00).shr(8),
            this.and(0x000000FF)
    )
private const val gamut: Double = 1.8

private val Triple<Int, Int, Int>.luminance
    get(): Int {
        val channelTupleRelative = this zip relativeLuminance
        val luma = channelTupleRelative.toList().map { it.first.toDouble().pow(gamut) * it.second }.sum().pow(1 / gamut)
        return luma.roundToInt().boundToRange(0, 255)
    }

private val Int.luminance
    get(): Int = this.asRGBTriple.luminance

fun Int.decideBestForegroundColor(vararg colors: Int): Int {
    //val backgroundLuma = this.luminance
    return colors.map { foregroundColor ->
        Pair(foregroundColor, (this.asRGBTriple zip foregroundColor.asRGBTriple).map { (it.first - it.second).absoluteValue }.luminance)
        //Pair(foregroundColor, (backgroundLuma - foregroundColor.luminance).absoluteValue)
    }.sortedBy {
        it.second // contrast
    }.last().first
}

fun Int.boundToRange(lower: Int, upper: Int): Int = max(lower, min(upper, this))
infix fun <A1, A2, A3, B1, B2, B3> Triple<A1, A2, A3>.zip(that: Triple<B1, B2, B3>) = Triple(
        Pair(this.first, that.first),
        Pair(this.second, that.second),
        Pair(this.third, that.third)
)

inline fun <T, R> Triple<T, T, T>.map(transform: (T) -> R): Triple<R, R, R> = Triple(
        transform(this.first),
        transform(this.second),
        transform(this.third)
)
//fun <T> List<T>.toTriple(): Triple<T, T, T> = Triple(this[0], this[1], this[2])
