package com.adealink.weparty.room.applymic.viewmodel

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.adealink.frame.base.CommonDataNullError
import com.adealink.frame.base.Rlt
import com.adealink.frame.base.fastLazy
import com.adealink.frame.mvvm.livedata.ExtMutableLiveData
import com.adealink.frame.mvvm.livedata.OnceMutableLiveData
import com.adealink.frame.mvvm.viewmodel.BaseViewModel
import com.adealink.frame.network.data.PageReq
import com.adealink.weparty.App
import com.adealink.weparty.commonui.ext.isSuccess
import com.adealink.weparty.module.profile.ProfileModule
import com.adealink.weparty.room.applymic.ApplyMicStore
import com.adealink.weparty.room.applymic.data.APPLY_MIC_LIST_TYPE_ALL
import com.adealink.weparty.room.applymic.data.ApplyMicItemData
import com.adealink.weparty.room.data.APPLY_MIC_ONLY_HOST_ERROR
import com.adealink.weparty.room.data.AcceptApplyMicReq
import com.adealink.weparty.room.data.ApplyMicListReq
import com.adealink.weparty.room.data.ApplyMicOnlyHostError
import com.adealink.weparty.room.data.ApplyMicReq
import com.adealink.weparty.room.data.CancelApplyMicReq
import com.adealink.weparty.room.data.ClearApplyMicListReq
import com.adealink.weparty.room.datasource.remote.RoomHttpService
import com.adealink.weparty.room.sdk.service.roomService
import com.adealink.weparty.util.PageHandler
import kotlinx.coroutines.launch

class ApplyMicViewModel : BaseViewModel() {

    private val roomHttpService by fastLazy {
        App.instance.networkService.getHttpService(RoomHttpService::class.java)
    }

    private var total = 0L
    val totalLD = ExtMutableLiveData<Long>()
    private val applyList = mutableListOf<ApplyMicItemData>()
    private val applyIds = mutableSetOf<String>()
    private val pageHandler = PageHandler()

    val applyListRltLD = ExtMutableLiveData<Rlt<Any>>()
    val applyListLD = MutableLiveData<List<ApplyMicItemData>>()

    private var roomId: String? = null
    private var searchType: Int = APPLY_MIC_LIST_TYPE_ALL
    private var skillCategories: List<String>? = null

    fun pullList(roomId: String, searchType: Int, skillCategories: List<String>?) {
        this.roomId = roomId
        this.searchType = searchType
        this.skillCategories = skillCategories

        applyList.clear()
        applyIds.clear()
        pageHandler.reset()
        total = 0
        loadMoreList()
    }

    fun refreshList() {
        applyList.clear()
        applyIds.clear()
        pageHandler.reset()
        loadMoreList()
    }

    private fun resetApplyList() {
        applyList.clear()
        applyIds.clear()
        pageHandler.reset()
    }

    fun hasMoreData(): Boolean {
        return !pageHandler.isEnd
    }

    fun loadMoreList() {
        viewModelScope.launch {
            val roomId = this@ApplyMicViewModel.roomId
            if (roomId.isNullOrEmpty()) {
                applyListRltLD.send(Rlt.Failed(CommonDataNullError()))
                return@launch
            }
            val rlt = roomHttpService.applyMicList(
                ApplyMicListReq(
                    roomId = roomId,
                    searchType = searchType,
                    skillCategories = skillCategories,
                    page = PageReq(size = pageHandler.pageSize, next = pageHandler.currentPage)
                )
            )
            when (rlt) {
                is Rlt.Failed -> {
                    applyListRltLD.send(rlt)
                }

                is Rlt.Success -> {
                    pageHandler.nextPage(rlt.data.data?.next)
                    rlt.data.data?.total?.let {
                        total = it
                        totalLD.send(it)
                    }

                    rlt.data.data?.list?.forEach {
                        if (!applyIds.contains(it.applyId)) {
                            applyList.add(ApplyMicItemData(it))
                            applyIds.add(it.applyId)
                        }
                    }
                    applyListRltLD.send(rlt)
                    applyListLD.send(applyList)
                }
            }
        }
    }

    fun notifyApplyAccepted(item: ApplyMicItemData, position: Int) {
        viewModelScope.launch {
            applyList.removeAt(position)
            applyListLD.send(applyList)
        }
    }

    fun notifyApplyCanceled() {
        viewModelScope.launch {
            val myUid = ProfileModule.getMyUid()
            applyList.indexOfFirst { it.data.user.uid == myUid }.let { index ->
                if (index >= 0) {
                    applyList.removeAt(index)
                }
                applyListLD.send(applyList)
            }
        }
    }

    fun notifyClearAllApply() {
        viewModelScope.launch {
            resetApplyList()
            applyListLD.send(applyList)
        }
    }


    /**
     * 申请操作
     */

    fun applyMic(micIndex: Int): LiveData<Rlt<Any>> {
        val liveData = OnceMutableLiveData<Rlt<Any>>()
        viewModelScope.launch {
            val roomId = roomService.joinController.getJoinedRoomId()
            if (roomId.isNullOrEmpty()) {
                liveData.send(Rlt.Failed(CommonDataNullError()))
                return@launch
            }
            val rlt = roomHttpService.applyMic(
                ApplyMicReq(
                    roomId, micIndex
                )
            )
            when (rlt) {
                is Rlt.Failed -> {
                    if (rlt.error.serverCode == APPLY_MIC_ONLY_HOST_ERROR) {
                        //申请主持人麦位，需要主持人或房主权限
                        liveData.send(Rlt.Failed(ApplyMicOnlyHostError()))
                    } else {
                        liveData.send(rlt)
                    }
                }

                is Rlt.Success -> {
                    ApplyMicStore.addApplyRecord(roomId, micIndex)
                    liveData.send(rlt)
                }
            }
        }
        return liveData
    }

    fun cancelApply(): LiveData<Rlt<Any>> {
        val liveData = OnceMutableLiveData<Rlt<Any>>()
        viewModelScope.launch {
            val roomId = roomService.joinController.getJoinedRoomId()
            if (roomId.isNullOrEmpty()) {
                liveData.send(Rlt.Failed(CommonDataNullError()))
                return@launch
            }
            val rlt = roomHttpService.cancelApplyMic(
                CancelApplyMicReq(roomId)
            )
            if (rlt.isSuccess) {
                ApplyMicStore.removeRecord(roomId)
            }
            liveData.send(rlt)
        }
        return liveData
    }

    fun acceptApply(roomId: String, applyId: String, accept: Boolean): LiveData<Rlt<Any>> {
        val liveData = OnceMutableLiveData<Rlt<Any>>()
        viewModelScope.launch {
            val rlt = roomHttpService.acceptApplyMic(
                AcceptApplyMicReq(
                    roomId,
                    applyId,
                    accept
                )
            )
            liveData.send(rlt)
        }
        return liveData
    }


    fun clearAllApply(roomId: String, searchType: Int): LiveData<Rlt<Any>> {
        val liveData = OnceMutableLiveData<Rlt<Any>>()
        viewModelScope.launch {
            val rlt = roomHttpService.clearApplyMicList(
                ClearApplyMicListReq(
                    roomId,
                    searchType
                )
            )
            liveData.send(rlt)
        }
        return liveData
    }

}