package com.ydl.consultantim

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.graphics.Paint
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.net.Uri
import android.os.PowerManager
import android.provider.Settings
import android.text.TextUtils
import android.view.View
import android.view.animation.AccelerateInterpolator
import androidx.core.content.ContextCompat
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
import com.google.gson.Gson
import com.tbruyelle.rxpermissions2.RxPermissions
import com.ydl.audioim.BuildConfig
import com.ydl.audioim.R
import com.ydl.audioim.YDLavManager
import com.ydl.audioim.http.command.ConnectExceptionCommand
import com.ydl.audioim.http.command.PayLoad
import com.ydl.audioim.player.AudioPlayer
import com.ydl.audioim.utils.AudioLogUtils
import com.ydl.audioim.utils.DateUtils
import com.ydl.consultantim.contract.IConsultantAudioHomeActivityContract
import com.ydl.consultantim.event.AudioHomeEvent
import com.ydl.consultantim.presenter.ConsultantAudioHomePresenterImpl
import com.ydl.consultantim.utils.ConsultantAudioUtils
import com.ydl.consultantim.utils.VibratorUtil
import com.ydl.ydl_av.chat.bean.AudioMessageBean
import com.ydl.ydl_av.voice.listener.IYDLVoiceEventHandler
import com.ydl.ydl_av.voice.manager.YDLVoiceManager
import com.ydl.ydl_image.config.SimpleImageOpConfiger
import com.ydl.ydl_image.manager.YDLImageCacheManager
import com.ydl.ydlcommon.base.BaseMvpActivity
import com.ydl.ydlcommon.modular.ModularServiceManager
import com.ydl.ydlcommon.router.YdlCommonRouterManager
import com.ydl.ydlcommon.utils.ActivityManager
import com.ydl.ydlcommon.utils.LogUtil
import com.ydl.ydlcommon.utils.StatusBarUtils
import com.ydl.ydlcommon.utils.Utils
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
import com.ydl.ydlcommon.utils.log.AliYunLogConfig
import com.ydl.ydlcommon.utils.log.AliYunRichLogsHelper
import com.ydl.ydlcommon.utils.log.LogHelper
import com.ydl.ydlcommon.utils.remind.ToastHelper
import com.yidianling.user.api.service.IUserService
import de.greenrobot.event.EventBus
import io.agora.rtc.Constants
import io.agora.rtc.IRtcEngineEventHandler
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.audioim_cativity_consultant_audio_home.*
import java.util.*
import java.util.concurrent.TimeUnit

/**
 * @author jiucheng
 * @描述: 咨询声网通话页面(用户接受电话界面)
 * @Copyright Copyright (c) 2018
 * @Company 壹点灵
 * @date 2018/10/30
 */
@Route(path = "/av/ConsultantAudioHomeActivity")
class ConsultantAudioHomeActivity :
    BaseMvpActivity<IConsultantAudioHomeActivityContract.View, IConsultantAudioHomeActivityContract.Presenter>(),
    IConsultantAudioHomeActivityContract.View, SensorEventListener {

    //语音管理类
    private var voiceManage: YDLVoiceManager? = null

    //音视频数据
    private var mAudioMessageBean: AudioMessageBean? = null

    //音频播放
    private var mPlayer: AudioPlayer? = null

    //当前状态 0.未接听 1.已接听
    public var status = STATUS_NOT_ANSWERED

    //电源管理对象
    private var localPowerManager: PowerManager? = null

    //电源锁
    private var localWakeLock: PowerManager.WakeLock? = null
    private var sensorManager: SensorManager? = null

    /**
     * 通话开始时间(接通)
     */
    private var callStartTime: Long? = null

    /**
     * 本次倾述倒计时
     */
    private var totalDisposable: Disposable? = null
    private var connectingStatusDisposable: Disposable? = null

    //频道管理器
    //    private var channelManager: ChannelManager? = null

    //频道token
    private var channelToken: String? = null
    private var hasUpLoadLog = false
    private var callStatus: Int = -1
    private var userId = -1

    /**
     * 是否连接成功
     */
    private var isConnectSuccess: Boolean = false

    companion object {
        const val PARAM: String = "param"

        //0.未接听 1.已接听
        const val STATUS_NOT_ANSWERED = 0
        const val STATUS_ANSWERED = 1

        //666.未接听,直接挂断 667.已接听,正常挂断  668:未接听,用户端取消了
        const val RESULT_NOT_ANSWERED_CODE = 666
        const val RESULT_ANSWERED_CODE = 667
        const val RESULT_USER_CANCEL = 668
    }
    /**
     * 事件回调 (SDK 通过指定的事件通知应用程序 SDK 的运行事件,如: 加入或离开频道,新用户加入频道等)
     */
    private val mRtcEventHandler = object : IYDLVoiceEventHandler() {

        /**
         * 远端用户静音回调
         * @param uid 用户 ID
         * @param muted 该用户是否静音:true: 该用户已静音音频 false: 该用户已取消音频静音
         */
        override fun onUserMuteAudio(uid: Int, muted: Boolean) {
            callEventSave("80", "uid:${uid}  开启了静音 = ${muted}")
            AliYunRichLogsHelper.getInstance()
                .sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:咨询用户端:uid:${uid}  开启了静音 = ${muted} channelId:${mAudioMessageBean?.channelId}")
//            runOnUiThread {
//                showToast("对方静音了,提醒他打开!")
//            }
        }

        override fun onJoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) {
            super.onJoinChannelSuccess(channel, uid, elapsed)
            callEventSave("40", "uid:${uid}  加入声网($channel)频道成功")

            LogUtil.e("[agora]$uid 加入频道回调")
            writeAgoraLog("被叫(用户)加入声网($channel)频道成功")
            AliYunRichLogsHelper.getInstance()
                .sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:被叫(用户)uid:${uid}加入声网($channel)频道成功")
            runOnUiThread {
                // 加入频道后再通知用户已接受
                //        YDLRTMClient.instances.acceptCall(mAudioMessageBean?.channelId)
                YDLavManager.instances.acceptCall(
                    mAudioMessageBean?.userId!!,
                    mAudioMessageBean?.channelId,
                    Gson().toJson(mAudioMessageBean)
                )

                tv_toast.visibility = View.VISIBLE
                tv_toast.text = "连接中..."

                voiceManage!!.getVoiceApi().setEnableSpeakerphone(false)

                connectingStatusWaitingTimeCount()

                tv_tips.visibility = View.INVISIBLE
            }
        }

        /**
         * 重新加入频道回调
         */
        override fun onRejoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) {
            super.onRejoinChannelSuccess(channel, uid, elapsed)
            callEventSave("70", "uid:${uid}  被叫(用户${uid})重新加入声网频道($channel)成功")

            LogUtil.e("[agora]$uid 重新加入频道回调")
            writeAgoraLog("被叫(用户)重新加入声网频道($channel)成功")
            AliYunRichLogsHelper.getInstance()
                .sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:被叫(用户)uid:${uid} 重新加入声网频道($channel)成功")

            runOnUiThread {
                if (!isConnectSuccess) {
                    tv_toast.visibility = View.VISIBLE
                    tv_toast.text = "连接中..."


                    voiceManage!!.getVoiceApi().setEnableSpeakerphone(false)

                    connectingStatusWaitingTimeCount()
                }
            }
        }

        override fun onUserJoined(uid: Int, elapsed: Int) {
            super.onUserJoined(uid, elapsed)
            callEventSave("40", "uid:${uid}  主叫(专家)加入声网频道成功")

            LogUtil.e("[agora]远端用户加入频道回调")
            writeAgoraLog("主叫(专家)加入声网频道成功")
            AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:主叫(专家)uid:${uid}加入声网频道成功 channelId:${mAudioMessageBean?.channelId}")

            //另一方加入频道成功
            runOnUiThread {
                isConnectSuccess = true
                //通话开始,刷新ui开始倒计时
                updateStartUi()
                status = STATUS_ANSWERED
                //接通开始回调
                callStartTime = System.currentTimeMillis()
            }
        }

        override fun onRtcStats(stats: IRtcEngineEventHandler.RtcStats?) {
        }

        /**
         * * 该回调在网络连接状态发生改变的时候触发,并告知用户当前的网络连接状态,和引起网络状态改变的原因。
         * @param state    当前的网络连接状态:
         * CONNECTION_STATE_DISCONNECTED(1):网络连接断开
         * CONNECTION_STATE_CONNECTING(2):建立网络连接中
         * CONNECTION_STATE_CONNECTED(3):网络已连接
         * CONNECTION_STATE_RECONNECTING(4):重新建立网络连接中
         * CONNECTION_STATE_FAILED(5):网络连接失败
         * @param reason 引起当前网络连接状态发生改变的原因:
         * CONNECTION_CHANGED_CONNECTING(0):建立网络连接中
         * CONNECTION_CHANGED_JOIN_SUCCESS(1):成功加入频道
         * CONNECTION_CHANGED_INTERRUPTED(2):网络连接中断
         * CONNECTION_CHANGED_BANNED_BY_SERVER(3):网络连接被服务器禁止
         * CONNECTION_CHANGED_JOIN_FAILED(4):加入频道失败
         * CONNECTION_CHANGED_LEAVE_CHANNEL(5):离开频道
         * CONNECTION_CHANGED_INVALID_APP_ID(6):不是有效的 APP ID。请更换有效的 APP ID 重新加入频道
         * CONNECTION_CHANGED_INVALID_CHANNEL_NAME(7):不是有效的频道名。请更换有效的频道名重新加入频道
         * CONNECTION_CHANGED_INVALID_TOKEN(8):生成的 Token 无效。一般有以下原因:
         * 在控制台上启用了 App Certificate,但加入频道未使用 Token。当启用了 App Certificate,必须使用 Token
         * 在调用 joinChannel 加入频道时指定的 uid 与生成 Token 时传入的 uid 不一致
         * CONNECTION_CHANGED_TOKEN_EXPIRED(9):当前使用的 Token 过期,不再有效,需要重新在你的服务端申请生成 Token
         * CONNECTION_CHANGED_REJECTED_BY_SERVER(10):此用户被服务器禁止
         * CONNECTION_CHANGED_SETTING_PROXY_SERVER(11):由于设置了代理服务器,SDK 尝试重连
         * CONNECTION_CHANGED_RENEW_TOKEN(12):更新 Token 引起网络连接状态改变
         * CONNECTION_CHANGED_CLIENT_IP_ADDRESS_CHANGED(13):客户端 IP 地址变更,可能是由于网络类型,或网络运营商的 IP 或端口发生改变引起
         * CONNECTION_CHANGED_KEEP_ALIVE_TIMEOUT(14):SDK 和服务器连接保活超时,进入自动重连状态
         * */
        override fun onConnectionStateChanged(state: Int, reason: Int) {
            super.onConnectionStateChanged(state, reason)
            // 3 网络连接被服务器中止  该情况现在是因为后端踢人逻辑
            if (reason == 3) {
                callEventSave("60", "通话挂断:网络连接被服务器(后端)中止")

                showToast("对方已挂断")
                YDLavManager.instances.callEndStatusUpdate(
                    mAudioMessageBean?.channelId!!,
                    4,
                    "服务端踢人触发的回调"
                )

                writeAgoraLog("通话挂断:网络连接被服务器(后端)中止")
                //通话结束或挂断时,上传日志文件
                uploadLog()
//                leaveChannel()
//                finish()
                close(RESULT_ANSWERED_CODE, "")
            }
        }

        /**
         * 离开频道回调(自己)
         *
         */
        override fun onLeaveChannel(stats: IRtcEngineEventHandler.RtcStats?) {
            super.onLeaveChannel(stats)
            callEventSave("52", "自己离开频道回调")

            LogUtil.e("[agora]自己离开频道回调")
            AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:自己离开频道回调  channelId:${mAudioMessageBean?.channelId}")

            //通知php 通话已结束
            close(RESULT_ANSWERED_CODE, "")
        }

        /**
         * 主播离开频道回调
         * 提示有主播离开了频道(或掉线)。
         * SDK 判断用户离开频道(或掉线)的依据是超时:在一定时间内(20 秒)没有收到对方的任何数据包,判定为对方掉线。
         * 在网络较差的情况下,可能会有误报。建议可靠的掉线检测应该由信令来做
         * @param uid 主播 ID
         * @param reason 离线原因:
         *                         USER_OFFLINE_QUIT(0):用户主动离开
         *                         USER_OFFLINE_DROPPED(1):因过长时间收不到对方数据包,超时掉线。注意:由于 SDK 使用的是不可靠通道,也有可能对方主动离开本方没收到对方离开消息而误判为超时掉线
         *                         USER_OFFLINE_BECOME_AUDIENCE(2):用户身份从主播切换为观众(直播模式下)
         */
        override fun onUserOffline(uid: Int, elapsed: Int) {
            super.onUserOffline(uid, elapsed)
            LogUtil.e("[agora]$uid 主播离开频道回调")
            when (elapsed) {
                0 -> {
                    callEventSave("52", "用户主动离开")
                }
                1 -> {
                    callEventSave(
                        "60",
                        "因过长时间收不到对方数据包,超时掉线。注意:由于 SDK 使用的是不可靠通道,也有可能对方主动离开本方没收到对方离开消息而误判为超时掉线"
                    )

                }
                2 -> {
                    callEventSave("60", "用户身份从主播切换为观众(直播模式下)")
                }
            }
            runOnUiThread {
                YDLavManager.instances.callEndStatusUpdate(
                    mAudioMessageBean?.channelId!!,
                    4,
                    "对方离开频道"
                )
                showToast("对方已挂断")
                writeAgoraLog("通话接通后挂断:主叫(专家)离开频道")
                AliYunRichLogsHelper.getInstance()
                    .sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:通话接通后挂断:主叫(专家)$uid 离开频道 channelId:${mAudioMessageBean?.channelId}")

                if (null != totalDisposable) {
                    totalDisposable!!.dispose()
                }
                //通知php 通话已结束
                close(RESULT_ANSWERED_CODE, "")
            }
        }

        override fun onWarning(warn: Int) {
            super.onWarning(warn)
            // 过滤1031 录制声音模糊
            if (warn != 1031) {
                uploadException("mRtcEventHandler-onWarning:warnCode--%${warn}")
            }
            LogUtil.e("[agora]发生警告回调=$warn")
            writeAgoraLog("声网警告回调码:($warn)")
            AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:声网警告回调码:($warn) channelId:${mAudioMessageBean?.channelId}")

            //103:没有可用的频道资源。可能是因为服务端没法分配频道资源
            //104:查找频道超时。在加入频道时 SDK 先要查找指定的频道,出现该警告一般是因为网络太差,连接不到服务器
            //105:查找频道请求被服务器拒绝。服务器可能没有办法处理这个请求或请求是非法的
            //106:打开频道超时。查找到指定频道后,SDK 接着打开该频道,超时一般是因为网络太差,连接不到服务器
            //107:打开频道请求被服务器拒绝。服务器可能没有办法处理该请求或该请求是非法的
            // 声网发出警告错误码,不应该直接离开房间
//            runOnUiThread {
//                when (warn) {
//                    103, 105, 107 -> {
//                        YDLavManager.instances.callEndStatusUpdate(mAudioMessageBean?.channelId!!, 4, "收到频道回调警告信息${warn}")
//                        writeAgoraLog("通话挂断:网络异常($warn)")
//                        showToast("当前网络较差,请更换网络!")
//                        //通话结束或挂断时,上传日志文件
//                        uploadLog()
//                        close(RESULT_NOT_ANSWERED_CODE, "[agora]专家网络较差")
//                    }
//                }
//            }
        }

        override fun onError(err: Int) {
            super.onError(err)
            uploadException("mRtcEventHandler-onError:errorCode--%${err}")
            LogUtil.e("[agora] 发生错误回调 =$err")
            writeAgoraLog("声网错误回调errorCode--%${err}")
            AliYunRichLogsHelper.getInstance()
                .sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:声网错误回调errorCode--%${err} channelId:${mAudioMessageBean?.channelId}")

            //3:SDK 初始化失败。Agora 建议尝试以下处理方法
            //7:SDK 尚未初始化,就调用其 API。请确认在调用 API 之前已创建 RtcEngine 对象并完成初始化
            //10:API 调用超时。有些 API 调用需要 SDK 返回结果,如果 SDK 处理时间过长,超过 10 秒没有返回,会出现此错误
            //17:加入频道被拒绝。一般有以下原因:
            //用户已进入频道,再次调用加入频道的 API,例如 joinChannel,会返回此错误。停止调用该方法即可。
            //用户在做 Echo 测试时尝试加入频道。等待 Echo test 结束后再加入频道即可。
            //101:不是有效的 APP ID。请更换有效的 APP ID 重新加入频道
            //102:不是有效的 频道名。请更换有效的频道名重新加入频道
            //109:当前使用的 Token 过期,不再有效
            //110:生成的 Token 无效
            //123:此用户被服务器禁止
            runOnUiThread {
                when (err) {
                    3, 7, 109, 110 -> {
                        showToast("请退出应用,重新打开")
                        close(RESULT_NOT_ANSWERED_CODE, "咨询师已挂断")
                        callEventSave(
                            "80",
                            "err:${err} 3:SDK 初始化失败|7:SDK 尚未初始化|109:当前使用的 Token 过期|110:生成的 Token 无效"
                        )

                    }
                    10 -> {
                        callEventSave("80", "err:${err} 专家网络较差")
                        showToast("当前网络较差,请更换网络")
                        close(RESULT_NOT_ANSWERED_CODE, "专家网络较差")
                    }
                    101 -> {
                        callEventSave("80", "err:${err} 不是有效的 APP ID")
                        showToast("安装包有问题,请联系技术")
                        close(RESULT_NOT_ANSWERED_CODE, "安装包有问题,请联系技术")
                    }
                    102 -> {
                        callEventSave("80", "err:${err} 不是有效的 频道名")

                        showToast("频道错误,请联系技术")
                        close(RESULT_NOT_ANSWERED_CODE, "频道错误,请联系技术")
                    }
                    123 -> {
                        callEventSave("80", "err:${err}此用户被服务器禁止")

                        //                        showToast("对方不允许接听电话,请联系客服")
                        //                        close(RESULT_NOT_ANSWERED_CODE, "该专家不允许接听电话,请联系客服")
                    }
                    else -> {
                    }
                }
                if (err == 0 || err == 18) {
                    return@runOnUiThread
                }
                YDLavManager.instances.callEndStatusUpdate(
                    mAudioMessageBean?.channelId!!,
                    4,
                    "频道的错误回调信息${err} "
                )
            }
        }

        //本地音频状态监听
        override fun onLocalAudioStateChanged(localVideoState: Int, error: Int) {
            super.onLocalAudioStateChanged(localVideoState, error)
            writeAgoraLog("本地音频回调$error")
        }

        override fun onNetworkQuality(uid: Int, txQuality: Int, rxQuality: Int) {
            super.onNetworkQuality(uid, txQuality, rxQuality)
            var status = -1
            var netStatus = when (uid) {
                0 -> {
                    if (txQuality in 1..2 && rxQuality in 1..2) {
                        ""
                    } else if (txQuality >= 5 || rxQuality >= 5) {
                        AliYunRichLogsHelper.getInstance()
                            .sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:您的网络已断开 channelId:${mAudioMessageBean?.channelId}")
                        "您的网络已断开"
                    } else {
                        status = if (txQuality >= 4 || rxQuality >= 4) {
                            0
                        } else {
                            1
                        }
                        AliYunRichLogsHelper.getInstance()
                            .sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:您的网络状况不佳 channelId:${mAudioMessageBean?.channelId}")
                        "您的网络状况不佳"
                    }
                }
                else -> {
                    if (txQuality in 1..2 && rxQuality in 1..2) {
                        ""
                    } else if (txQuality >= 5 || rxQuality >= 5) {
                        AliYunRichLogsHelper.getInstance()
                            .sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:对方的网络已断开 channelId:${mAudioMessageBean?.channelId}")
                        "对方的网络已断开"
                    } else {
                        status = if (txQuality >= 4 || rxQuality >= 4) {
                            0
                        } else {
                            1
                        }
                        AliYunRichLogsHelper.getInstance()
                            .sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:对方的网络状况不佳 channelId:${mAudioMessageBean?.channelId}")
                        "对方的网络状况不佳"
                    }
                }
            }

            showNetStatus(netStatus, status)
        }
    }

    override fun createPresenter(): IConsultantAudioHomeActivityContract.Presenter {
        return ConsultantAudioHomePresenterImpl()
    }

    override fun layoutResId(): Int {
        return R.layout.audioim_cativity_consultant_audio_home
    }



    override fun initDataAndEvent() {
        EventBus.getDefault().register(this)
        callEventSave("30", "进入接听界面")

        //状态栏颜色
        setWindowStatusBarColor()
        //点亮屏幕 并解锁
        ConsultantAudioUtils.wakeUpAndUnlock(this)
        //页面传递数据初始化
        getParam()
        //初始化传感器
        initSensorManager()
        initUser()
        initData()
        //获取声网频道号
        getChannelToken()
    }

    private fun setWindowStatusBarColor() {
        StatusBarUtils.setWindowStatusBarColor(this, R.color.audioim_color_40353535)
    }

    private fun getParam() {
        if (null == intent) {
            close(RESULT_NOT_ANSWERED_CODE, "通话异常")
            return
        }
        if (null != intent.getStringExtra(PARAM)) {
            val json = intent.getStringExtra(PARAM)
            if (!TextUtils.isEmpty(json)) {
                writeAgoraLog("收到邀请通话消息内容:$json")
                mAudioMessageBean = Gson().fromJson(json, AudioMessageBean::class.java)

                if (YDLavManager.sdkStatus != Constants.CONNECTION_STATE_CONNECTED) {
                    callEventSave("90", "RMT状态:${YDLavManager.sdkStatus},重新登录RMT")

                    writeAgoraLog("RMT状态:${YDLavManager.sdkStatus},重新登录RMT")
                    val uid =
                        ModularServiceManager.provide(IUserService::class.java).getUserInfo()?.uid
                    YDLavManager.instances.login(uid) { _isSuccess, _msg ->
                        writeAgoraLog("登录RTM的uid=${uid}")
                        val result = if (_isSuccess) "RMT登录成功" else "RMT登录失败:$_msg"
                        writeAgoraLog(result)
                    }
                } else {
                    writeAgoraLog("当前RMT状态:${YDLavManager.sdkStatus}")
                }
            }
        } else {
            callEventSave("90", "通话异常")

            close(RESULT_NOT_ANSWERED_CODE, "通话异常")
            return
        }
    }

    @SuppressLint("InvalidWakeLockTag")
    private fun initSensorManager() {
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager?

        localPowerManager = getSystemService(POWER_SERVICE) as PowerManager?
        localWakeLock = localPowerManager!!.newWakeLock(
            PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK,
            "yidianling"
        )
    }

    /**
     * 初始化界面用户信息
     */
    private fun initUser() {
        var userName = "咨询师"
        if (null != mAudioMessageBean) {
            if (!TextUtils.isEmpty(mAudioMessageBean?.userName)) {
                userName = mAudioMessageBean?.userName!!
            }
            if (!TextUtils.isEmpty(mAudioMessageBean?.userIcon)) {
                var option = SimpleImageOpConfiger()
                option.errorPic = R.drawable.audioim_head_place_hold_pic
                option.loadingPic = R.drawable.audioim_head_place_hold_pic
                option.transform = 0
                YDLImageCacheManager.showImage(this, mAudioMessageBean?.userIcon, iv_head, option)
            } else {
                iv_head.setBackgroundResource(R.drawable.audioim_head_place_hold_pic)
            }
            userId = mAudioMessageBean?.userId?.toInt() ?: -1
        } else {
            iv_head.setBackgroundResource(R.drawable.audioim_head_place_hold_pic)
        }
        tv_name.text = userName
        writeAgoraLog("用户接收电话界面开启")
        callEventSave("90", "用户接收电话界面开启")

    }

    private fun initData() {
        wave_view.setDuration(6000)
        wave_view.setStyle(Paint.Style.STROKE)
        wave_view.setSpeed(1000)
        wave_view.setColor(Color.WHITE)
        wave_view.setInitialRadius(140f)
        wave_view.setInterpolator(AccelerateInterpolator(1.2f))
        //启动背景动画
        wave_view.start()
        mPlayer = AudioPlayer(this, true)
        mPlayer!!.setDataSource(R.raw.audioim_call_music)
        mPlayer!!.start(isLooping = true, isSetOnCompletionListener = false)

        //间接性震动手机
        VibratorUtil.vibrate(AudioHomeActivity@ this, longArrayOf(1000, 1000, 1000, 1000), true)
    }

    /**
     *  //获取声网频道号
     */
    private fun getChannelToken() {
        writeAgoraLog("获取声网token")
        //获取频道token
        mPresenter.getChannelToken(mAudioMessageBean, false)
    }

    override fun channelTokenResponse(token: String?, needJoinChannel: Boolean) {
        if (TextUtils.isEmpty(token)) {
            callEventSave("90", "通话频道不存在")

            LogUtil.e("[agora]token not null")
            AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:token isEmpty channelId:${mAudioMessageBean?.channelId}")

            showToast("通话频道不存在")
            finish()
            return
        }
        this.channelToken = token
        writeAgoraLog("返回的声网token=$channelToken")
        if (needJoinChannel) {
            //权限申请
            requestPermission()
        }
    }

    /**
     * 更新ui
     */
    private fun updateUI() {
        tv_toast.visibility = View.VISIBLE
        tv_toast.text = "正在建立连接..."

        rl_call.visibility = View.GONE
        rl_hands_free.visibility = View.VISIBLE
    }

    //申请音频权限
    @SuppressLint("CheckResult")
    private fun requestPermission() {
        val rxPermissions = RxPermissions(this)
        rxPermissions.requestEach(Manifest.permission.RECORD_AUDIO).subscribe { permission ->
            when {
                //权限已申请 进行初始化操作
                permission.granted -> {
                    init()
                    callEventSave("90", "申请音频权限成功")
                }
                //权限为申请 重新申请
                permission.shouldShowRequestPermissionRationale -> {
                    requestPermission()
                    callEventSave("90", "权限 重新申请")
                }
                //跳转设置界面
                else -> {
                    ToastHelper.show(getString(R.string.audioim_need_storage_permission_hint))

                    val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                    val uri = Uri.fromParts("package", packageName, null)
                    intent.data = uri
                    startActivity(intent)
                    finish()
                }
            }
        }
    }

    private fun init() {
        //初始化语音
        initializeAgoraEngine()
        joinChannel()
    }

    /**
     * 语音通话 初始化
     */
    private fun initializeAgoraEngine() {
        /**
         * 创建一个实例
         * param appId            应用id
         * param mRtcEventHandler 事件回调(SDK 通过指定的事件通知应用程序 SDK 的运行事件,如: 加入或离开频道,新用户加入频道等)
         */
        voiceManage = YDLVoiceManager(this, BuildConfig.AGORA_APPID, mRtcEventHandler)
        voiceManage!!.init()
    }

    /**
     * 加入频道
     */
    private fun joinChannel() {
        val account = YdlCommonRouterManager.getYdlCommonRoute().getUid()
        if (!TextUtils.isEmpty(mAudioMessageBean?.channelId)) {
            callEventSave("40", "加入频道joinChannel:$account")

            LogUtil.e("[agora] joinChannel:$account")
            AliYunRichLogsHelper.getInstance()
                .sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:joinChannel:$account  channelId:${mAudioMessageBean?.channelId}")

            voiceManage?.getVoiceApi()?.joinChannel(
                channelToken
                    ?: "", mAudioMessageBean!!.channelId!!, "Extra Optional Data", account
            )
        }
    }

    override fun executeFinish() {
        callEventSave("51", "对方已挂断")

        showToast("对方已挂断")
        close(RESULT_ANSWERED_CODE, "")
    }

    /**
     * 通话开始后更新ui
     */
    private fun updateStartUi() {
        tv_toast.text = "已接通"
        tv_toast.postDelayed({ tv_toast.visibility = View.GONE }, 500)
        rl_remain_time.visibility = View.VISIBLE


        totalDisposable =
            Observable.interval(0, 1, TimeUnit.SECONDS).subscribeOn(Schedulers.computation())
                .observeOn(AndroidSchedulers.mainThread()).subscribe({
                    tv_remain_time.text = DateUtils.formatTime(it.toString())
                }, {
                    close(RESULT_NOT_ANSWERED_CODE, "对方异常")
                })
    }

    /**
     * 通话结束
     */
    private fun callFinish() {
        status = STATUS_NOT_ANSWERED
    }

    private fun showStopService() {
        if (status == STATUS_NOT_ANSWERED) {
            YDLavManager.instances.callEndStatusUpdate(mAudioMessageBean?.channelId!!, 2, "被叫主动拒绝")
            callEventSave("51", "通话未接通挂断:用户主动挂断")

            writeAgoraLog("通话未接通挂断:用户主动挂断")
            //当未接听 直接挂断 要发送给老师一条消息
            close(RESULT_NOT_ANSWERED_CODE, "用户已挂断")
        } else if (status == STATUS_ANSWERED) {
            callEventSave("51", "通话接通后挂断:专家主动挂断")

            YDLavManager.instances.callEndStatusUpdate(mAudioMessageBean?.channelId!!, 3, "被叫主动拒绝")
            writeAgoraLog("通话接通后挂断:专家主动挂断")
            //正常接听 挂断电话 需要重置信令管理类状态
            close(RESULT_ANSWERED_CODE, "")
        }
    }

    override fun listenStatusPushResponse() {
    }

    /**
     * 挂断
     */
    fun hangUpClick(view: View) {
        if (Utils.isFastClick()) {
            //防止连击
            return
        }
        showStopService()
        callEventSave("52", "用户点击挂断按钮")

        writeAgoraLog("用户点击挂断按钮")
        ActionCountUtils.count(
            "shengwang_popup_layer_page|shengwang_popup_layer_refuse_click",
            YdlCommonRouterManager.getYdlCommonRoute().getUid().toString(),
            uid = YdlCommonRouterManager.getYdlCommonRoute().getUid().toString()
        )
    }

    /**
     * 接听
     */
    fun onCall(view: View) {
        if (Utils.isFastClick()) {
            //防止连击
            return
        }

        //调用接口判断邀请专家的用户当前是否在频道内,如果在,则专家加入频道,如果不在,则提示用户已挂断
        //更改逻辑:现在是专家先进频道,这个接口暂时只作为参考
        //        presenter.userIsInChannel(mAudioMessageBean?.channelId ?: "", mAudioMessageBean?.userId
        //                ?: "")

        executeCall(true)
        callEventSave("90", "用户点击接听按钮")


        ActionCountUtils.count(
            "shengwang_popup_layer_page|shengwang_popup_layer_answer_click",
            YdlCommonRouterManager.getYdlCommonRoute().getUid().toString(),
            uid = YdlCommonRouterManager.getYdlCommonRoute().getUid().toString()
        )
    }

    /**
     * 执行接听操作
     */
    override fun executeCall(canExcute: Boolean) {
        stopPlaying()
        //停止震动
        VibratorUtil.StopVibrate(this)
        if (!canExcute) {
            callEventSave("51", "对方已挂断")

            showToast("对方已挂断")
            finish()
        } else {
            if (null != mAudioMessageBean) {
                updateUI()
                //专家先加入频道,然后再接受用户邀请,保证专家比用户先加入频道
                if (!TextUtils.isEmpty(channelToken)) {
                    //权限申请完成后加入频道
                    requestPermission()
                } else {
                    //获取频道token
                    mPresenter.getChannelToken(mAudioMessageBean)
                }
            }
        }
    }

    /**
     * 打开扬声器 true:开启 false:关闭(听筒)
     */
    fun onSwitchSpeakerphoneClicked(view: View) {
        view.isSelected = !view.isSelected
        if (view.isSelected) {
            //扬声器模式
            iv_hands_free.setImageResource(R.drawable.audioim_img_hands_free)
        } else {
            //听筒模式
            iv_hands_free.setImageResource(R.drawable.audioim_img_hands_free_unuse)
        }
        LogUtil.e("http---------------isSelected=" + !view.isSelected)
        if (null == voiceManage || null == voiceManage!!.getVoiceApi()) {
            return
        }

        voiceManage!!.getVoiceApi().setEnableSpeakerphone(view.isSelected)
    }

    override fun onResume() {
        super.onResume()
        sensorManager!!.registerListener(
            this,
            sensorManager!!.getDefaultSensor(Sensor.TYPE_PROXIMITY),
            SensorManager.SENSOR_DELAY_NORMAL
        )

        ActionCountUtils.count(
            "shengwang_popup_layer_page|shengwang_popup_layer_page_visit",
            "",
            uid = YdlCommonRouterManager.getYdlCommonRoute().getUid().toString()
        )
    }

    override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
    }

    override fun onSensorChanged(event: SensorEvent?) {
        val values = event!!.values
        when (event.sensor.type) {
            Sensor.TYPE_PROXIMITY -> {
                if (values[0] == 0.0f) {
                    //贴近手机
                    if (!localWakeLock!!.isHeld) {
                        localWakeLock!!.acquire()
                    }
                } else {
                    //离开手机
                    //唤醒设备
                    if (localWakeLock!!.isHeld) {
                        localWakeLock!!.release()
                    }
                }
            }
        }
    }

    /**
     * 显示自定义弹窗
     */
    private fun showToast(msg: String?) {
        runOnUiThread {
            ToastHelper.show(msg ?: "")
        }
    }

    /**
     * 网络状态
     */
    private fun showNetStatus(msg: String, status: Int = 0) {
        runOnUiThread {
            if (TextUtils.isEmpty(msg)) {
                tv_nte_status.visibility = View.GONE
            } else {
                tv_nte_status.text = msg
                if (status == 0) {
                    tv_nte_status.setCompoundDrawablesWithIntrinsicBounds(
                        ContextCompat.getDrawable(
                            this,
                            R.drawable.av_audio_wifi_normal
                        ), null, null, null
                    )
                }
                if (status == 1) {
                    tv_nte_status.setCompoundDrawablesWithIntrinsicBounds(
                        ContextCompat.getDrawable(
                            this,
                            R.drawable.av_audio_wifi_better
                        ), null, null, null
                    )
                }
                if (status == -1) {
                    tv_nte_status.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
                }
                tv_nte_status.visibility = View.VISIBLE
            }
        }
    }

    //关闭本页面
    fun close(code: Int, msg: String) {
        runOnUiThread {
            LogUtil.e("[agora]close(code:$code,msg:$msg)")
            AliYunRichLogsHelper.getInstance()
                .sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:close(code:$code,msg:$msg)  channelId:${mAudioMessageBean?.channelId}")

            //上传日志文件
            uploadLog()
            stopMusic()
            //播放结束音频
            playFinishMusic()
            when (code) {
                RESULT_ANSWERED_CODE -> {
                    //已接听,正常挂断
                    //离开频道
                    AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:已接听,正常挂断 channelId:${mAudioMessageBean?.channelId}")

                    leaveChannel()
                }
                RESULT_NOT_ANSWERED_CODE -> {
                    callStatus = 2
                    uploadException("被叫拒绝", zhu = "")
                    //未接听,直接挂断 发送消息
                    //        YDLRTMClient.instances.refuseCall(mAudioMessageBean?.channelId)
                    YDLavManager.instances.refuseCall(
                        mAudioMessageBean!!.userId!!,
                        mAudioMessageBean?.channelId,
                        Gson().toJson(mAudioMessageBean)
                    )
                }
                RESULT_USER_CANCEL -> {
                    callStatus = 1
                    uploadException("主叫取消", zhu = "")
                    showToast("对方已挂断")
                }
            }
            ActivityManager.getInstance().removeStack(activity = this)
            LogUtil.e("[agora]页面移除")
            AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:页面移除 channelId:${mAudioMessageBean?.channelId}")
            finish()
        }
    }

    private fun stopMusic() {
        //停止播放音乐
        stopPlaying()
        //停止震动
        VibratorUtil.StopVibrate(AudioHomeActivity@ this)
    }

    /**
     * 停止播放
     */
    private fun stopPlaying() {
        AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:stopPlaying channelId:${mAudioMessageBean?.channelId}")

        mPlayer?.pause()
    }

    /**
     * 播放结束音频
     */
    private fun playFinishMusic() {
        AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:playFinishMusic channelId:${mAudioMessageBean?.channelId}")

        if (mPlayer == null) {
            mPlayer = AudioPlayer(this, true)
        }
        mPlayer!!.setDataSource(R.raw.audioim_hand_down_music)
        //        mPlayer!!.switchPlayType(true)
        mPlayer!!.start(isLooping = false, isSetOnCompletionListener = false)
    }

    fun onEventMainThread(event: AudioHomeEvent) {
        stopMusic()
    }

    /**
     *连接中状态倒计时:15s后如果还是处于连接中,则直接退出当前页面
     */
    private fun connectingStatusWaitingTimeCount() {
        if (connectingStatusDisposable == null) {
            connectingStatusDisposable =
                Observable.interval(0, 1, TimeUnit.SECONDS).subscribeOn(Schedulers.computation())
                    .take(16).observeOn(AndroidSchedulers.mainThread()).subscribe({}, {}, {
                        if (!isConnectSuccess) {
                            YDLavManager.instances.callEndStatusUpdate(
                                mAudioMessageBean?.channelId!!,
                                1,
                                "被叫加入频道后主叫未加入超时"
                            )
                            AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:15s后如果还是处于连接中,则直接退出当前页面 channelId:${mAudioMessageBean?.channelId}")

                            writeAgoraLog("通话未接通挂断:连接中的状态超过5s自动挂断")
                            showToast("用户已挂断")
                            close(RESULT_NOT_ANSWERED_CODE, "")
                        }
                    })
        }
    }

    /**
     * 离开频道
     */
    private fun leaveChannel() {
        uploadException("", "zhu", "108")
        totalDisposable?.dispose()
        connectingStatusDisposable?.dispose()
        voiceManage?.getVoiceApi()?.leaveChannel()
        voiceManage?.getVoiceApi()?.destroy()
        voiceManage = null
        mPlayer?.clear()
        sensorManager?.unregisterListener(this)
        //唤醒设备
        if (localWakeLock?.isHeld == true) {
            localWakeLock?.release()
        }
        sensorManager = null
        localWakeLock = null
        localPowerManager = null
    }

    private fun voiceDestory() {
        voiceManage?.getVoiceApi()?.destroy()
        voiceManage = null
    }

    /**
     * 重写返回键逻辑:屏蔽返回键
     */
    override fun onBackPressed() {
    }

    private fun writeAgoraLog(content: String) {
        Observable.create<Any> {
            try {
                AudioLogUtils.writeAgoraLog(
                    "$content-------Time:${
                        AudioLogUtils.format.format(
                            Calendar.getInstance().time
                        )
                    }", "consult.log"
                )
            } catch (e: Exception) {
            }
        }.subscribeOn(Schedulers.io()).subscribe()
    }

    fun uploadExceptionStatus(msg: String, status: Int) {
        callStatus = status
        uploadException(msg, zhu = "zhu", eventType = "108")
    }

    /**
     * 上传错误日志
     */
    private fun uploadException(message: String, zhu: String = "", eventType: String = "99") {
        var time: String = (System.currentTimeMillis() / 1000).toString()
        var uid: String =
            ModularServiceManager.provide(IUserService::class.java).getUserInfo()?.uid!!
        var payLoad = PayLoad(mAudioMessageBean?.channelId ?: "0", time, uid, "1", "999", message)
        var connectException =
            ConnectExceptionCommand(time + zhu, "2", eventType, payLoad, callStatus)
        YDLavManager.instances.uploadException(connectException, null)
    }

    private fun uploadLog() {
        if (!hasUpLoadLog) {
            hasUpLoadLog = true
            LogHelper.getInstance().uploadLog(false)
        }
    }

    override fun onDestroy() {
        LogUtil.e("http-------------onDestory")
        AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:onDestroy channelId:${mAudioMessageBean?.channelId}")

        leaveChannel()
        voiceDestory()
        isConnectSuccess = false
        status = STATUS_NOT_ANSWERED
        hasUpLoadLog = false
        EventBus.getDefault().unregister(this)
        if (ActivityManager.getActivitySize() == 1) {
            try {
                //                startActivity(MainActivity.newIntent(this, false))
                ARouter.getInstance().build("/main/main").addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
                    .navigation()
            } catch (e: Exception) {

            }
        }

        super.onDestroy()
    }

    /**
     *  倾诉日志
     * @param session 通话业务id
     * @param status 状态:01通话中(不影响通话的事件) 10:拨打 20未拨通 30未接通 40 接通 50挂断 60断线 70重连 80 呼叫方信号 90 被呼叫方信号
     * @param res 上报的详细
     * @param line 载体:1.网易 2.中国移动(双呼)3.联通 4.华为 5.糖猫-联通 7:声网 8:微信 10:新移动
     * */
    private fun callEventSave(
        status: String,
        res: String,
        session: String? = channelToken,
        line: String = "7"
    ) {
        YDLavManager.instances.callEventSave(status, res, session, line)
    }
}