package com.laseroptek.raman.ui.screens.home.slider

import android.annotation.SuppressLint
import android.content.res.Configuration
import android.util.Log
import android.view.MotionEvent
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.input.pointer.pointerInteropFilter
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.res.imageResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.round
import com.laseroptek.raman.R
import com.laseroptek.raman.utils.ext.px
import timber.log.Timber
import kotlin.math.PI
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.min
import kotlin.math.sin
import kotlin.math.sqrt

@SuppressLint("NewApi")
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun CircularSlider(
    modifier: Modifier = Modifier.Companion,
    angleNew: Float = 0f,
    padding: Float = 10f,
    stroke: Float = 30f,
    touchStroke: Float = 60f,
    cap: StrokeCap = StrokeCap.Round,
    onChange: ((Float) -> Unit)? = null
) {
    Timber.d("angleNew: ${angleNew}")

    var width by remember { mutableStateOf(0) }
    var height by remember { mutableStateOf(0) }
    var angleOld by remember { mutableStateOf(  angleNew ) }
    var nearTheThumbIndicator by remember {
        mutableStateOf(
            false
        )
    }
    var radius by remember { mutableStateOf(10f) }
    var center by remember {
        mutableStateOf(
            Offset.Zero
        )
    }
    var appliedAngle by remember {
        mutableStateOf(
            0f
        )
    }
    val trackColor: Color = Color(212,212,212)
    val trackBorderColor: Color = Color(164,164,164)
    val gradientBorderColor: Color = Color(100,0,100)

    //Timber.d("radius: ${radius}, center: ${center}")
    //Timber.d("angleNew.value: ${angleNew.value}, angleOld: ${angleOld}")

    LaunchedEffect(key1 = angleOld) {
        Timber.d(">> angleOld: %f", angleOld)

        if (angleOld > 270.0f && angleOld < 315.0f) {
            angleOld = 270.0f
        } else if (angleOld >= 315.0f && angleOld < 360f) {
            angleOld = 0.0f
        } else if (angleOld >= 360f) {
            angleOld = 0f
        }

        appliedAngle = angleOld

        Timber.d(">> appliedAngle: %f", appliedAngle)
        onChange?.invoke(appliedAngle)
    }

    appliedAngle = angleNew
    val sweepAngle = -(270.0f - appliedAngle)

    Timber.d("## appliedAngle: $appliedAngle, sweepAngle: $sweepAngle")
    val gradient = Brush.sweepGradient(
        colorStops = arrayOf(
            0.0f to Color(216,33,9),
            0.1f to Color(216,33,9),
            0.3f to Color(250,250,3),
            0.4f to Color(255,245,0),
            1.0f to Color(216,33,9),
        ),
        center = Offset(width / 2f, height / 2f)
    )



    val imageBitMap = ImageBitmap.imageResource(
        id = R.drawable.ic_btn_control
    )


    Canvas(
        modifier = modifier
            .onGloballyPositioned {
                width = it.size.width
                height = it.size.height
                center = Offset(width / 2f, height / 2f)
                radius = min(width.toFloat(), height.toFloat()) / 2f - padding - stroke / 2f
            }
            .pointerInteropFilter {
                val x = it.x
                val y = it.y
                val offset = Offset(x, y)
                when (it.action) {
                    MotionEvent.ACTION_DOWN -> {
                        val d = distance(offset, center)
                        val a = angle(center, offset)
                        if (d >= radius - touchStroke / 2f && d <= radius + touchStroke / 2f) {
                            nearTheThumbIndicator = true
                            if (a >= 0 && a <= 270) {
                                Timber.d("ACTION_DOWN: angle: %f", a)
                                angleOld = a
                            }
                        } else {
                            nearTheThumbIndicator = false
                        }
                    }

                    MotionEvent.ACTION_MOVE -> {
                        if (nearTheThumbIndicator) {
                            val angleMove = angle(center, offset)
                            //if (angleMove >=0 && angleMove <= 270) {
                                Timber.d("ACTION_MOVE: angle: %f", angleMove)
                                angleOld = angleMove
                            //}
                        }
                    }

                    MotionEvent.ACTION_UP -> {
                        Timber.d("ACTION_UP")

                        nearTheThumbIndicator = false
                    }

                    else -> return@pointerInteropFilter false
                }
                return@pointerInteropFilter true
            }
    ) {
        //Timber.d("appliedAngle: $appliedAngle, sweepAngle: $sweepAngle")

        // background border
        drawArc(
            color = trackBorderColor,
            startAngle = 45f,
            sweepAngle = -270f,
            topLeft = center - Offset(radius, radius),
            size = Size(radius * 2, radius * 2),
            useCenter = false,
            style = Stroke(
                width = stroke + 0.1f,
                cap = cap
            )
        )

        // background
        drawArc(
            color = trackColor,
            startAngle = 45f,
            sweepAngle = -270f,
            topLeft = center - Offset(radius, radius),
            size = Size(radius * 2, radius * 2),
            useCenter = false,
            style = Stroke(
                width = stroke,
                cap = cap
            )
        )

        // background
        drawArc(
            color = gradientBorderColor,
            startAngle = 135f,
            sweepAngle = appliedAngle,
            topLeft = center - Offset(radius, radius),
            size = Size(radius * 2, radius * 2),
            useCenter = false,
            style = Stroke(
                width = stroke + 0.1f,
                cap = cap
            ),
        )

        drawArc(
            brush = gradient,
            startAngle = 135f,
            sweepAngle = appliedAngle,
            topLeft = center - Offset(radius, radius),
            size = Size(radius * 2, radius * 2),
            useCenter = false,
            style = Stroke(
                width = stroke,
                cap = cap
            ),
        )

        drawImage(
            image = imageBitMap,
            dstOffset = Offset(
                (center.x - padding - stroke) + (radius) * cos( (appliedAngle + 135.0f) * PI / 180.0 ).toFloat(),
                (center.y - padding/2 - stroke) + (radius) * sin( (appliedAngle + 135.0f) * PI / 180.0 ).toFloat()
            ).round(),
            dstSize = IntSize((stroke * 3).toInt(), (stroke * 3).toInt()),
        )
    }
}

// 135.0도를 시작점 0 도로 계산 ~ 270도 까지
fun angle(center: Offset, offset: Offset, startAngle: Float = 135.0f): Float {
    val rad = atan2(offset.y - center.y, offset.x - center.x)
    var deg = Math.toDegrees(rad.toDouble())
    deg = (deg + 360) % 360
    var deg2 = deg - startAngle
    deg2 = (deg2 + 360) % 360

    Timber.d("org: $deg, new: $deg2")
    return deg2.toFloat()
}

fun distance(first: Offset, second: Offset): Float {
    return sqrt((first.x - second.x).square() + (first.y - second.y).square())
}

fun Float.square(): Float {
    return this * this
}

@Preview(
    uiMode = Configuration.UI_MODE_NIGHT_NO,
    showBackground = false,
    device = "spec:width=1080dp,height=720dp,dpi=150,isRound=false,chinSize=0dp,orientation=landscape"
)
@Composable
fun preViewCircularSlider() {
    CircularSlider(
        modifier = Modifier.size(400.px.dp),
    ) {
        Log.d("OnChange: Original VAL", "${it * 180}")
        var sliderPercentage = it
        var currTempValue = 16 + (sliderPercentage * 16)
        var roundedTempValue = "%.0f".format(currTempValue)
        //mainViewModel.tempValue.value = roundedTempValue
        Log.d("progress", "$roundedTempValue°C")

        //onChange?.invoke(it * 180f)
    }
}