package com.swago.room.user

import android.content.Intent
import android.view.View
import android.view.ViewGroup
import android.view.ViewStub
import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.Toast
import androidx.activity.viewModels
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.lifecycle.lifecycleScope
import androidx.viewpager.widget.ViewPager
import com.alibaba.android.arouter.facade.annotation.Autowired
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.gyf.immersionbar.ImmersionBar
import com.swago.baseswago.SwagoAdapter
import com.swago.baseswago.UserVm
import com.swago.baseswago.agora.AgoraManager
import com.swago.baseswago.agora.ISwagoIRtcEngineEventHandler
import com.swago.baseswago.baseroom.IRoomInfo
import com.swago.baseswago.baseroom.RoleType
import com.swago.baseswago.baseroom.SwagoRoomManager
import com.swago.baseswago.baseroom.ui.AbsUserActivity
import com.swago.baseswago.constant.ARouteConstant
import com.swago.baseswago.databinding.ActivityAbsRoomUserBinding
import com.swago.baseswago.dialog.ChoiceDialogFragment
import com.swago.baseswago.model.MomentModel
import com.swago.baseswago.model.live.audio.AudioSeatModel
import com.swago.baseswago.model.live.audio.IMAudioModel
import com.swago.baseswago.model.live.mic.LianMaiIMModel
import com.swago.baseswago.model.live.pk.ProcessPKModel
import com.swago.baseswago.model.live.pk.PunishPKModel
import com.swago.baseswago.model.live.pk.StartPKModel
import com.swago.baseswago.model.live.pk.StopPKModel
import com.swago.baseswago.util.*
import com.swago.room.R
import com.swago.room.audio.AudioRoomManager
import com.swago.room.audio.IAudioRoomListener
import com.swago.room.base.NoContentFragment
import com.swago.room.bean.UserRoomModel
import com.swago.room.data.RoomDataManager
import com.swago.room.enum.RoomType
import com.swago.room.lianmai.ILianMaiListener
import com.swago.room.lianmai.LianMaiManager
import com.swago.room.lianmai.LianMaiView
import com.swago.room.lianmai.LianMaiVm
import com.swago.room.pk.IPKListener
import com.swago.room.pk.PKStateManager
import com.swago.room.pk.PkVm
import com.swago.room.vm.MsgVm
import com.swago.room.vm.RoomOtherVm
import com.swago.room.vm.RoomVm
import com.swago.room.widget.ChoiceViewPager
import com.swago.room.widget.UserShowAnchorCloseView
import io.agora.rtc.IRtcEngineEventHandler
import jp.wasabeef.glide.transformations.BlurTransformation
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.concurrent.CopyOnWriteArrayList

/**
 *@date 2021/10/11 14:12
 *description:
 */
@Route(path = ARouteConstant.Room.user)
class UserRoomActivity : AbsUserActivity<ActivityAbsRoomUserBinding, UserRoomModel>(),
    ISwagoIRtcEngineEventHandler,IPKListener,ILianMaiListener, IAudioRoomListener {

    private val roomVm by viewModels<RoomVm>()
    private val msgVm by viewModels<MsgVm>()
    private val userVm by viewModels<UserVm>()
    private val roomOtherVm by viewModels<RoomOtherVm>()
    private val pkVm by viewModels<PkVm>()
    private val lianMaiVm by viewModels<LianMaiVm>()

    private val fragments by lazy{
        listOf(NoContentFragment(), UserRoomFragment())
    }

    @Autowired
    @JvmField
    var position: Int = 0

    @Autowired
    @JvmField
    var data: ArrayList<MomentModel>? = null

    private var userRoomFragment: UserRoomFragment? = null

    private var ivClose: ImageView? = null
    private var ivCover: ImageView? = null
    private var ivAudioBg: ImageView? = null
    private var userShowAnchorCloseView: UserShowAnchorCloseView? = null
    private var flRoot: FrameLayout? = null
    private var peerFl: FrameLayout? = null
    private var lianMaiView: LianMaiView? = null
    private var choiceViewPager:ChoiceViewPager? = null

    override val roomCoverView: ViewGroup by lazy {
        val userRoomView = layoutInflater.inflate(R.layout.layout_user_room, null) as ViewGroup
        choiceViewPager = userRoomView.findViewById<ChoiceViewPager>(R.id.viewPager)
        lianMaiView = userRoomView.findViewById(R.id.lianMaiView)
        ivClose = userRoomView.findViewById(R.id.ivClose)
        ivAudioBg = userRoomView.findViewById(R.id.ivAudioBg)
        userShowAnchorCloseView = userRoomView.findViewById(R.id.userShowAnchorCloseView)
//        ivCover = userRoomView.findViewById(R.id.ivCover)
        flRoot = userRoomView.findViewById(R.id.flRoot)
        peerFl = userRoomView.findViewById(R.id.peerFl)
        choiceViewPager?.adapter = SwagoAdapter(fragments, supportFragmentManager)
        choiceViewPager?.currentItem = 1
        userRoomView
    }


    override var mCurrentPosition: Int = position
    override var iRoomInfos: CopyOnWriteArrayList<UserRoomModel> = RoomDataManager.data

    override fun initUserRoomView() {
        ARouter.getInstance().inject(this)
        PKStateManager.resetData()
        PKStateManager.addPKListener(this)
        LianMaiManager.addLianMaiListener(this)
        AudioRoomManager.addListener(this)
        AgoraManager.initializeEngine(this, this)
        mCurrentPosition = position
        RoomDataManager.initData(data)
        userRoomFragment = fragments[1] as UserRoomFragment

        roomVm.init()
        msgVm.init()
        pkVm.init()
        lianMaiVm.init()
        initPeerAnchorLayoutParams()
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

        AgoraManager.setVideoConfiguration()
        AgoraManager.setVideoAudio(
            pullVideo = true,
            pullAudio = true,
            pushVideo = false,
            pushAudio = false
        )
        AgoraManager.enableAudioVolumeIndication()

        ivClose?.setOnClickListener(object : NoDoubleClickListener() {
            override fun onClick() {
                if (SwagoRoomManager.iRoomInfo == null){
                    SwagoRoomManager.closeRoom()
                }else{
                    SwagoRoomManager.iRoomInfo?.let { iRoomInfo ->
                        if (iRoomInfo.getRoomType() == RoomType.VIDEO.type){
                            if (LianMaiManager.lianMaiState == 1){
                                ChoiceDialogFragment.newInstance(AppContext.getContext().resources.getString(R.string.lian_mai_ing_sure_close),AppContext.getContext().resources.getString(
                                    R.string.tips)).apply {
                                    this.sureFun = {
                                        lianMaiVm.closeLianMai(){
                                            lianMaiView?.closeLianMai(false)
                                            SwagoRoomManager.closeRoom()
                                        }
                                    }
                                }.show(supportFragmentManager,"ChoiceDialogFragment")
                            }else if(LianMaiManager.lianMaiState == 3 || LianMaiManager.lianMaiState == 4){
                                lianMaiVm.cancelApplyLianMai(LianMaiManager.lianMaiId){
                                    SwagoRoomManager.closeRoom()
                                }
                            }else{
                                SwagoRoomManager.closeRoom()
                            }
                        }else if (iRoomInfo.getRoomType() == RoomType.AUDIO.type){
                            if (AudioRoomManager.isOnMic){
                                UserInfo.getUserInfo()?.let { userInfoModel ->
                                    roomVm.downMicByAnchor(AudioRoomManager.maiIndex,userInfoModel.id){
                                        SwagoRoomManager.closeRoom()
                                    }
                                }

                            }else{
                                SwagoRoomManager.closeRoom()
                            }
                        }else {
                            SwagoRoomManager.closeRoom()
                        }
                    }
                }

            }
        })

        lianMaiView?.openCloseLianMaiDialogFun = {
            ChoiceDialogFragment.newInstance(AppContext.getContext().resources.getString(R.string.close_mic_content),AppContext.getContext().resources.getString(
                R.string.end_lian_mai)).apply {
                this.sureFun = {
                    lianMaiVm.closeLianMai(){
                        lianMaiView?.closeLianMai(false)
                    }
                }
            }.show(supportFragmentManager,"ChoiceDialogFragment")
        }
    }

    override fun initLiveData() {
        msgVm.anchorRoomClosed = {
            userShowAnchorCloseView?.visibility = View.VISIBLE
            it?.let { userShowAnchorCloseView?.setData(it) }
            SwagoRoomManager.receiveStopLive()
        }

        msgVm.kickFromRoom = {
            Toast.makeText(
                AppContext.getContext(),
                AppContext.getContext().resources.getString(R.string.be_kick_out),
                Toast.LENGTH_SHORT
            ).show()
            SwagoRoomManager.closeRoom()
        }

        roomVm.roomClosedLiveData.observe(this) {
            userShowAnchorCloseView?.visibility = View.VISIBLE
            it?.let { userShowAnchorCloseView?.setData(it) }
        }

        roomVm.momentModelLiveData.observe(this) {
            val userRoomModel = UserRoomModel()
            userRoomModel.momentModel = it
            iRoomInfos.add(userRoomModel)
            scrollToPosition(iRoomInfos.lastIndex)
        }

        lianMaiVm.anchorRefuseUserLianMai = {
            setRvState(true)
        }
    }

    override fun changeRoom(iRoomInfo: IRoomInfo) {
        isRobot = iRoomInfo.getIsRobot()
        ivCover?.let {
            Glide.with(this)
                .load(iRoomInfo.getRoomCover())
                .dontAnimate()
                .apply(RequestOptions.bitmapTransform(BlurTransformation(5, 100)))
                .into(it)
        }
        ivCover?.visibility = View.VISIBLE
        userShowAnchorCloseView?.visibility = View.INVISIBLE

        when(iRoomInfo.getRoomType()){
            RoomType.VIDEO.type -> {
                choiceViewPager?.setCanScroll(true)
                AgoraManager.setVideoAudio(
                    pullVideo = true,
                    pullAudio = true,
                    pushVideo = false,
                    pushAudio = false
                )
            }

            RoomType.AUDIO.type -> {
                choiceViewPager?.setCanScroll(false)
                AgoraManager.setVideoAudio(
                    pullVideo = false,
                    pullAudio = true,
                    pushVideo = false,
                    pushAudio = false
                )
            }

            RoomType.NULL.type -> {}
        }
    }

    override fun leaveRoom(iRoomInfo: IRoomInfo) {
        setPKLayoutParams(flRoot,false)
        if (PKStateManager.roomState == PKStateManager.LIVING) {
            AgoraManager.changeRoom(iRoomInfo.getAnchorId().toInt(), flRoot)
        } else {
            AgoraManager.changeRoom(iRoomInfo.getAnchorId().toInt(), flRoot)
            AgoraManager.changeRoom(peerAnchorId, peerFl)
        }
        PKStateManager.resetData()
        LianMaiManager.clearData()
        AudioRoomManager.resetData()
    }

    override fun joinedRoom(iRoomInfo: IRoomInfo) {
        if (iRoomInfo.getIsRobot()) {
            ivCover?.visibility = View.GONE
        }else{
            pkVm.getPKInfo(iRoomInfo.getRoomId())
            lianMaiVm.getRoomLianMaiInfo()
        }
        when (iRoomInfo.getRoomType()){
            RoomType.VIDEO.type -> {
                ivAudioBg?.visibility = View.GONE
                UserInfo.getUserInfo()?.let { userInfoModel ->
                    lifecycleScope.launch(Dispatchers.Main) {
                        AgoraManager.joinChannel(
                            iRoomInfo.getChannelName(),
                            userInfoModel.id.toInt(),
                            iRoomInfo.getAgoraToken()
                        )
                        if (!isRobot) {
                            flRoot?.let {
                                //这里加个延迟是因为第一次进入直播间的时候布局未完全加载成功导致部分布局无法显示
                                delay(600)
                                AgoraManager.setupRemoteVideo(
                                    this@UserRoomActivity,
                                    iRoomInfo.getAnchorId().toInt(), it
                                )
                            }
                        }
                    }
                }
            }
            RoomType.AUDIO.type -> {
                ivAudioBg?.visibility = View.VISIBLE
                UserInfo.getUserInfo()?.let { userInfoModel ->
                    lifecycleScope.launch(Dispatchers.Main) {
                        AgoraManager.joinChannel(
                            iRoomInfo.getChannelName(),
                            userInfoModel.id.toInt(),
                            iRoomInfo.getAgoraToken()
                        )
                    }
                }
            }
            RoomType.NULL.type -> {}
        }
    }

    override fun receiveStopLive() {
        AudioRoomManager.resetData()
        SwagoRoomManager.iRoomInfo?.let {
            if (it.getRoomType() == RoomType.AUDIO.type){
                AgoraManager.setVideoAudio(
                    pullVideo = false,
                    pullAudio = false,
                    pushVideo = false,
                    pushAudio = false
                )
            }
        }
    }

    override fun endRoom(iRoomInfo: IRoomInfo?) {
    }

    override fun closeRoomed() {
        LianMaiManager.clearData()
        AudioRoomManager.resetData()
        AgoraManager.closedRoom()
    }

    override fun onBackPressed() {
        SwagoRoomManager.closeRoom()
    }

    override fun onDestroy() {
        AudioRoomManager.removeListener(this)
        LianMaiManager.removeLianMaiListener(this)
        PKStateManager.removePKListener(this)
        super.onDestroy()
    }

    private var isRobot = false
    override fun onFirstRemoteVideoDecoded(uid: Int, width: Int, height: Int, elapsed: Int) {
        if (!isRobot) {
            ivCover?.visibility = View.GONE
        }
    }

    override fun onConnectionStateChanged(state: Int, reason: Int) {
        LogUtil.d("网络变更", "$state----$reason")
    }

    override fun onChannelMediaRelayStateChanged(state: Int, code: Int) {}
    override fun onFirstLocalAudioFramePublished(elapsed: Int) {
        SwagoRoomManager.iRoomInfo?.let {
            if (it.getRoomType() == RoomType.VIDEO.type){
                lianMaiVm.lianMaiCallback()
            }
        }

    }

    override fun onError(err: Int) {

    }

    override fun onAudioVolumeIndication(
        speakers: Array<out IRtcEngineEventHandler.AudioVolumeInfo>?,
        totalVolume: Int
    ) {
        lifecycleScope.launch(Dispatchers.Main) {
            SwagoRoomManager.iRoomInfo?.let {
                if (it.getRoomType() == RoomType.AUDIO.type) {
                    AudioRoomManager.dispatchOnAudioVolumeIndication(speakers)
                }
            }
        }
    }

    fun gotoTargetRoom(anchorId: String) {
        iRoomInfos.forEachIndexed { index, userRoomModel ->
            if (userRoomModel?.momentModel != null) {
                if (userRoomModel.momentModel!!.id == anchorId) {
                    scrollToPosition(index)
                    return
                }
            }
        }
        roomVm.getMomentModel(anchorId)
    }

    private var peerAnchorId = 0
    override fun startPK(startPKModel: StartPKModel, isGetDataFromIM: Boolean) {
        lifecycleScope.launch(Dispatchers.Main){
            peerAnchorId = startPKModel.oppositeUserId.toInt()
            setPKLayoutParams(flRoot,true)
            peerFl?.let { AgoraManager.setupRemoteVideo(this@UserRoomActivity,peerAnchorId, it) }

        }
    }

    override fun stopPK(stopPKModel: StopPKModel) {
        setPKLayoutParams(flRoot,false)
        AgoraManager.removeRemoteVideo(peerAnchorId,peerFl)
    }

    override fun punishPK(punishPKModel: PunishPKModel, isGetDataFromIM: Boolean) {
        if (!isGetDataFromIM){
            //如果是通过接口获取的
            peerAnchorId = punishPKModel.oppositeUserId.toInt()
            setPKLayoutParams(flRoot,true)
            peerFl?.let { AgoraManager.setupRemoteVideo(this@UserRoomActivity,peerAnchorId, it) }
        }
    }

    override fun processChangePK(processPKModel: ProcessPKModel,isGetDataFromIM: Boolean) {

    }

    private val marginTopValue by lazy {
        ImmersionBar.getStatusBarHeight(this) + DpPxUtil.dip2px(78f)
    }

    //设置视频画面大小
    private fun setPKLayoutParams(view:View?,isPK:Boolean){
        if (isPK){
            val x = DpPxUtil.getScreenWidth() / 2
            val y = DpPxUtil.getScreenWidth() * 275 / 360
            val params = ConstraintLayout.LayoutParams(x, y)
            params.topToTop = R.id.rootUserView
            params.startToStart = R.id.rootUserView
            params.width = x
            params.height = y
            params.topMargin = marginTopValue
            view?.layoutParams = params
        }else{
            val params = ConstraintLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
            )
            view?.layoutParams = params
        }
    }

    private fun initPeerAnchorLayoutParams() {
        val x = DpPxUtil.getScreenWidth() / 2
        val y = DpPxUtil.getScreenWidth() * 275 / 360
        val params = ConstraintLayout.LayoutParams(x, y)
        params.topToTop = R.id.rootUserView
        params.endToEnd = R.id.rootUserView
        params.width = x
        params.height = y
        params.topMargin = marginTopValue
        peerFl?.layoutParams = params
    }

    override fun startLianMai(lianMaiIMModel: LianMaiIMModel) {
        UserInfo.getUserInfo()?.let {
            if (lianMaiIMModel.senderId == it.id){
                setRvState(false)
            }
        }
    }

    override fun stopLianMai(lianMaiIMModel: LianMaiIMModel) {
        UserInfo.getUserInfo()?.let {
            if (lianMaiIMModel.senderId == it.id){
                setRvState(true)
            }
        }
    }

    override fun lockOrUnlockSeat(imAudioModel: IMAudioModel) {
    }

    override fun openSeatMic() {
        AgoraManager.setMute(false)
    }

    override fun muteSeatMic() {
        AgoraManager.setMute(true)
    }

    override fun onSeatMic() {
        AgoraManager.setVideoAudio(pullVideo = false, pullAudio = true, pushVideo = false, pushAudio = true)
        setCanVerticalScroll(false)
    }

    override fun downSeatMic() {
        AgoraManager.setVideoAudio(pullVideo = false, pullAudio = true, pushVideo = false, pushAudio = false)
        setCanVerticalScroll(true)
    }

    override fun updateData(audioSeatModel: AudioSeatModel) {

    }

    override fun changeJiFen(imAudioModel: IMAudioModel) {
    }

    override fun clearJiFen() {

    }

}