package com.adealink.weparty.room.micseat

import androidx.annotation.CallSuper
import androidx.annotation.LayoutRes
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import com.adealink.frame.base.Rlt
import com.adealink.frame.ext.isViewBindingValid
import com.adealink.frame.log.Log
import com.adealink.frame.room.data.TAG_ROOM_SEAT
import com.adealink.frame.util.onClick
import com.adealink.weparty.commonui.BaseFragment
import com.adealink.weparty.module.profile.data.UserInfo
import com.adealink.weparty.module.room.data.MIC_OFF
import com.adealink.weparty.module.room.data.MicIndex
import com.adealink.weparty.module.room.listener.IMemberInfoListener
import com.adealink.weparty.room.constant.logRoomTime
import com.adealink.weparty.room.member.viewmodel.RoomMemberViewModel
import com.adealink.weparty.room.micseat.defaults.BaseDefaultSeatView
import com.adealink.weparty.room.sdk.service.roomService
import com.adealink.weparty.room.viewmodel.RoomViewModelFactory
import io.trtc.tuikit.atomicxcore.api.live.SeatInfo
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

/**
 * 麦位模板要解决的问题？
 * 1.方便对麦位玩法拓展
 * 2.管理多麦位，实现对多麦位的数据分发
 * 3.方便麦位装饰的添加和拓展，完成麦位装饰的层级管理
 */
abstract class BaseSeatsTemplate<SV : BaseDefaultSeatView, VM : BaseSeatsTemplateViewModel> :
    BaseFragment,
    IMemberInfoListener {

    constructor() : super()

    constructor(@LayoutRes contentLayoutId: Int) : super(contentLayoutId)

    private val micSeatViews = hashMapOf<Int, SV>() //key: 麦序
    abstract val viewModel: VM
    val memberViewModel by viewModels<RoomMemberViewModel> { RoomViewModelFactory() }


    fun getSeatView(index: Int): SV? {
        return micSeatViews[index]
    }

    fun getSeatView(index: MicIndex): SV? {
        if (index.index == MIC_OFF) {
            return null
        }

        return getSeatView(index.index)
    }

    fun updateSeatViews(action: (SV) -> Unit) {
        micSeatViews.forEach {
            action(it.value)
        }
    }

    open fun setSeatView(index: MicIndex, seatView: SV) {
        seatView.micIndex = index
        seatView.memberInfoListener = this
        micSeatViews[index.index] = seatView
    }

    fun getSeatViewByUid(uid: String): SV? {
        val micIndex = roomService.seatController.getMicSeatIndex(uid) ?: return null
        return getSeatView(micIndex)
    }

    override fun initViews() {
        bindSeatViews()
        initSeatEvents()
    }

    abstract fun bindSeatViews()

    @CallSuper
    open fun initSeatEvents() {
        micSeatViews.forEach { entry ->
            entry.value.let { sv ->
                sv.onClick {
                    onSeatClick(sv)
                }
            }
        }
    }

    open fun onSeatClick(seatView: SV) {

    }


    @CallSuper
    override fun observeViewModel() {
        //不要转成lambda, 注意kotlin SAM 优化，不注意就会踩坑！(https://www.jianshu.com/p/acba3986c4a2)
        roomService.seatController.micSeatsFlow.onEach {
            logRoomTime("BaseSeatsTemplate, micSeatsChange")
            //上麦列表
            val onMicMap = mutableMapOf<Int, SeatInfo>()
            val offMicList = mutableListOf<Int>()
            micSeatViews.onEach { seatViewEntry ->
                val micIndex = seatViewEntry.key
                val seatView = seatViewEntry.value
                val micSeatInfo = it[micIndex] ?: SeatInfo(micIndex, false)
//                        if (micIndex == MicIndex.SUPER_MIC.index) {
//                            openSuperMic(it.containsKey(micIndex), micSeatInfo?.isMicDeluxeOpen() ?: false)
//                        }
                seatView.handleMicSeatInfo(
                    micSeatInfo,
                    { onMicInfo ->
                        //有人上麦
                        onMicMap[micIndex] = onMicInfo
                    },
                    {
                        //下麦
                        offMicList.add(micIndex)
                    }
                )
            }

            if (onMicMap.isNotEmpty()) {
                onUserOnMic(onMicMap)
            }
            if (offMicList.isNotEmpty()) {
                onUserOffMic(offMicList)
            }
        }.launchIn(lifecycleScope)

        roomService.seatController.speakingUsersFlow.onEach { speakingMap ->
            micSeatViews.onEach { seatViewEntry ->
                val uid = seatViewEntry.value.micSeatInfo?.userInfo?.userID ?: return@onEach
                seatViewEntry.value.showSpeaking(speakingMap[uid] ?: false)
            }
        }.launchIn(lifecycleScope)
    }

    @CallSuper
    override fun loadData() {
        viewModel.getMicSeatsInfo()
    }

    open fun resetAllMicSeatViews() {
        micSeatViews.onEach {
            it.value.resetMicSeat()
        }
    }

    /**
     * 通知有人上麦
     */
    open fun onUserOnMic(onMicMap: Map<Int, SeatInfo>) {
        Log.d(TAG_ROOM_SEAT, "onUserOnMic, ${onMicMap.keys}")
    }

    /**
     * 通知有人下麦
     */
    open fun onUserOffMic(offMicIndexList: List<Int>) {
        Log.d(TAG_ROOM_SEAT, "onUserOffMic, $offMicIndexList")
    }

    override fun getMemberInfo(
        uid: String,
        callback: (UserInfo?) -> Unit
    ) {
        if (!isViewBindingValid()) {
            callback.invoke(null)
            return
        }
        memberViewModel.getRoomMemberInfo(uid).observe(viewLifecycleOwner) {
            callback(if (it is Rlt.Success) it.data else null)
        }
    }

    override fun getMembersInfo(
        uidSet: Set<String>,
        callback: (Map<String, UserInfo>) -> Unit
    ) {
        if (!isViewBindingValid()) {
            callback.invoke(emptyMap())
            return
        }
        memberViewModel.getRoomMembersInfo(uidSet).observe(viewLifecycleOwner) {
            if (it is Rlt.Success) {
                callback(it.data)
            }
        }
    }


}