package com.intergration.test.dms

import android.os.Environment
import com.arcsoft.visdrive.sdk.ArcErrorInfo
import com.arcsoft.visdrive.sdk.ArcVisDriveEngine
import com.arcsoft.visdrive.sdk.constant.common.ArcAlarmSensitivityLevel
import com.arcsoft.visdrive.sdk.constant.common.ArcImageFormat
import com.arcsoft.visdrive.sdk.constant.common.ArcModType
import com.arcsoft.visdrive.sdk.constant.dms.ArcDMSAlarmType
import com.arcsoft.visdrive.sdk.constant.dms.ArcDMSDetectMaskType
import com.arcsoft.visdrive.sdk.model.common.ArcDrivingStatus
import com.arcsoft.visdrive.sdk.model.common.ArcInitParamInfo
import com.arcsoft.visdrive.sdk.model.common.ArcInitParamInfoDetail
import com.arcsoft.visdrive.sdk.model.dms.ArcDMSAlarmParam
import com.arcsoft.visdrive.sdk.model.dms.ArcDMSDetectResult
import com.arcsoft.visdrive.sdk.model.dms.ArcDMSDistractScope
import com.arcsoft.visdrive.sdk.model.dms.ArcDMSInitParam
import com.blankj.utilcode.util.FileUtils
import com.blankj.utilcode.util.LogUtils
import com.intergration.test.utils.DMS_PIC_HEIGHT
import com.intergration.test.utils.DMS_PIC_WIDTH
import com.intergration.test.utils.toByteBuffer
import com.mediatek.smartplatform.ImageReaderEx
import com.mediatek.smartplatform.PictureConfiguration
import com.mediatek.smartplatform.PictureSequenceSource
import com.mediatek.smartplatform.SmartPlatformManager
import com.mediatek.smartplatform.SpmCameraDevice
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.callbackFlow
import java.io.Closeable
import java.io.File
import java.util.concurrent.Executors
import kotlin.coroutines.AbstractCoroutineContextElement
import kotlin.coroutines.CoroutineContext

val COROUTINE_DMS = CoroutineName("dms")

const val CAMERA_ID_DMS = "0"

val dmsResult by lazy {
    ArcDMSDetectResult()
}

class DmsCoroutineContext(val engine: ArcVisDriveEngine,val spmCameraDevice: SpmCameraDevice): AbstractCoroutineContextElement(DmsCoroutineContext){
    companion object Key:CoroutineContext.Key<DmsCoroutineContext>
}

class DmsCoroutineScope(context: CoroutineContext) : Closeable, CoroutineScope {
    override val coroutineContext: CoroutineContext = context + SupervisorJob()
    override fun close() {
        LogUtils.eTag("dms","DmsCoroutineScope.close")
        SmartPlatformManager.get().closeCameraDevice(coroutineContext[DmsCoroutineContext]?.spmCameraDevice)
        coroutineContext.cancel()
    }
}

private val dmsWorker by lazy {
    Executors.newSingleThreadExecutor()
}

val dmsEngine by lazy {
    ArcVisDriveEngine()
}

fun ArcVisDriveEngine.initializeDms():Int{
    val dmsInitParam = ArcDMSInitParam().apply {
        detectMask = ArcDMSDetectMaskType.MOD_DMS_CALL or
                ArcDMSDetectMaskType.MOD_DMS_SMOKE or
                ArcDMSDetectMaskType.MOD_DMS_CLOSE_EYE or
                ArcDMSDetectMaskType.MOD_DMS_YAWN or
                ArcDMSDetectMaskType.MOD_DMS_DISTRACT or
                ArcDMSDetectMaskType.MOD_DMS_DRIVER_ABNORMAL or
                ArcDMSDetectMaskType.MOD_DMS_LENS_COVERED
    }
    val initParamDetail = ArcInitParamInfoDetail()
    initParamDetail.modType = ArcModType.TYPE_DMS
    initParamDetail.arcInitParamBase = dmsInitParam
    val arcInfoParam = ArcInitParamInfo()
    arcInfoParam.arcInitParamInfoDetailArray = Array(1) { initParamDetail }
    return init(arcInfoParam)
}

/**
 * 打电话参数设置
 *
 * */
fun ArcVisDriveEngine.setDmsAlarmCallParams(interval:Int = 30, speedThreshold:Int = 33){
    val dmsAlarmParam = ArcDMSAlarmParam()
    val result = getDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_CALL, dmsAlarmParam)
    if (result == ArcErrorInfo.ARC_ERROR_OK) {
        dmsAlarmParam.sensitivityLevel = ArcAlarmSensitivityLevel.ALARM_SENSITIVITY_MEDIUM
        dmsAlarmParam.arcAlarmParam.interval = interval
        dmsAlarmParam.arcAlarmParam.speedThreshold = speedThreshold
        setDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_CALL, dmsAlarmParam)
    }
}
/**
 * 抽烟参数设置
 *
 * */
fun ArcVisDriveEngine.setDmsAlarmSmokeParams(interval:Int = 30, speedThreshold:Int = 33){
    val dmsAlarmParam = ArcDMSAlarmParam()
    val result = getDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_SMOKE, dmsAlarmParam)
    if (result == ArcErrorInfo.ARC_ERROR_OK) {
        dmsAlarmParam.sensitivityLevel = ArcAlarmSensitivityLevel.ALARM_SENSITIVITY_MEDIUM
        dmsAlarmParam.arcAlarmParam.interval = interval
        dmsAlarmParam.arcAlarmParam.speedThreshold = speedThreshold
        setDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_SMOKE, dmsAlarmParam)
    }
}
/**
 * 闭眼睛参数设置
 *
 * */
fun ArcVisDriveEngine.setDmsAlarmCloseEyeParams(interval:Int = 30, speedThreshold:Int = 33){
    val dmsAlarmParam = ArcDMSAlarmParam()
    val result = getDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_CLOSE_EYE, dmsAlarmParam)
    if (result == ArcErrorInfo.ARC_ERROR_OK) {
        dmsAlarmParam.sensitivityLevel = ArcAlarmSensitivityLevel.ALARM_SENSITIVITY_MEDIUM
        dmsAlarmParam.arcAlarmParam.interval = interval
        dmsAlarmParam.arcAlarmParam.speedThreshold = speedThreshold
        setDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_CLOSE_EYE, dmsAlarmParam)
    }
}
/**
 * 打哈欠参数设置
 *
 * */
fun ArcVisDriveEngine.setDmsAlarmYawnParams(interval:Int = 30, speedThreshold:Int = 33){
    val dmsAlarmParam = ArcDMSAlarmParam()
    val result = getDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_YAWN, dmsAlarmParam)
    if (result == ArcErrorInfo.ARC_ERROR_OK) {
        dmsAlarmParam.sensitivityLevel = ArcAlarmSensitivityLevel.ALARM_SENSITIVITY_MEDIUM
        dmsAlarmParam.arcAlarmParam.interval = interval
        dmsAlarmParam.arcAlarmParam.speedThreshold = speedThreshold
        setDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_YAWN, dmsAlarmParam)
    }
}
/**
 * 分神参数设置
 *
 * */
fun ArcVisDriveEngine.setDmsAlarmDistractParams(interval:Int = 30, speedThreshold:Int = 33){
    val dmsAlarmParam = ArcDMSAlarmParam()
    val result = getDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_DISTRACT, dmsAlarmParam)
    if (result == ArcErrorInfo.ARC_ERROR_OK) {
        dmsAlarmParam.sensitivityLevel = ArcAlarmSensitivityLevel.ALARM_SENSITIVITY_MEDIUM
        dmsAlarmParam.arcAlarmParam.interval = interval
        dmsAlarmParam.arcAlarmParam.speedThreshold = speedThreshold
        setDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_DISTRACT, dmsAlarmParam)
    }
}
/**
 * 驾驶员异常参数设置
 *
 * */
fun ArcVisDriveEngine.setDmsAlarmDriverAbnormalParams(interval:Int = 120, speedThreshold:Int = 33){
    val dmsAlarmParam = ArcDMSAlarmParam()
    val result = getDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_DRIVER_ABNORMAL, dmsAlarmParam)
    if (result == ArcErrorInfo.ARC_ERROR_OK) {
        dmsAlarmParam.sensitivityLevel = ArcAlarmSensitivityLevel.ALARM_SENSITIVITY_LOW
        dmsAlarmParam.arcAlarmParam.interval = interval
        dmsAlarmParam.arcAlarmParam.speedThreshold = speedThreshold
        setDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_DRIVER_ABNORMAL, dmsAlarmParam)
    }
}
/**
 * 遮挡镜头参数设置
 *
 * */
fun ArcVisDriveEngine.setDmsAlarmLensCoveredParams(interval:Int = 60, speedThreshold:Int = 33){
    val dmsAlarmParam = ArcDMSAlarmParam()
    val result = getDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_LENS_COVERED, dmsAlarmParam)
    if (result == ArcErrorInfo.ARC_ERROR_OK) {
        dmsAlarmParam.sensitivityLevel = ArcAlarmSensitivityLevel.ALARM_SENSITIVITY_LOW
        dmsAlarmParam.arcAlarmParam.interval = interval
        dmsAlarmParam.arcAlarmParam.speedThreshold = speedThreshold
        setDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_LENS_COVERED, dmsAlarmParam)
    }
}

fun ArcVisDriveEngine.setDmsDistractScope(leftYaw:Int = -30,rightYaw:Int = 30,upPitch:Int = 20,downPitch:Int = -20):Int{
    val dmsScope = ArcDMSDistractScope()
    var result = getDMSDistractScopeParam(dmsScope)
    return if (result == ArcErrorInfo.ARC_ERROR_OK) {
        /**
         * 以下为模拟修改数值，实际使用请根据真实环境设置
         */
        dmsScope.leftYaw = leftYaw
        dmsScope.rightYaw = rightYaw
        dmsScope.upPitch = upPitch
        dmsScope.downPitch = downPitch
        setDMSDistractScopeParam(dmsScope)
    } else result
}

fun ArcVisDriveEngine.setDmsDrivingStatus(speed:Int = 50):Int{
    val driveStatus = ArcDrivingStatus()
    driveStatus.speed = speed
    return setDrivingStatus(driveStatus)
}

fun SpmCameraDevice.startDms(engin:ArcVisDriveEngine) = callbackFlow{
    val dmsDir = File(Environment.getExternalStorageDirectory(),"dms/")
    if (!FileUtils.isFileExists(dmsDir)) {
        FileUtils.createOrExistsDir(dmsDir)
    }
    val pictureConfig = PictureConfiguration.get(PictureSequenceSource.GENERAL_CAMERA)
    pictureConfig.mPath = dmsDir.absolutePath
    pictureConfig.mImageFormat = SpmCameraDevice.ImageDataCallback.IMAGE_FORMAT_NV21
    pictureConfig.mPicWidth = DMS_PIC_WIDTH
    pictureConfig.mPicHeight = DMS_PIC_HEIGHT
    pictureConfig.mDataType = SpmCameraDevice.ImageDataCallback.IMAGE_DATA_RAW
    pictureConfig.mImageCallback = ImageReaderEx.ImageCallback { _, _, _, data, _ ->
        dmsWorker.execute {
            val dmsResp = engin.detectDMS(pictureConfig.mPicWidth,pictureConfig.mPicHeight,
                ArcImageFormat.ARC_IMAGE_FORMAT_NV21,
                data.toByteBuffer(),dmsResult)
            if (dmsResp == ArcErrorInfo.ARC_ERROR_OK) {
                when (dmsResult.alarmMask) {
                    ArcDMSDetectMaskType.MOD_DMS_CALL -> {
                        trySend("打电话")
                        LogUtils.dTag("dms", "打电话")
                    }

                    ArcDMSDetectMaskType.MOD_DMS_CLOSE_EYE -> {
                        trySend( "闭眼睛")
                        LogUtils.dTag("dms", "闭眼睛")
                    }

                    ArcDMSDetectMaskType.MOD_DMS_SMOKE -> {
                        trySend("抽烟")
                        LogUtils.dTag("dms", "抽烟")
                    }

                    ArcDMSDetectMaskType.MOD_DMS_YAWN -> {
                        trySend("打哈欠报警")
                        LogUtils.dTag("dms", "打哈欠报警")
                    }

                    ArcDMSDetectMaskType.MOD_DMS_DISTRACT -> {
                        trySend("分神")
                        LogUtils.dTag("dms", "分神")
                    }

                    ArcDMSDetectMaskType.MOD_DMS_DRIVER_ABNORMAL -> {
                        trySend("驾驶员异常报警")
                        LogUtils.dTag("dms", "驾驶员异常报警")
                    }

                    ArcDMSDetectMaskType.MOD_DMS_LENS_COVERED -> {
                        trySend("遮挡镜头")
                        LogUtils.dTag("dms", "遮挡镜头")
                    }

                    ArcDMSDetectMaskType.MOD_DMS_SEATBELT_UNFASTENED -> {
                        trySend("不知道")
                        LogUtils.dTag("dms", "不知道")
                    }
                }
            } else {
                LogUtils.dTag("dms","dms检测识别，错误码:$dmsResp")
            }
        }
    }
    startPictureSequence(PictureSequenceSource.GENERAL_CAMERA,pictureConfig)
    awaitClose {
        LogUtils.e("dms","dms detect ended")
        stopPictureSequence(PictureSequenceSource.GENERAL_CAMERA)
        engin.unInit()
    }
}