package com.adealink.weparty.hardware

import com.adealink.frame.aab.util.getCompatString
import com.adealink.frame.base.IError
import com.adealink.frame.base.Rlt
import com.adealink.weparty.R
import com.adealink.weparty.hardware.resource.HardwareResource
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume

class HardwareManager : IHardwareManager {
    override fun checkHardwareAvailable(vararg hardwareList: Hardware): Rlt<Any> {
        for (hardware in hardwareList) {
            val hardwareResource: HardwareResource = HardwareConflictDetector.getHardwareResource(hardware) ?: continue
            if (!hardwareResource.isAvailable) {
                return Rlt.Failed(IError(msg = getCompatString(R.string.common_hardware_is_busy, hardware.getDesc(), hardwareResource.currentClient?.clientDesc ?: "")))
            }
        }
        return Rlt.Success(true)
    }

    override fun requestHardware(client: HardwareClient, priority: HardwarePriority, hardware: Hardware, callback: HardwareRequestCallback?) {
        HardwareConflictDetector.requestResource(hardware, client, priority, callback)
    }

    override suspend fun requestHardware(client: HardwareClient, priority: HardwarePriority, vararg hardwareList: Hardware): Rlt<Any> {
        var requestRlt: Rlt<Any>? = null
        for (hardware in hardwareList) {
            val rlt = suspendRequestHardware(client, priority, hardware)
            if (rlt is Rlt.Failed) {
                requestRlt = rlt
            }
        }
        return requestRlt ?: Rlt.Success(Any())
    }

    private suspend fun suspendRequestHardware(client: HardwareClient, priority: HardwarePriority, hardware: Hardware): Rlt<Any> {
        return suspendCancellableCoroutine { continuation ->
            HardwareConflictDetector.requestResource(hardware, client, priority, object : HardwareRequestCallback {
                override fun onGranted() {
                    if (continuation.isActive) {
                        continuation.resume(Rlt.Success(Any()))
                    }
                }

                override fun onDenied(reason: Int) {
                    if (continuation.isActive) {
                        continuation.resume(Rlt.Failed(IError()))
                    }
                }

                override fun onPreempted() {
                    if (continuation.isActive) {
                        continuation.resume(Rlt.Success(Any()))
                    }
                }
            })
        }
    }

    override fun release(clientId: String, vararg hardwareList: Hardware) {
        for (hardware in hardwareList) {
            HardwareConflictDetector.releaseResource(hardware, clientId)
        }
    }

    override fun releaseAll(clientId: String) {
        HardwareConflictDetector.releaseAllResource(clientId)
    }
}