package com.ydl.audioim

import android.annotation.SuppressLint
import android.content.Context
import android.text.TextUtils
import com.alibaba.android.arouter.launcher.ARouter
import com.google.gson.Gson
import com.ydl.audioim.http.AudioApiRequestUtil
import com.ydl.audioim.http.command.ConnectExceptionCommand
import com.ydl.consultantim.ConsultantAudioHomeActivity
import com.ydl.ydl_av.chat.bean.AudioMessageBean
import com.ydl.ydl_av.messge_service.YDLRTMClient
import com.ydl.ydl_av.messge_service.bean.RTMMesssage
import com.ydl.ydl_av.messge_service.callback.CallListener
import com.ydl.ydl_av.messge_service.callback.InitListener
import com.ydl.ydl_av.messge_service.callback.LoginCallback
import com.ydl.ydl_av.messge_service.request.LoginParam
import com.ydl.ydl_av.messge_service.response.CallLocalResponse
import com.ydl.ydl_av.messge_service.response.CallRemoteResponse
import com.ydl.ydlcommon.modular.ModularServiceManager
import com.ydl.ydlcommon.utils.ActivityManager
import com.ydl.ydlcommon.utils.LogUtil
import com.ydl.ydlcommon.utils.log.LogHelper
import com.yidianling.common.tools.ToastUtil
import com.yidianling.user.api.service.IUserService
import io.agora.rtm.RtmStatusCode
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import java.util.concurrent.TimeUnit

/**
 * @author harvie
 * @date 2019/9/27
 * 语音通话入口类
 */
class YDLavManager {


    companion object {
        val instances: YDLavManager by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            YDLavManager()
        }
    }

    private constructor()

    fun init(context: Context, appId: String) {
        YDLRTMClient.instances.init(context, appId, listener)
        //设置回调
        setCallback()
    }


    private fun setCallback() {
        YDLRTMClient.instances.setCallListener(object : CallListener {
            override fun onCallRecivedByPeer(response: CallLocalResponse?) {
                //返回给主叫：被叫已收到呼叫邀请
                LogUtil.e("[agora]${response?.calleeId}已收到呼叫邀请，频道号${response?.ChannelId}")

                val act = ActivityManager.getInstance().getTopTaskActivity()
                if (act is AudioHomeActivity) {
                    act.runOnUiThread {
                        act.playWaitingMusic()
                    }
                }

            }

            override fun onCallAccepted(response: CallLocalResponse?, msg: String?) {
                //返回给主叫
                LogUtil.e("[agora]${response?.calleeId}已接收呼叫邀请")

                //加入声网频道时机修改：用户收到专家接受邀请的回调后再加入声网频道
                val act = ActivityManager.getInstance().getTopTaskActivity()
                if (act is AudioHomeActivity) {
                    act.runOnUiThread {
                        act.joinChannel()
                    }
                }
            }

            override fun onCallRefused(response: CallLocalResponse?, msg: String?) {
                //返回给主叫
                LogUtil.e("[agora]${response?.calleeId}已拒绝呼叫邀请")

                val act = ActivityManager.getInstance().getTopTaskActivity()
                if (act is AudioHomeActivity) {
                    act.runOnUiThread {
                        ToastUtil.toastShort("对方已挂断")
                        //通话结束或挂断时，上传日志文件
                        act.uploadLog()
                        act.leaveChannel()
                    }
                }


            }

            override fun onCallCanceled(response: CallLocalResponse?) {
                //返回给主叫
                LogUtil.e("[agora]主叫已取消呼叫邀请")
            }

            override fun onCallFailure(response: CallLocalResponse?, errorCode: Int) {
                //返回给主叫
                LogUtil.e("[agora]呼叫${response?.calleeId}用户失败：${response?.response}")
                //专家离线或者30 秒后仍未收到专家响应，重新再邀请一次
                when (errorCode) {
                    //被叫不在线   呼叫邀请发出 30 秒后被叫仍未 ACK 响应呼叫邀请
                    RtmStatusCode.LocalInvitationError.LOCAL_INVITATION_ERR_PEER_OFFLINE,
                    RtmStatusCode.LocalInvitationError.LOCAL_INVITATION_ERR_PEER_NO_RESPONSE -> {
                        val act = ActivityManager.getInstance().getTopTaskActivity()
                        if (act is AudioHomeActivity) {
                            act.runOnUiThread {
                                act.rtcCall()
                            }
                        }
                    }
                    RtmStatusCode.LocalInvitationError.LOCAL_INVITATION_ERR_INVITATION_EXPIRE -> {//呼叫邀请过期。被叫 ACK 响应呼叫邀请后 60 秒呼叫邀请未被取消、接受、拒绝，则呼叫邀请过期。

                    }
                }
            }

            override fun onRemoteInvitationReceived(response: CallRemoteResponse?) {
                //返回给被叫
                LogUtil.e("[agora]收到来自${response?.callerId}的呼叫邀请")
                receivedCall(response?.content)
            }

            override fun onRemoteInvitationAccepted(response: CallRemoteResponse?) {
                //返回给被叫
                LogUtil.e("[agora]接受来自${response?.callerId}的呼叫成功")
            }

            override fun onRemoteInvitationRefused(response: CallRemoteResponse?) {
                //返回给被叫
                LogUtil.e("[agora]已拒绝来自${response?.callerId}的呼叫")
            }

            override fun onRemoteInvitationCanceled(response: CallRemoteResponse?) {
                //返回给被叫
                LogUtil.e("[agora]主叫${response?.callerId}已取消呼叫邀请")
                closePage()
            }

            override fun onRemoteInvitationFailure(response: CallRemoteResponse?, errorCode: Int) {
                //返回给被叫
                LogUtil.e("[agora]来自主叫${response?.callerId}的呼叫邀请进程失败:${response?.response}")
                //关闭页面
                closePage()
            }

            override fun onOtherMsg(error: String?) {
                LogUtil.e("[agora]其它消息：${error}")
            }
        })
    }

    @SuppressLint("CheckResult")
    fun login(userId: String?) {
        if (TextUtils.isEmpty(userId) || userId ?: "0" <= "0") {
            //如果uid为空或小于等于0 ，则不进行登录，因为uid为0也会登录成功，会导致后面uid正确时无法登录
            LogUtil.e("[agora]login-uid:$userId")
            return
        }
        //登录实时消息
        //获取token
        AudioApiRequestUtil.getAgoraToken()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({
                if ("200".equals(it.code)) {
                    YDLRTMClient.instances.login(LoginParam(userId, it.data.token),
                        object : LoginCallback {
                            override fun onSuccess() {
                                //登陆成功，发起呼叫
                                LogUtil.e("[agora]实时消息登录成功")
                            }

                            override fun onFailure(msg: String?) {
                                LogUtil.e("[agora]实时消息登录失败：$msg")
                            }

                        })
                } else {
                    LogUtil.e("声网token获取失败uid:" + userId + " error:" + it.msg)
                    LogHelper.getInstance()
                        .writeLogSync("声网token获取失败uid:" + userId + " error:" + it.msg)
                }
            }, {
                LogUtil.e("声网token获取异常uid:" + userId + " error:" + it.message)
            })
    }


    /**
     * 收到邀请
     */
    @SuppressLint("CheckResult")
    fun receivedCall(content: String?) {
        if (!TextUtils.isEmpty(content)) {
            //如果已经接听了用户电话 再有电话进来 是不能接听的
            if (!activityIsExists(ConsultantAudioHomeActivity::class.java) && !activityIsExists(
                    AudioHomeActivity::class.java
                )
            ) {
                //延时启动通话界面，防止刚打开就被main遮挡
                Observable.timer(1000, TimeUnit.MILLISECONDS).subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe {
                        LogUtil.e("[agora]启动通话界面")
                        //邀请加入频道消息，跳转通话界面
                        ARouter.getInstance().build("/av/ConsultantAudioHomeActivity")
                            .withString("param", content)
                            .navigation()
                    }
            } else {
                try {
                    val mAudioMessageBean = Gson().fromJson(content, AudioMessageBean::class.java)
                    YDLRTMClient.instances.refuseCall(mAudioMessageBean.channelId)
                } catch (e: Exception) {

                }
                LogUtil.d("[agora]收到声网邀请，但界面实例已存在")
            }
        } else {
            LogUtil.d("[agora]收到声网邀请，但response==null")
        }
    }


    private fun activityIsExists(cls: Class<*>): Boolean {
        for (activity in ActivityManager.getInstance().getActivitys()) {
            if (activity.javaClass == cls) {
                return true
            }
        }
        return false
    }


    /**
     * 关闭通话界面
     */
    fun closePage() {
        var act = ActivityManager.getInstance().getTopTaskActivity()
        if (act is ConsultantAudioHomeActivity) {
            //未接通时，收到呼叫进程失败关闭页面，已接通无需关闭
            if (act.status == ConsultantAudioHomeActivity.STATUS_NOT_ANSWERED) {
                act.close(ConsultantAudioHomeActivity.RESULT_USER_CANCEL, "")
            }
        }
    }


    /**
     * 退出登录
     */
    fun logout() {
        YDLRTMClient.instances.logout(object : LoginCallback {
            override fun onSuccess() {
                //退出登陆成功
                LogUtil.d("[agora]实时消息退出成功")
            }

            override fun onFailure(msg: String?) {
                LogUtil.d("[agora]实时消息退出失败：$msg")
            }

        })
    }

    /**
     * RTM登录异常，上传错误日志 msg
     * 声网出现异常，上传错误日志 connectException
     */
    @SuppressLint("CheckResult")
    fun uploadException(connectException: ConnectExceptionCommand) {
        AudioApiRequestUtil.connectException(connectException)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())

            .subscribe({
            }, {
                LogUtil.e("agora", "声网上传异常与错误日志接口调用失败:" + it.message)
            })
    }

    /**
     * 实时消息全局监听
     */
    private val listener = object : InitListener {

        override fun onTokenExpired() {
            LogUtil.e("[agora]onTokenExpired")
            instances.login(ModularServiceManager.provide(IUserService::class.java).getUserInfo()?.uid)
        }

        override fun onMessageReceived(message: RTMMesssage, userId: Int) {
            LogUtil.i("[agora]onMessageReceived:${message.text} -->uid:$userId")
        }

        override fun onConnectionStateChanged(state: Int, reason: Int) {
            LogUtil.i("[agora]onConnectionStateChanged:state:${state} -->reason:$reason")
        }

    }
}