package com.adealink.weparty.hardware

import android.os.Handler
import android.os.Looper
import com.adealink.frame.log.Log
import com.adealink.weparty.hardware.data.TAG_HARDWARE
import com.adealink.weparty.hardware.resource.CameraResource
import com.adealink.weparty.hardware.resource.HardwareResource
import com.adealink.weparty.hardware.resource.MicResource
import java.util.PriorityQueue
import java.util.concurrent.ConcurrentHashMap

object HardwareConflictDetector {
    private val resources: MutableMap<Hardware, HardwareResource> = ConcurrentHashMap()
    private val pendingRequests: MutableMap<Hardware, PriorityQueue<ResourceRequest>> = ConcurrentHashMap()
    private val stateListeners: MutableMap<Hardware, MutableSet<ResourceStateListener>> = ConcurrentHashMap()
    private val mainHandler = Handler(Looper.getMainLooper())

    init {
        // 初始化系统硬件资源
        registerSystemResources()
    }

    private fun registerSystemResources() {
        // 摄像头资源
        registerResource(CameraResource())
        // 音频资源
        registerResource(MicResource())
    }

    fun registerResource(resource: HardwareResource) {
        resources[resource.hardware] = resource
        pendingRequests[resource.hardware] = PriorityQueue(11, ResourceRequestComparator())
    }

    fun getHardwareResource(hardware: Hardware): HardwareResource? {
        return resources[hardware]
    }

    fun requestResource(
        hardware: Hardware,
        client: HardwareClient,
        priority: HardwarePriority,
        callback: HardwareRequestCallback?
    ): Boolean {
        val resource = resources[hardware]
        if (resource == null) {
            Log.d(TAG_HARDWARE, "requestResource, client:${client.clientId}, hardware:$hardware, fail for REASON_HARDWARE_NOT_EXIST")
            callback?.onDenied(HardwareRequestCallback.REASON_HARDWARE_NOT_EXIST)
            return false
        }

        // 检查权限
        if (!checkClientPermission(resource, client.clientId)) {
            Log.d(TAG_HARDWARE, "requestResource, client:${client.clientId}, hardware:$hardware, fail for REASON_PERMISSION_DENIED")
            callback?.onDenied(HardwareRequestCallback.REASON_PERMISSION_DENIED)
            return false
        }

        synchronized(resource) {
            if (resource.isAvailable ||
                (!resource.isExclusive && resource.currentClient?.clientId === client.clientId)
            ) {
                if (resource.acquire(client)) {
                    Log.d(TAG_HARDWARE, "requestResource, client:${client.clientId}, hardware:$hardware")
                    notifyResourceGranted(hardware, client, callback)
                    return true
                }
            }
            // 添加到等待队列
            val request = ResourceRequest(
                hardware, client, priority, callback
            )
            val requests = pendingRequests.getOrPut(hardware) { PriorityQueue<ResourceRequest>() }
            requests.add(request)

            // 检查是否可以抢占(抢占逻辑比较复杂)
            if (resource.isExclusive && priority > resource.currentClientPriority) {
                attemptPreemption(hardware)
            }

            notifyResourceDenied(hardware, client, callback, HardwareRequestCallback.REASON_HARDWARE_BUSY)
            return false
        }
    }

    fun releaseResource(hardware: Hardware, clientId: String?) {
        if (clientId.isNullOrEmpty()) {
            return
        }
        val resource = resources[hardware] ?: return
        synchronized(resource) {
            if (resource.release(clientId)) {
                Log.d(TAG_HARDWARE, "releaseResource, clientId:$clientId, hardware:$hardware")
                processPendingRequests(hardware)
            }
        }
    }

    fun releaseAllResource(clientId: String?) {
        if (clientId.isNullOrEmpty()) {
            return
        }
        for (resourceEntry in resources) {
            val hardware = resourceEntry.key
            val resource = resourceEntry.value
            synchronized(resource) {
                if (resource.release(clientId)) {
                    Log.d(TAG_HARDWARE, "releaseResource, clientId:$clientId, hardware:$hardware")
                    processPendingRequests(hardware)
                }
            }
        }
    }

    fun addResourceStateListener(hardware: Hardware, listener: ResourceStateListener) {
        val listeners = stateListeners.getOrPut(hardware) { mutableSetOf() }
        listeners.add(listener)
    }

    fun removeResourceStateListener(hardware: Hardware, listener: ResourceStateListener) {
        val listeners = stateListeners[hardware]
        listeners?.remove(listener)
    }

    private fun processPendingRequests(hardware: Hardware) {
        val queue = pendingRequests[hardware] ?: return

        val resource = resources[hardware] ?: return

        synchronized(resource) {
            while (!queue.isEmpty() && resource.isAvailable) {
                val request = queue.poll() ?: continue
                if (resource.acquire(request.client)) {
                    notifyResourceGranted(
                        hardware,
                        request.client,
                        request.callback
                    )
                }
            }
            if (resource.isAvailable) {
                notifyResourceAvailable(hardware)
            }
        }
    }

    private fun attemptPreemption(hardware: Hardware) {
        val resource = resources[hardware]
        if (resource == null || !resource.isExclusive) return

        val currentClient = resource.currentClient ?: return
        val topRequest = pendingRequests[hardware]?.peek() ?: return

        if (topRequest.priority > resource.currentClientPriority.priority) {
            // 找到当前占用资源的回调并通知抢占
            notifyResourcePreempted(hardware, currentClient, topRequest.callback)
        }
    }

    private fun notifyResourceGranted(
        hardware: Hardware, client: HardwareClient, callback: HardwareRequestCallback?
    ) {
        callback?.let {
            mainHandler.post {
                callback.onGranted()
            }
        }
        notifyResourceUnavailable(hardware)
    }

    private fun notifyResourceDenied(
        hardware: Hardware, client: HardwareClient, callback: HardwareRequestCallback?, reason: Int
    ) {
        callback ?: return
        mainHandler.post { callback.onDenied(reason) }
    }

    private fun notifyResourcePreempted(hardware: Hardware, client: HardwareClient, callback: HardwareRequestCallback?) {
        callback ?: return
        // 实际应用中需要通过clientId找到对应的callback
        mainHandler.post { callback.onPreempted() }
    }

    private fun notifyResourceAvailable(hardware: Hardware) {
        val listeners: Set<ResourceStateListener>? = stateListeners[hardware]
        if (listeners != null) {
            mainHandler.post {
                for (listener in listeners) {
                    listener.onResourceAvailable(hardware)
                }
            }
        }
    }

    private fun notifyResourceUnavailable(hardware: Hardware) {
        val listeners: Set<ResourceStateListener>? = stateListeners[hardware]
        if (listeners != null) {
            mainHandler.post {
                for (listener in listeners) {
                    listener.onResourceUnavailable(hardware)
                }
            }
        }
    }

    private fun checkClientPermission(resource: HardwareResource, clientId: String): Boolean {
        // 实际实现中检查应用权限
        return resource.checkClientPermission(clientId)
    }

    private class ResourceRequestComparator

        : Comparator<ResourceRequest> {
        override fun compare(r1: ResourceRequest, r2: ResourceRequest): Int {
            // 先按优先级降序，再按等待时间升序
            if (r1.priority != r2.priority) {
                return Integer.compare(r2.priority, r1.priority)
            }
            return java.lang.Long.compare(r1.waitDuration, r2.waitDuration)
        }
    }
}