package com.ez.ertc.call.ui

import android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.content.res.Configuration
import android.media.AudioManager
import android.os.*
import android.preference.PreferenceManager
import android.view.*
import android.widget.*
import androidx.appcompat.app.ActionBar
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.ez.baselib.utils.GsonUtils
import com.ez.baselib.utils.LogUtil
import com.ez.basertc.RTCConstant
import com.ez.basertc.RTCConstant.ERTCVideoEncParam
import com.ez.basertc.RTCConstant.ERTCVideoResolution
import com.ez.basertc.RTCListener
import com.ez.ertc.ConstantApp
import com.ez.ertc.MyApp
import com.ez.ertc.R
import com.ez.ertc.base.BaseActivity
import com.ez.ertc.call.bean.DeviceState
import com.ez.ertc.call.bean.UserStatusData
import com.ez.ertc.call.bean.VideoInfoData
import com.ez.ertc.call.service.EZVideoMeetingService
import com.ez.ertc.call.service.StatsLiveDataService
import com.ez.ertc.call.ui.*
import com.ez.ertc.call.ui.widget.EzmTextureView
import com.ez.basertc.utils.EncoderParamUtils
import com.ez.dclog.RTCStatsListener
import kotlinx.android.synthetic.main.activity_call.*
import kotlinx.android.synthetic.main.activity_settings.*
import java.util.*
import com.ez.dclog.statistics.ERTCLocalAudioStats
import com.ez.dclog.statistics.ERTCLocalVideoStats
import com.ez.dclog.statistics.ERTCRemoteAudioStats
import com.ez.dclog.statistics.ERTCRemoteVideoStats


class CallActivity : BaseActivity() {

    private val TAG = "CallActivity"

    private val REQUEST_MEDIA_PROJECTION = 1000
    // should only be modified under UI thread
    private val userTextureViewList = HashMap<String, EzmTextureView?>() // userId = 0 || userId == EngineConfig.mUid

    @Volatile
    private var mVideoEnabled = true

    @Volatile
    private var mAudioEnabled = false

    @Volatile
    private var mSpeakerPhoneOn = true

    @Volatile
    private var mSmallStreamOn = false

    private var renderMode = RTCConstant.ERTC_VIDEO_RENDER_MODE_FILL

    private var localUserInfo: RTCConstant.EnterParam? = null

    private var userStatusList = ArrayList<UserStatusData>()

    private var userAdapter : UserAdapter? = null
    private var orientation = 0

    //当前选中的大屏user
    private var currentBigUserStatusData: UserStatusData? = null

    private var localTextureView: EzmTextureView? = null

    private val rtcListener = object : RTCListener() {

        override fun onEnterRoomSuccess() {
            super.onEnterRoomSuccess()
            runOnUiThread {
                currentBigUserStatusData = UserStatusData()
                currentBigUserStatusData?.userId = localUserInfo!!.userId
                setLocalViewChanged()
                progressBar_big.isVisible = false
                toast("加入房间成功roomID: ${com.ez.network.BaseRTC.getInstance().appId + localUserInfo!!.roomId}")
                LogUtil.d(TAG, "newRoomID：${com.ez.network.BaseRTC.getInstance().appId + localUserInfo!!.roomId}")
            }
        }

        override fun onRemoteUserEnterRoom(userId: String) {
            runOnUiThread {
                toast("{$userId}加入房间")
                var hasRemoteUser = false
                userStatusList.forEach {
                    if(it.userId == userId){
                        hasRemoteUser = true
                        return@forEach
                    }
                }
                if(!hasRemoteUser) {
                    val remoteUser = UserStatusData()
                    remoteUser.userId = userId
                    remoteUser.videoInfoData = VideoInfoData(0, 0)
                    remoteUser.streamType = RTCConstant.ERTC_VIDEO_STREAM_TYPE_BIG
                    userStatusList.add(remoteUser)
                }
                doRenderRemoteUi(userId)
                userAdapter?.notifyDataSetChanged(userStatusList)
            }
        }

        override fun onRemoteUserLeaveRoom(userId: String, reason: Int) {
            runOnUiThread {
                toast("{$userId}离开房间")
                LogUtil.d(TAG, "{$userId}离开房间" + GsonUtils.toJson(userStatusList) + "ui:" + userTextureViewList.size)
                userStatusList =
                    userStatusList.filter { it.userId != userId } as ArrayList<UserStatusData>
                doRemoveRemoteUi(userId)
                userAdapter?.notifyDataSetChanged(userStatusList)

            }
        }

        // 刚进入房间时，该回调先与onRemoteUserEnterRoom
        override fun onUserVideoAvailable(userId: String, enable: Boolean, streamType: Int) {
            LogUtil.d(TAG, "onUserVideoAvailable {$userId} enable {$enable}")
            var hasRemoteUser = false
            userStatusList.forEach {
                if(it.userId == userId){
                    hasRemoteUser = true
                    return@forEach
                }
            }
            if(!hasRemoteUser && enable) {
                val remoteUser = UserStatusData()
                remoteUser.userId = userId
                remoteUser.videoInfoData = VideoInfoData(0, 0)
                remoteUser.videoStatus = if (enable) DeviceState.DS_Active.value else DeviceState.DS_Closed.value
                remoteUser.streamType = streamType
                userStatusList.add(remoteUser)
            } else {
                userStatusList.forEach { remoteUser ->
                    if (remoteUser.userId == userId) {
                        remoteUser.videoStatus =
                            if (enable) DeviceState.DS_Active.value else DeviceState.DS_Closed.value
                        remoteUser.streamType = streamType
                    }
                }
            }
            if (enable) {
                doRenderRemoteUi(userId)
            }else {
                doRemoveRemoteUi(userId)
            }

        }

        override fun onUserAudioAvailable(userId: String, available: Boolean) {
            userStatusList.forEach { romoteUser ->
                if(romoteUser.userId == userId) {
                    romoteUser.audioStatus = if (available) DeviceState.DS_Active.value else DeviceState.DS_Closed.value
                }
            }
            runOnUiThread {
                LogUtil.d(TAG, "用户[$userId]声音$available")
            }
        }

        override fun onFirstLocalVideoFrame(width: Int, height: Int) {
            LogUtil.d(TAG, "onFirstLocalVideoFrame self res[$width * $height]")
            runOnUiThread {
                progressBar_big.isVisible = false
                userStatusList.forEach {
                    if(it.userId == localUserInfo!!.userId){
                        it.videoInfoData = VideoInfoData(width, height)
                    }
                }
                doHideTargetView(localUserInfo!!.userId, false)
            }
        }

        override fun onFirstRemoteVideoFrame(userId: String, width: Int, height: Int) {
            LogUtil.d(TAG, "onFirstRemoteVideoFrame userId[$userId] res[$width * $height]")
            runOnUiThread {
                progressBar_big.isVisible = false
                userTextureViewList[userId]?.hideProgress()
                userStatusList.forEach {
                    if(it.userId == userId){
                        it.videoInfoData = VideoInfoData(width, height)
                    }
                }
                doHideTargetView(userId, false)
            }
        }

        override fun onVolumeEvaluation(audioVolumeInfoList: MutableList<RTCConstant.AudioVolumeInfo>, total: Int) {
            runOnUiThread {
                userStatusList.forEach{
                    it.audioStatus = DeviceState.DS_Closed.value
                    it.volume = 0
                }
                audioVolumeInfoList.forEach { info ->
                    userStatusList.forEach inner@{ user ->
                        if (user.userId == info.userId) {
                            if(user.userId == localUserInfo!!.userId) {
                                if(mAudioEnabled) {
                                    user.volume = info.volume
                                    if(user.volume > 0) {
                                        user.audioStatus = DeviceState.DS_Active.value
                                    }
                                    return@inner
                                }
                                return@inner
                            }
                            user.volume = info.volume
                            if(user.volume > 0) {
                                user.audioStatus = DeviceState.DS_Active.value
                            }
                            return@inner
                        }
                    }
                }
                grid_video_view_container.notifyDataSetChanged(userStatusList)
            }
        }

        override fun onNetworkQuality(userId: String, upNetQuality: Int, downNetQuality: Int) {
            runOnUiThread {
                userStatusList.forEach {
                    if (userId == it.userId){
                        it.networkQuality = upNetQuality
                        return@forEach
                    }
                }
                userAdapter?.notifyDataSetChanged(userStatusList)
                grid_video_view_container.notifyDataSetChanged(userStatusList)
            }
        }

        override fun onError(errorCode: Int) {
            runOnUiThread {
//                toast("recv error:$errorCode")
//                finish()
                if (!isFinishing){
                    showAlertDialog(errorCode)
                }else{
                    toast("recv error:$errorCode")
                }
            }
        }

        override fun onShareStateChanged(userId: String?, enable: Boolean) {
            runOnUiThread {
                switch_look_share.isEnabled = enable
                if (!enable) {
                    grid_video_view_share.isVisible = false
                    switch_look_share.setOnCheckedChangeListener(null)
                    switch_look_share.isChecked = false
                } else {
                    grid_video_view_share.tag = userId
                    switch_look_share.setOnCheckedChangeListener(subShareChangeListener)
                }
            }
        }

        override fun onRecvCustomMsg(userId: String, message: ByteArray?, messageSize: Int) {
            runOnUiThread {
                toast("userId:$userId message:{${message?.let { String(it) }} messageSize: $messageSize}")
            }
        }

        override fun onExitRoom(reason: Int) {
            super.onExitRoom(reason)
        }

        override fun onWarning(warnCode: Int) {
            super.onWarning(warnCode)
        }

        override fun onDisplayLoadingState(userId: String?, unDisplayTime: Long) {
            runOnUiThread {
                if(currentBigUserStatusData?.userId?.equals(userId) == true) {
                    progressBar_big.isVisible = unDisplayTime > 2*1000
                }
                if(unDisplayTime > 2*1000) {
                    userTextureViewList[userId]?.showProgress()
                } else {
                    userTextureViewList[userId]?.hideProgress()
                }
            }
        }
    }

    private val rtcStatsListener = object : RTCStatsListener() {

        override fun onLocalVideoStats(localVideoStats: ERTCLocalVideoStats?) {
//            LogUtil.d(TAG, "onLocalVideoStats "+ GsonUtils.toJson(localVideoStats))
            runOnUiThread {
                StatsLiveDataService.instance?.mERTCLocalVideoStats?.value = localVideoStats
            }
        }

        override fun onLocalAudioStats(localAudioStats: ERTCLocalAudioStats?) {
            LogUtil.d(TAG, "onLocalAudioStats "+ GsonUtils.toJson(localAudioStats))
            runOnUiThread {
                StatsLiveDataService.instance?.mERTCLocalAudioStats?.value = localAudioStats
            }
        }

        override fun onRemoteVideoStats(remoteVideoStats: ERTCRemoteVideoStats?) {
            LogUtil.d(TAG, "onRemoteVideoStats "+ GsonUtils.toJson(remoteVideoStats))
            runOnUiThread {
                StatsLiveDataService.instance?.mERTCRemoteVideoStats?.value = remoteVideoStats
            }
        }

        override fun onRemoteAudioStats(remoteAudioStats: ERTCRemoteAudioStats?) {
            LogUtil.d(TAG, "onRemoteAudioStats "+ GsonUtils.toJson(remoteAudioStats))
            runOnUiThread {
                StatsLiveDataService.instance?.mERTCRemoteAudioStats?.value = remoteAudioStats
            }
        }
    }

    private val subShareChangeListener =
        CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->
            if (isChecked) {
                MyApp.ertcEngine?.setScreenShareWindow(grid_video_view_share)
            } else {
                MyApp.ertcEngine?.setScreenShareWindow(null)
            }
            grid_video_view_share.isVisible = isChecked
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        makeActivityContentShownUnderStatusBar()
        setContentView(R.layout.activity_call)
        val ab = supportActionBar
        if (ab != null) {
            ab.displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM
            var layout = View.inflate(this, R.layout.ard_agora_actionbar_with_back_btn, null)
            layout.findViewById<ImageView>(R.id.img_back).setOnClickListener {
                finish()
            }

            val option = layout.findViewById<View>(R.id.img_options)
            option.visibility = View.VISIBLE
            option.setOnClickListener{
                user_list.visibility = if (user_list.visibility == View.VISIBLE) View.GONE else View.VISIBLE
                LogUtil.d(TAG, "${user_list.visibility}")
            }

            ab.setCustomView(layout, ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
        }

        configEngine()
        initUIandEvent()

        initRemoteListUI()

        connectToService()
    }
    private fun configEngine() {
        MyApp.ertcEngine?.setRTCListener(rtcListener)
        MyApp.ertcEngine?.setRtcStatsListener(rtcStatsListener)
        MyApp.ertcEngine?.setSensorMode(1)
        val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
        val rotation = windowManager.defaultDisplay.rotation
        if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
            orientation = Configuration.ORIENTATION_PORTRAIT
        }

        val sp = PreferenceManager.getDefaultSharedPreferences(this)
        renderMode = sp.getInt(ConstantApp.PrefManager.PREF_PROPERTY_RENDER_MODE, RTCConstant.ERTC_VIDEO_RENDER_MODE_FILL)

        val resIndex = sp.getInt(ConstantApp.PrefManager.PREF_PROPERTY_VIDEO_ENC_RESOLUTION, ConstantApp.DEFAULT_VIDEO_ENC_RESOLUTION_IDX)
        val fps = sp.getInt(ConstantApp.PrefManager.PREF_PROPERTY_VIDEO_ENC_FPS, ConstantApp.DEFAULT_VIDEO_ENC_FPS)
        val bps = sp.getInt(ConstantApp.PrefManager.PREF_PROPERTY_VIDEO_ENC_BPS, ConstantApp.DEFAULT_VIDEO_ENC_BPS)
        val isDebugLog = sp.getBoolean(ConstantApp.ACTION_KEY_DEBUG_LOG, false)
        val isHardDecode = sp.getBoolean(ConstantApp.ACTION_KEY_HARDDECODE, false)

        val videoParam = ERTCVideoEncParam()
        videoParam.videoResolution = ERTCVideoResolution.values()[resIndex]
        videoParam.videoFps = fps
        videoParam.videoBitrate = bps * 1024

        MyApp.ertcEngine?.setVideoEncoderParam(videoParam)
        MyApp.ertcEngine?.setShareViewScaleEnable(true)
        MyApp.ertcEngine?.setScreenShareEncoderParam(videoParam)
        MyApp.ertcEngine?.setLogLevelDebug(RTCConstant.BavLogLevel.BAV_LOG_LEVEL_DEBUG)
        MyApp.ertcEngine?.setHardDecodePriority(isHardDecode)
    }

    private fun initUIandEvent() {
        resetOrientation()

        look_stats_data.setOnClickListener {
            var intent = Intent(this@CallActivity, StatsActivity::class.java)
            startActivity(intent)
        }

        img_hangup.setOnClickListener {
            finish()
        }

        switch_sub.setOnCheckedChangeListener { buttonView, isChecked ->
            if(!isChecked) {
                userStatusList.forEach { remoteUser ->
                    if(remoteUser.userId != localUserInfo!!.userId) {
                        remoteUser.streamType = RTCConstant.ERTC_VIDEO_STREAM_TYPE_NULL
                        doRemoveRemoteUi(remoteUser.userId)
                    }
                }
                if(currentBigUserStatusData?.userId != localUserInfo!!.userId) {
                    MyApp.ertcEngine?.setRemoteViewChanged(null, currentBigUserStatusData?.userId)
                }
                currentBigUserStatusData?.userId = localUserInfo!!.userId
                setLocalViewChanged()
            } else {
                userStatusList.forEach { remoteUser ->
                    if(remoteUser.userId != localUserInfo!!.userId) {
                        remoteUser.streamType = RTCConstant.ERTC_VIDEO_STREAM_TYPE_BIG
                        doRenderRemoteUi(remoteUser.userId)
                    }
                }
            }
            userAdapter?.notifyDataSetChanged(userStatusList)
        }

        switch_share_screen.isChecked = false
        switch_share_screen.isEnabled = true

        img_switch_camera.setOnClickListener {
            MyApp.ertcEngine?.switchCamera()
        }

        img_camera.setImageResource(if (mVideoEnabled) R.mipmap.btn_camera else R.mipmap.btn_camera_off)
        img_camera.setOnClickListener {
            mVideoEnabled = !mVideoEnabled
            MyApp.ertcEngine?.setLocalView(if(mVideoEnabled) localTextureView?.videoCanvasView else null)
            if(currentBigUserStatusData?.userId == localUserInfo?.userId) {
                setLocalViewChanged()
            }
            MyApp.ertcEngine?.enableLocalVideo(mVideoEnabled)
            if (userTextureViewList.size == 0) {
                return@setOnClickListener
            }
            img_camera.setImageResource(if (mVideoEnabled) R.mipmap.btn_camera else R.mipmap.btn_camera_off)
            doHideTargetView(localUserInfo!!.userId, !mVideoEnabled)
        }

        img_microphone.setImageResource(if (mAudioEnabled) R.mipmap.btn_microphone else R.mipmap.btn_microphone_off)
        img_microphone.setOnClickListener {
            mAudioEnabled = !mAudioEnabled
            MyApp.ertcEngine?.enableLocalAudio(mAudioEnabled)
            userStatusList.forEach {
                if (it.userId == localUserInfo?.userId) {
                    it.audioStatus =
                        if (mAudioEnabled) DeviceState.DS_Active.value else DeviceState.DS_Closed.value
                    return@forEach
                }
            }
            grid_video_view_container.notifyDataSetChanged(userStatusList)
            img_microphone.setImageResource(if (mAudioEnabled) R.mipmap.btn_microphone else R.mipmap.btn_microphone_off)
        }

        switch_speaker_id.setOnClickListener {
            mSpeakerPhoneOn = !mSpeakerPhoneOn
            switch_speaker_id.setImageResource(if (mSpeakerPhoneOn) R.mipmap.btn_speaker else R.mipmap.btn_speaker_off)
            MyApp.ertcEngine?.setSpeakerPhoneOn(mSpeakerPhoneOn)
        }

        image_small.setOnClickListener {
            mSmallStreamOn = !mSmallStreamOn

            val resIndex = PreferenceManager.getDefaultSharedPreferences(this).getInt(ConstantApp.PrefManager.PREF_PROPERTY_VIDEO_ENC_RESOLUTION, ConstantApp.DEFAULT_VIDEO_ENC_RESOLUTION_IDX)
            val videoResolution = ERTCVideoResolution.values()[resIndex]
            MyApp.ertcEngine?.setSmallVideoEncodeParam(EncoderParamUtils.getDefaultSmallVideoEncoderParam(videoResolution))
            MyApp.ertcEngine?.enableDualStreamMode(mSmallStreamOn)
            image_small.setImageResource(if (mSmallStreamOn) R.mipmap.btn_small else R.mipmap.btn_small_off)
        }

        localUserInfo = intent.getSerializableExtra(ConstantApp.ACTION_KEY_ENTER_INFO) as RTCConstant.EnterParam?
        val ab = supportActionBar
        if (ab != null) {
            val channelNameView = findViewById<View>(R.id.ovc_page_title) as TextView
            channelNameView.text = "${localUserInfo!!.roomId}[${localUserInfo!!.userId}]"
        }

        // programmatically layout ui below of status bar/action bar
        root.setPadding(0, getStatusBarHeight() + getActionBarHeight(), 0, 0)
//        val eofmp = grid_video_view_container.layoutParams as MarginLayoutParams
//        eofmp.topMargin = getStatusBarHeight() + getActionBarHeight()
//        eofmp.topMargin =
//            getStatusBarHeight() + getActionBarHeight() + resources.getDimensionPixelOffset(
//                R.dimen.activity_vertical_margin
//            ) / 2 // status bar + action bar + divider
        grid_video_view_container.setItemEventHandler(object :
            RecyclerItemClickListener.OnItemClickListener {
            override fun onItemClick(view: View, position: Int) {
                onBigVideoViewClicked(view, position)
            }

            override fun onItemLongClick(view: View, position: Int) {}
            override fun onItemDoubleClick(view: View, position: Int) {
            }
        })
        localTextureView = EzmTextureView(this)
        localTextureView?.videoCanvasView?.renderType = renderMode
        localTextureView?.hideProgress()
        userTextureViewList[localUserInfo!!.userId] = localTextureView // get first surface view

        val localUser = UserStatusData()
        localUser.userId = localUserInfo!!.userId
        localUser.videoInfoData = VideoInfoData(0, 0)
        localUser.videoStatus = DeviceState.DS_Active.value
        userStatusList.add(0, localUser)
        grid_video_view_container.initViewContainer(
            this,
            localUserInfo!!.userId,
            userTextureViewList,
            userStatusList
        ) // first is now full view

        grid_video_view_share.renderType = renderMode

        switch_look_share.setOnCheckedChangeListener(subShareChangeListener)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            switch_share_screen.setOnCheckedChangeListener { compoundButton: CompoundButton?, isChecked: Boolean ->
                if (isChecked) {
                    MyApp.ertcEngine?.initShareScreen("Screen_Crasher") { success ->
                        if (!success) {
                            toast("会议分享人数达到上限，你不能分享了")
                            switch_share_screen.isChecked = false
                        }
                    }
                    MyApp.ertcEngine?.requestShareScreenPermission(this@CallActivity, REQUEST_MEDIA_PROJECTION)
                } else {
                    MyApp.ertcEngine?.stopScreenShare()
                }
            }
        }

        bt_send.setOnClickListener{
            var sendText = et_sendtext.text.toString()
            MyApp.ertcEngine?.sendCustomMsg(sendText)
        }
        MyApp.ertcEngine?.enableAudioVolumeEvaluation(300)
        MyApp.ertcEngine?.setSpeakerPhoneOn(mSpeakerPhoneOn)
        MyApp.ertcEngine?.enableLocalVideo(mVideoEnabled)
        MyApp.ertcEngine?.setLocalView(localTextureView?.videoCanvasView)
//        MyApp.ertcEngine?.enableLocalAudio(true)
        MyApp.ertcEngine?.enterRoom(localUserInfo, RTCConstant.Scene.VideoCall)

        optional()
    }

    private fun setLocalViewChanged(){
        MyApp.ertcEngine?.setLocalViewChanged(if (mVideoEnabled) big_view else null)
        big_default_avatar.isVisible = !mVideoEnabled
        big_view.isVisible = mVideoEnabled
    }

    private fun onBigVideoViewClicked(view: View, position: Int) {
        var checkUser = view.tag as UserStatusData
        checkUser?.apply {
            if (this.userId == localUserInfo!!.userId) {
                setLocalViewChanged()
                if(currentBigUserStatusData?.userId != checkUser.userId) {
                    MyApp.ertcEngine?.setRemoteViewChanged(null, currentBigUserStatusData?.userId)
                }
                currentBigUserStatusData = checkUser
            } else {
                if(userStatusList[position].videoStatus == DeviceState.DS_Active.value) {
                    MyApp.ertcEngine?.setRemoteViewChanged(big_view, this.userId)
                    big_default_avatar.isVisible = false
                    big_view.isVisible = true
                    currentBigUserStatusData = checkUser
                    MyApp.ertcEngine?.setLocalViewChanged(null)
                }
            }
        }

    }

    private fun makeActivityContentShownUnderStatusBar() {
        // https://developer.android.com/training/system-ui/status
        // May fail on some kinds of devices
        val decorView = window.decorView
        val uiOptions = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
        decorView.systemUiVisibility = uiOptions
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            window.statusBarColor = resources.getColor(R.color.ertc_blue)
        }
    }

    private fun showOrHideStatusBar(hide: Boolean) {
        // May fail on some kinds of devices
        val decorView = window.decorView
        var uiOptions = decorView.systemUiVisibility
        uiOptions = if (hide) {
            uiOptions or View.SYSTEM_UI_FLAG_FULLSCREEN
        } else {
            uiOptions xor View.SYSTEM_UI_FLAG_FULLSCREEN
        }
        decorView.systemUiVisibility = uiOptions
    }

    private fun optional() {
        volumeControlStream = AudioManager.STREAM_VOICE_CALL
    }

    private fun doHideTargetView(targetUid: String, hide: Boolean) {
        userStatusList.forEach {
            if(it.userId == targetUid) {
                it.videoStatus =
                    if (hide) DeviceState.DS_Closed.value else DeviceState.DS_Active.value
            }
        }
        grid_video_view_container.notifyDataSetChanged(userStatusList)
    }

    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)

        grid_video_view_container.notifyUiChanged(userTextureViewList, userStatusList)

        if (orientation != newConfig.orientation) {
            orientation = newConfig.orientation
            resetOrientation()
        }
    }

    private fun resetOrientation() {
        big_view.post {
            var width = big_view.measuredWidth
            var height = big_view.measuredHeight
            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                big_view.layoutParams.width = height
                big_view.layoutParams.height = width
            } else {
                big_view.layoutParams.width = height
                big_view.layoutParams.height = width
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        MyApp.ertcEngine?.setLocalView(null)
        MyApp.ertcEngine?.enableLocalVideo(false)
        MyApp.ertcEngine?.exitRoom()
        stopService()
    }

    private fun doRenderRemoteUi(userId: String) {
        runOnUiThread {
            if (isFinishing) {
                return@runOnUiThread
            }

            if(!userTextureViewList.containsKey(userId)) {
                val ezmTextureView = EzmTextureView(this)
                ezmTextureView.videoCanvasView.renderType = renderMode
                userTextureViewList[userId] = ezmTextureView
            }
            MyApp.ertcEngine?.setRemoteView(
                userId,
                RTCConstant.ERTC_VIDEO_STREAM_TYPE_BIG,
                userTextureViewList[userId]!!.videoCanvasView
            )
            grid_video_view_container.notifyUiChanged(userTextureViewList, userStatusList)
            userAdapter?.notifyDataSetChanged(userStatusList)
        }
    }

    private fun doRemoveRemoteUi(userId: String) {
        runOnUiThread {
            if (isFinishing) {
                return@runOnUiThread
            }
            MyApp.ertcEngine?.setRemoteView(
                userId,
                RTCConstant.ERTC_VIDEO_STREAM_TYPE_BIG,
                null
            )
            userTextureViewList.remove(userId)
            grid_video_view_container.notifyUiChanged(userTextureViewList, userStatusList)
            if(currentBigUserStatusData?.userId == userId) {
                currentBigUserStatusData = UserStatusData()
                currentBigUserStatusData?.userId = localUserInfo!!.userId
                MyApp.ertcEngine?.setRemoteViewChanged(null, userId)
                setLocalViewChanged()
            }
        }
    }

    private fun initRemoteListUI(){
        user_list.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL,false)
        user_list.addItemDecoration(DividerItemDecoration(this,DividerItemDecoration.VERTICAL))
        userAdapter = UserAdapter(localUserInfo!!.userId, userStatusList)
        user_list.adapter = userAdapter
        user_list.addOnItemTouchListener(RecyclerItemClickListener(this, object : RecyclerItemClickListener.OnItemClickListener{
            override fun onItemClick(view: View, position: Int) {
                if(userStatusList[position].userId != localUserInfo!!.userId) {
                    if (userStatusList[position].streamType == RTCConstant.ERTC_VIDEO_STREAM_TYPE_NULL) {
                        userStatusList[position].streamType = RTCConstant.ERTC_VIDEO_STREAM_TYPE_BIG
                        doRenderRemoteUi(userStatusList[position].userId)
                    } else {
                        userStatusList[position].streamType =
                            RTCConstant.ERTC_VIDEO_STREAM_TYPE_NULL
                        doRemoveRemoteUi(userStatusList[position].userId)
                    }
                    userAdapter?.notifyDataSetChanged(userStatusList)
                }
            }

            override fun onItemLongClick(view: View, position: Int) {

            }

            override fun onItemDoubleClick(view: View, position: Int) {

            }

        }))
    }

    //service
    private var isRecovery = false
    private val mServiceConnection: ServiceConnection = object : ServiceConnection {
        override fun onServiceConnected(componentName: ComponentName, iBinder: IBinder) {
//todo service Connection
        }

        override fun onServiceDisconnected(componentName: ComponentName) {
//            mEZVideoMeeting = null;
        }
    }

    private fun connectToService() {
        isRecovery = intent.getBooleanExtra(EZVideoMeetingService.LAUNCH_FROM_NOTIFICATION, false)
        val service = Intent(this, EZVideoMeetingService::class.java)
        if (!isRecovery) {
            service.putExtra(
                EZVideoMeetingService.SCREEN_PARAM_TYPE,
                EZVideoMeetingService.CONFLUENCE_INIT
            )
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                startForegroundService(service)
            } else {
                startService(service)
            }
        }

        bindService(service, mServiceConnection, 0)
    }


    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_MEDIA_PROJECTION && resultCode == RESULT_OK) {
            val service = Intent(this, EZVideoMeetingService::class.java)
            service.putExtra(
                EZVideoMeetingService.SCREEN_PARAM_TYPE,
                EZVideoMeetingService.SCREEN_RECORDER_CREATE
            )
            service.putExtra(EZVideoMeetingService.SCREEN_PARAM_CODE, resultCode)
            service.putExtra(EZVideoMeetingService.SCREEN_PARAM_REQUEST, requestCode)
            service.putExtra(EZVideoMeetingService.SCREEN_PARAM_DATA, data)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                startForegroundService(service)
            } else {
                startService(service)
            }
        }else {
            switch_share_screen.isChecked = false
        }
    }

    private fun stopService() {
        val intent = Intent(this@CallActivity, EZVideoMeetingService::class.java)
        stopService(intent)
    }

    private fun showAlertDialog(code: Int) {
        val ensureDialog: AlertDialog = AlertDialog.Builder(this)
            .setTitle("recv error:$code")
            .setCancelable(false)
            .setPositiveButton("确定") { dialog, _ ->
                dialog.dismiss()
                finish()
            }
            .create()
        ensureDialog.show()
    }

}