package com.renrenliao.im.im

import com.renrenliao.im.bean.UserInfo
import com.renrenliao.im.http.checkSuccess
import com.renrenliao.im.model.repository.LocalDataSource
import com.renrenliao.im.model.repository.RemoteDataSource
import com.renrenliao.im.utils.DataCacheUtils
import com.renrenliao.im.utils.LogUtils
import com.renrenliao.im.utils.StringUtils
import kotlinx.coroutines.*
import net.openmob.mobileimsdk.android.ClientCoreSDK
import net.openmob.mobileimsdk.android.event.IMEvent
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject

/**
 **@ClassName ChatBaseEventListener
 **@Description
 **@Author gan
 **@Date 2022/6/16 14:37
 * 与IM服务器的底层连接事件在此ChatBaseEvent子类中实现即可。
 * <p>
 * 本类是MobileIMSDK的基础通信消息的回调事件接口实现类（将接收如：登陆成功事件 通知、掉线事件通知等）。
 *  数据接收都在子线程 UDP_DATA_RECIVER_TASK中
 **/
class IMEventListener : IMEvent, KoinComponent {

    //注入RemoteDataSource单例
    val remoteDataSource by inject<RemoteDataSource>()

    //LocalDataSource单例
    val localDataSource by inject<LocalDataSource>()


    /**
     * * 与MobileIMSDK框架服务端的通信断开的回调事件通知。
     * <p>
     * 该消息只有在客户端连接服务器成功之后网络异常中断之时触发。 导致与与服务端的通信断开的原
     * 因有（但不限于）：无线网络信号不稳定、WiFi与2G/3G/4G等同开情 况下的网络切换、手机系统的省电策略等。
     *
     *@param dwErrorCode 本回调参数表示表示连接断开的原因，目前错误码没有太多意义，仅作保留字段，目前通常为-1
     */
    @OptIn(DelicateCoroutinesApi::class)
    override fun onLinkClose(dwErrorCode: Int) {
        LogUtils.info("IM服务器连接已断开，error：$dwErrorCode")

        // 通知全局网络状态livedata  离线
        LocalDataSource.networkStatusLiveData.postValue(ClientCoreSDK.IM_STATE_OFFLINE)
        //设置所有好友为离线状态
        GlobalScope.launch(Dispatchers.IO) {
            localDataSource.setAllFriendsOffline()
        }
    }

    /**
     * 连接中
     */
    override fun onLinKing(paramInt: Int) {
        LogUtils.error("连接中... $paramInt")
        // 通知全局网络状态livedata  连接中
        LocalDataSource.networkStatusLiveData.postValue(ClientCoreSDK.IM_STATE_CONNECTING)

    }

    /**
     * 本地用户的MobileIMSDK框架登陆/重连结果回调事件通知。
     *
     * @param dwErrorCode 服务端反馈的登录结果：0 表示登陆/重连成功，否则为服务端自定义的出错代码（按照约定通常为>=1025的数）
     */
    //num 置  1 防止重连后 一直加1
    @OptIn(DelicateCoroutinesApi::class)
    override fun onLoginResponse(dwErrorCode: Int, fp: String?) {
        LogUtils.error("IM服务器连接成功！服务端响应码=$dwErrorCode fp= $fp")
        // 通知全局网络状态livedata  已连接
        LocalDataSource.networkStatusLiveData.postValue(ClientCoreSDK.IM_STATE_ONLINE)
        //获取未读加好友请求数（包括好友发请求时我不在线的情况），并尝试在首页“消息”里放入一条验证消息的表格item
        GlobalScope.launch(Dispatchers.Main) {
            val result = withContext(Dispatchers.IO) {
                remoteDataSource.getOfflineFriend()
            }
            result.checkSuccess {users ->
                LogUtils.error("好友请求加好友 $users")
                users.forEach {
                    withContext(Dispatchers.IO){
                        val alarmEntity = AlarmHelper.createAddFriendAlarm(it)
                        //保存在数据库中
                        localDataSource.insertAlarm(alarmEntity)
                        //更新头像版本
                        val newVersion = StringUtils.getAvatarVersion(it.userAvatarFileName)
                        localDataSource.updateAvatarVersion(account_uid = DataCacheUtils.getUid(), uid = it.userUid,newVersion=newVersion)
                    }
                }

            }
        }
    }


    /**
     * 消息未送达的回调事件
     * 发生场景：比如用户刚发完消息但网络已经断掉了的情况下，表现形式：就像手机qq或微信一样
     * 消息气泡边上会出现红色图标以示没有发送成功）.
     * @param lostMessages
     */
    @OptIn(DelicateCoroutinesApi::class)
    override fun messagesLost(lostMessages: List<ImMsgBean>) {
        LogUtils.error("收到系统的未实时送达消息通知，当前共有 ${lostMessages.size} 个消息未发送" )
        //播放一个消息丢失的声音

        //更新消息状态为发送失败
        GlobalScope.launch(Dispatchers.IO) {
            lostMessages.forEach {
                localDataSource.updateSendStatus(
                    sendStatus = ImMsgBean.SendStatus.sendFaild,
                    fp = it.fp
                )
            }
        }
    }

    /**
     *消息已被对方收到的回调事件
     * @param fingerPrint
     */
    @OptIn(DelicateCoroutinesApi::class)
    override fun messagesReceived(fingerPrint: String) {
        LogUtils.error("消息已经被用户收到--------$fingerPrint")
        //将数据库中的消息发送状态更新为 已接收
        GlobalScope.launch(Dispatchers.IO) {
            localDataSource.updateSendStatus(
                sendStatus = ImMsgBean.SendStatus.beReceived,
                fp = fingerPrint
            )
        }
    }

    /**
     * 好友上线通知事件
     * @param uid
     */
    @OptIn(DelicateCoroutinesApi::class)
    override fun FriendOnline(uid: String) {
        LogUtils.error("好友上线:$uid")
        //设置好友数据库中的状态为上线 1
        GlobalScope.launch(Dispatchers.IO) {
            localDataSource.setFriendLiveStatus(liveStatus = 1, uid = uid)
        }
    }

    /**
     * 好友下线通知事件
     * @param uid
     */
    @OptIn(DelicateCoroutinesApi::class)
    override fun FriendOffline(uid: String) {
        LogUtils.error("好友下线:$uid")
        //设置好友数据库中的状态为上线 0
        GlobalScope.launch(Dispatchers.IO) {
            localDataSource.setFriendLiveStatus(liveStatus = 0, uid = uid)
        }
    }

    //num + 1  累加
    @OptIn(DelicateCoroutinesApi::class)
    override fun FriendAddReq(imMsgBean: ImMsgBean) {

        LogUtils.error("收到好友添加请求 $imMsgBean")
        //展示一个通知  fid 发起好友请求那个人的userId

        GlobalScope.launch(Dispatchers.IO){
            //首页的表中添加或者更新
            val userInfo = UserInfo()
            userInfo.userUid = imMsgBean.fid.toString()
            userInfo.buddyRemark = imMsgBean.name
            userInfo.gId = imMsgBean.gId
            //本地alarm
            val localAlarm = localDataSource.getAlarm(userInfo.gId.toString(),AlarmType.ADDFRIENDREQUEST.value)
            val alarmEntity = AlarmHelper.createAddFriendAlarm(userInfo)
            if (localAlarm !=null){
                alarmEntity.num = localAlarm.num + 1
            }
            //保存在数据库中
            localDataSource.insertAlarm(alarmEntity)

            //更新头像
            if (imMsgBean.avatar !=null){
                val account_uid = DataCacheUtils.getUid()
                val uid = imMsgBean.fid.toString()
                val newVersion = imMsgBean.avatar?.toLong()
                localDataSource.updateAvatarVersion(account_uid,uid,newVersion!!)
            }
        }
    }


}