package com.performancecoachlab.posedetection.camera

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.DrawStyle
import androidx.compose.ui.graphics.drawscope.Stroke
import com.performancecoachlab.posedetection.custom.CustomObjectRespository
import com.performancecoachlab.posedetection.custom.ObjectModel
import com.performancecoachlab.posedetection.recording.AnalysisObject
import com.performancecoachlab.posedetection.skeleton.SkeletonRepository

enum class DetectMode { NONE, POSE, OBJECT, BOTH }

fun DetectMode.doPose(): Boolean {
    return this == DetectMode.POSE || this == DetectMode.BOTH
}

fun DetectMode.doObject(): Boolean {
    return this == DetectMode.OBJECT || this == DetectMode.BOTH
}

enum class PreviewFillMode {
    /** Show the full camera frame inside the view (letterbox/pillarbox as needed). */
    FIT,

    /** Fill the view and crop excess (center-crop). */
    FILL
}

/**
 * How the focus area is applied to the pose input.
 *
 * MASK — black out everything outside the focus area, then downscale the full
 * frame. Object detection is unaffected (it always sees the unmasked frame).
 *
 * CROP — crop the frame to the focus area, then downscale only the crop. Gives
 * the pose model higher effective resolution of the focus region at the same
 * downscaled side length. Landmarks are remapped back to full-frame coords.
 */
enum class PoseFocusMode { MASK, CROP }

@Composable
expect fun CameraView(
    skeletonRepository: SkeletonRepository,
    customObjectRepository: CustomObjectRespository,
    detectMode: DetectMode = DetectMode.BOTH,
    drawSkeleton: Boolean = true,
    objectModel: ObjectModel? = null,
    drawObjects: ((List<AnalysisObject>) -> List<DrawableObject>)? = { objs ->
        objs.map { DrawableObject(it) }
    },
    modifier: Modifier = Modifier.fillMaxSize(),
    frontCamera: Boolean = true,
    useUltraWide: Boolean = false,
    previewFillMode: PreviewFillMode = PreviewFillMode.FILL,
    recordingId: String? = null,
    focusArea: Rect? = null,
    poseFocusMode: PoseFocusMode = PoseFocusMode.MASK,
    controller: CameraViewController? = null,
    onRecordToggled: (Boolean) -> Unit = {},
    onVideoSaved: (String, String) -> Unit
)

data class DrawableObject(
    val obj: AnalysisObject,
    val shape: DrawableShape = DrawableShape.RECTANGLE,
    val colour: Color = Color.Red,
    val style: DrawStyle = Stroke(5f),
)

enum class DrawableShape {
    OVAL, RECTANGLE, LABEL
}

data class CameraViewData(
    val width: Float,
    val height: Float,
    val rotation: SensorRotation,
)

enum class SensorRotation {
    ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270
}


interface CameraViewController {
    fun requestData(onResult: (CameraViewData) -> Unit)
    fun setRequestDataProvider(provider: (() -> CameraViewData)?)
}

class CameraViewControllerImpl : CameraViewController {
    private var dataProvider: (() -> CameraViewData)? = null
    override fun requestData(onResult: (CameraViewData) -> Unit) {
        dataProvider?.let { onResult(it()) }
    }

    override fun setRequestDataProvider(provider: (() -> CameraViewData)?) {
        dataProvider = provider
    }
}