package com.swago.room.base

import android.graphics.Rect
import android.text.TextUtils
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gyf.immersionbar.ImmersionBar
import com.liulishuo.okdownload.DownloadListener
import com.liulishuo.okdownload.DownloadTask
import com.liulishuo.okdownload.core.breakpoint.BreakpointInfo
import com.liulishuo.okdownload.core.cause.EndCause
import com.liulishuo.okdownload.core.cause.ResumeFailedCause
import com.swago.baseswago.PersonDataDFragment
import com.swago.baseswago.UserVm
import com.swago.baseswago.baseroom.IRoomActiveListener
import com.swago.baseswago.baseroom.IRoomInfo
import com.swago.baseswago.baseroom.RoomTimer
import com.swago.baseswago.baseroom.SwagoRoomManager
import com.swago.baseswago.constant.UrlConstant
import com.swago.baseswago.fragment.BaseXFragment
import com.swago.baseswago.im.IRoomChat
import com.swago.baseswago.model.im.RoomSystemMsgBean
import com.swago.baseswago.model.im.UserJoinRoomBean
import com.swago.baseswago.model.live.RoomUserModel
import com.swago.baseswago.model.live.gift.GiftModel
import com.swago.baseswago.util.*
import com.swago.room.R
import com.swago.room.adapter.RoomChatAdapter
import com.swago.room.databinding.FragmentBaseComBinding
import com.swago.room.dialog.MessageListDialog
import com.swago.room.dialog.SendMsgDialog
import com.swago.room.game.GamePlayDialog
import com.swago.room.gift.GiftConfig
import com.swago.room.gift.GiftDialog
import com.swago.room.gift.GiftVm
import com.swago.room.gift.control.SvgPlayerManager
import com.swago.room.giftdandao.GiftDanDaoManager
import com.swago.room.inter.IFooter
import com.swago.room.inter.IHeader
import com.swago.room.piaotiao.WaftManager
import com.swago.room.vm.MsgVm
import com.swago.room.vm.RoomVm
import com.swago.room.widget.ComHeaderView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.io.File
import java.lang.Exception
import java.util.concurrent.CopyOnWriteArrayList

/**
 *@date 2021/10/8 16:43
 *description:
 */
abstract class BaseComFragment<T : FragmentBaseComBinding> : BaseXFragment<T>(),
    IRoomActiveListener,
    RoomTimer.TimeTickListener {

    val giftVm by activityViewModels<GiftVm>()

    val roomVm by activityViewModels<RoomVm>()
    val msgVm by activityViewModels<MsgVm>()
    val userVm by activityViewModels<UserVm>()

    //直播间观众列表
    var roomUserList = CopyOnWriteArrayList<RoomUserModel.ListBean>()

    //聊天消息
    private val dataChatList = CopyOnWriteArrayList<IRoomChat>()

    abstract val iHeader: IHeader
    abstract val iFooter: IFooter

    var dialog: SendMsgDialog? = null
    var gameDialog: GamePlayDialog? = null
    var msgListDialog: MessageListDialog? = null

    private val chatAdapter by lazy {
        RoomChatAdapter()
    }

    private val svgPlayerManager by lazy {
        SvgPlayerManager()
    }

    private val waftManager by lazy {
        WaftManager()
    }

    private val danDaoManager by lazy {
        GiftDanDaoManager()
    }

    override fun loadData() {

    }

    override fun initOther() {
        RoomTimer.timeTickList.add(this)
        SwagoRoomManager.addListener(this)
        binding.headFl.addView(iHeader.getHeaderView())
        binding.footerFl.addView(iFooter.getFooterView())
        setHeaderViewPosition()
        //获取礼物列表
        giftVm.getGiftList()
        //飘条
        waftManager.init()
        waftManager.waftViewList.add(binding.waftView)
        waftManager.waftViewList.add(binding.waftView2)
        //弹道
        danDaoManager.init()
        danDaoManager.giftDanDaoViewList.add(binding.danDaoView)
        danDaoManager.giftDanDaoViewList.add(binding.danDaoView2)
        danDaoManager.giftDanDaoViewList.add(binding.danDaoView3)

        val layoutManager = LinearLayoutManager(context)
        layoutManager.stackFromEnd = true
        binding.rv.layoutManager = layoutManager
        binding.rv.addItemDecoration(RoomChatItemDecoration())
        binding.rv.adapter = chatAdapter
        chatAdapter.setNewData(dataChatList)
        context?.let {
            svgPlayerManager.init(it, binding.xSvgaPlayer, binding.svgDanDaoView)
        }

        activity?.let {
            KeyboardUtils.registerSoftInputChangedListener(it.window, listener)
        }
    }

    var listener = KeyboardUtils.OnSoftInputChangedListener {
        if (it == 0) {
            setChatRvPop(false, it)
        } else {
            setChatRvPop(true, it)
        }
    }

    private fun setHeaderViewPosition() {
        val height = ImmersionBar.getStatusBarHeight(this)
        val params = binding.headFl.layoutParams as ConstraintLayout.LayoutParams
        params.topMargin = height
        binding.headFl.layoutParams = params
    }

    override fun initLiveData() {
        roomVm.roomUserDataLiveData.observe(this) {
            roomUserList.clear()
            roomUserList.addAll(it)
            (iHeader as ComHeaderView).updateRoomUser(it)
        }

        msgVm.updateUserRoom = { userJoinRoomBean, isJoinOrExit ->
            var isInit = false
            roomUserList.forEach {
                if (it != null && it.user_account == userJoinRoomBean.senderCode) {
                    isInit = true
                    if (!isJoinOrExit) {
                        roomUserList.remove(it)
                    }
                    return@forEach
                }
            }
            if (isJoinOrExit) {
                if (!isInit) {
                    val data = RoomUserModel.ListBean()
                    data.user_account = userJoinRoomBean.senderCode
                    data.user_head_img_url = userJoinRoomBean.userAvatar
                    data.user_id = userJoinRoomBean.senderId
                    data.user_name = userJoinRoomBean.senderName
                    roomUserList.add(0, data)
                }
            }
            (iHeader as ComHeaderView).updateRoomUser(roomUserList)
        }

        chatAdapter.showUserInfoDialog = {
            var isAnchor = false
            SwagoRoomManager.iRoomInfo?.let { iRoomInfo ->
                isAnchor = iRoomInfo.getAnchorId() == it.getSenderId()
            }
            PersonDataDFragment.newInstance(it.getSenderId(), isAnchor = isAnchor, inRoom = true)
                .apply {
                    this.openGiftDialog = { nickName, userId ->
                        GiftDialog.newInstance(
                            nickName,
                            userId
                        ).show(childFragmentManager, "GiftDialog")
                    }
                }.show(childFragmentManager, "PersonDataDFragment")
        }

        msgVm.newChatMsgFun = {
            addChatMsgToRv(it)
        }
        msgVm.playSvgUrl = {
            //svg播放
            svgPlayerManager.addSvgUrl(it)
            svgPlayerManager.addSvgDanDaoView(it)
        }
        //飘条
        msgVm.waftFun = {
            waftManager.addNewMessage(it)
        }
        msgVm.showGiftDanDao = {
            danDaoManager.addNewMessage(it)
        }

        msgVm.inComeChange = {
            (iHeader as ComHeaderView).updateIncome(it)
        }

        msgVm.updateHotValue = {
            (iHeader as ComHeaderView).updateHotValue(it)
        }

        (iHeader as ComHeaderView).followFun = {
            userVm.followUser(it, 0)
        }


    }

    private fun addChatMsgToRv(it: IRoomChat?) {
        if (dataChatList.size > 150) {
            dataChatList.removeAt(0)
        }
        it?.let {
            dataChatList.add(it)
        }
        chatAdapter.notifyDataSetChanged()
        binding.rv.smoothScrollToPosition(dataChatList.size - 1)
    }


    private var keyboardUpRvLayoutParams: ViewGroup.LayoutParams? = null
    private var keyboardCloseRvLayoutParams: ViewGroup.LayoutParams? = null
    private fun setChatRvPop(isPopUp: Boolean, height: Int) {
        if (isPopUp) {
            if (keyboardUpRvLayoutParams == null) {
                keyboardUpRvLayoutParams =
                    ConstraintLayout.LayoutParams(0, DpPxUtil.dip2px(170f)).apply {
                        bottomToBottom = R.id.cl
                        startToStart = R.id.cl
                        endToEnd = R.id.cl
                        marginStart = DpPxUtil.dip2px(10f)
                        marginEnd = DpPxUtil.dip2px(10f)
                        bottomMargin = height + DpPxUtil.dip2px(55f)
                    }
            }
            binding.rv.layoutParams = keyboardUpRvLayoutParams
        } else {
            if (keyboardCloseRvLayoutParams == null) {
                keyboardCloseRvLayoutParams =
                    ConstraintLayout.LayoutParams(0, DpPxUtil.dip2px(170f)).apply {
                        bottomToBottom = R.id.cl
                        startToStart = R.id.cl
                        endToEnd = R.id.cl
                        marginStart = DpPxUtil.dip2px(10f)
                        marginEnd = DpPxUtil.dip2px(10f)
                        bottomMargin = DpPxUtil.dip2px(70f)
                    }
            }
            binding.rv.layoutParams = keyboardCloseRvLayoutParams
        }

    }


    override fun onDestroyView() {
        super.onDestroyView()
        activity?.let {
            KeyboardUtils.unregisterSoftInputChangedListener(it.window)
        }
        SwagoRoomManager.removeListener(this)
    }

    fun openSendMessageDialog() {
        dialog = SendMsgDialog()
        dialog?.addSenderMsgToRoomChatList = {
            addChatMsgToRv(it)
        }
        dialog?.show(childFragmentManager, "SendMsgDialog")
    }

    fun openMessageListDialog() {
        msgListDialog = MessageListDialog()
        msgListDialog?.show(childFragmentManager, "MessageListDialog")
    }

    fun openGameDialog() {

        SwagoRoomManager.iRoomInfo?.let {
            val download = checkGameVersion(
                it.getGameType().toString(),
                it.getGameDownLoadUrl(),
                it.getGameVersion().toString()
            )
            if (download) {
                gameDialog =
                    GamePlayDialog.newInstance("file://" + UrlConstant.appGameRootPath + File.separator + it.getGameType() + File.separator + "index.html")
            } else {
                gameDialog = GamePlayDialog.newInstance(it.getGameUrl())
            }
            gameDialog?.show(childFragmentManager, "GamePlayDialog")
        }
    }

    override fun joinedRoom(iRoomInfo: IRoomInfo) {
        if (iRoomInfo.getRoomSystemMsg().isNotEmpty()) {
            val roomSystemMsgBean = RoomSystemMsgBean()
            roomSystemMsgBean.broadcast_notice_content = iRoomInfo.getRoomSystemMsg()
            dataChatList.add(roomSystemMsgBean)
            chatAdapter.notifyDataSetChanged()
        }


    }

    override fun leaveRoom(iRoomInfo: IRoomInfo) {
        dataChatList.clear()
        chatAdapter.notifyDataSetChanged()

    }

    override fun closeRoomed() {
        RoomTimer.timeTickList.remove(this)
    }

    inner class RoomChatItemDecoration : RecyclerView.ItemDecoration() {

        override fun getItemOffsets(
            outRect: Rect,
            view: View,
            parent: RecyclerView,
            state: RecyclerView.State
        ) {
            val margin = DpPxUtil.dip2px(10f)
            outRect.set(0, 0, 0, margin)
        }
    }

    override fun onResume() {
        super.onResume()
        msgVm.isReady = true
    }

    override fun onPause() {
        super.onPause()
        msgVm.isReady = false
    }

    override fun onTimeCount(time: Int) {
        if (time != 0 && time % 30 == 0) {
            SwagoRoomManager.iRoomInfo?.let {
                roomVm.loadRoomData(it.getRoomId())
            }

        }
    }


    private fun checkGameVersion(
        gameId: String,
        gamePackageUrl: String,
        gameVersionCode: String
    ): Boolean {
        if (gamePackageUrl.isEmpty() || gameVersionCode.isEmpty()) {
            return false
        }

        val zipNames = gamePackageUrl.split("/")
        val gameName = zipNames.last()
        if (TextUtils.isEmpty(UrlConstant.appGameRootPath) || !File(UrlConstant.appGameRootPath + File.separator + gameId).exists()) {
            downLoadGamePackage(gameId, gamePackageUrl, gameVersionCode, gameName)
            return false
        } else {
            return if (!File(UrlConstant.appGameRootPath + File.separator + gameId + File.separator + gameName).exists()) {
                downLoadGamePackage(gameId, gamePackageUrl, gameVersionCode, gameName)
                false
            } else {
                val localGameVersionCode = SpUtil.readInt(gameId)
                if (localGameVersionCode == 0 || (gameVersionCode.isNotEmpty() && localGameVersionCode < gameVersionCode.toInt())) {
                    downLoadGamePackage(gameId, gamePackageUrl, gameVersionCode, gameName)
                    false
                } else {
                    true
                }
            }
        }

    }

    private fun downLoadGamePackage(
        gameId: String,
        gamePackageUrl: String,
        gameVersionCode: String,
        name: String
    ) {
        val path = UrlConstant.appGameRootPath + File.separator + gameId
        val file = File(path)
        if (file.exists()) {
            file.delete()
        }
        file.mkdirs()

        val task = DownloadTask.Builder(gamePackageUrl, path, name).build()
        task.enqueue(object : DownloadListener {
            override fun taskStart(task: DownloadTask) {}

            override fun connectTrialStart(
                task: DownloadTask,
                requestHeaderFields: MutableMap<String, MutableList<String>>
            ) {
            }

            override fun connectTrialEnd(
                task: DownloadTask,
                responseCode: Int,
                responseHeaderFields: MutableMap<String, MutableList<String>>
            ) {
            }

            override fun downloadFromBeginning(
                task: DownloadTask,
                info: BreakpointInfo,
                cause: ResumeFailedCause
            ) {
            }

            override fun downloadFromBreakpoint(task: DownloadTask, info: BreakpointInfo) {}

            override fun connectStart(
                task: DownloadTask,
                blockIndex: Int,
                requestHeaderFields: MutableMap<String, MutableList<String>>
            ) {
            }

            override fun connectEnd(
                task: DownloadTask,
                blockIndex: Int,
                responseCode: Int,
                responseHeaderFields: MutableMap<String, MutableList<String>>
            ) {
            }

            override fun fetchStart(task: DownloadTask, blockIndex: Int, contentLength: Long) {}

            override fun fetchProgress(task: DownloadTask, blockIndex: Int, increaseBytes: Long) {}

            override fun fetchEnd(task: DownloadTask, blockIndex: Int, contentLength: Long) {}

            override fun taskEnd(task: DownloadTask, cause: EndCause, realCause: Exception?) {
                GlobalScope.launch(Dispatchers.IO) {
                    val packagePath = path + File.separator + name
                    FileUtil.upZipFile(packagePath, path + File.separator)
                    SpUtil.putInt(gameId, gameVersionCode.toInt())
                }
            }

        })
    }

}