package com.performancecoachlab.posedetection.recording

import android.graphics.Bitmap
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import com.google.mlkit.vision.pose.PoseDetection
import com.google.mlkit.vision.pose.defaults.PoseDetectorOptions
import com.performancecoachlab.posedetection.camera.drawAnalysisResults
import com.performancecoachlab.posedetection.camera.drawSkeleton
import com.performancecoachlab.posedetection.camera.process
import com.performancecoachlab.posedetection.custom.ObjectModel
import com.performancecoachlab.posedetection.skeleton.Skeleton
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume

actual class InputFrame(val bitmap: Bitmap, actual val timestamp: Long) {
    actual fun toImageBitmap(): ImageBitmap {
        return bitmap.asImageBitmap()
    }

    actual fun drawSkeleton(skel: Skeleton): ImageBitmap {
        return toImageBitmap().drawSkeleton(skel)
    }

    actual fun drawAnalysisResults(analysisResults: AnalysisResult): ImageBitmap {
        return toImageBitmap().drawAnalysisResults(analysisResults)
    }

    actual fun crop(rect: Rect): InputFrame {
        val width = bitmap.width
        val height = bitmap.height
        val sanitised = Rect(
            left = rect.left.coerceIn(0f, width.toFloat()),
            top = rect.top.coerceIn(0f, height.toFloat()),
            right = rect.right.coerceIn(0f, width.toFloat()),
            bottom = rect.bottom.coerceIn(0f, height.toFloat())
        )
        val croppedBitmap = Bitmap.createBitmap(
            bitmap,
            sanitised.left.toInt(),
            sanitised.top.toInt(),
            sanitised.width.toInt(),
            sanitised.height.toInt()
        )
        return InputFrame(croppedBitmap, timestamp)
    }
}

actual class FrameAnalyser actual constructor(val model: ObjectModel?) {
    private val options =
        PoseDetectorOptions.Builder().setDetectorMode(PoseDetectorOptions.STREAM_MODE).build()
    private val poseDetector = PoseDetection.getClient(options)
    private val objDetector = model?.getDetector()
    actual suspend fun analyseFrame(inputFrame: InputFrame, focusArea: Rect?): AnalysisResult =
        suspendCancellableCoroutine { continuation ->
            inputFrame.bitmap.process(
                objDetector, poseDetector, inputFrame.timestamp,focusArea
            ) { result, bitmap ->
                continuation.resume(result)
            }
        }
}