package com.yidianling.im.helper

import android.util.Log
import com.netease.nimlib.sdk.NIMClient
import com.netease.nimlib.sdk.Observer
import com.netease.nimlib.sdk.RequestCallback
import com.netease.nimlib.sdk.StatusCode
import com.netease.nimlib.sdk.auth.AuthServiceObserver
import com.netease.nimlib.sdk.avchat.model.AVChatAttachment
import com.netease.nimlib.sdk.msg.MsgService
import com.netease.nimlib.sdk.msg.MsgServiceObserve
import com.netease.nimlib.sdk.msg.constant.AttachStatusEnum
import com.netease.nimlib.sdk.msg.constant.MsgDirectionEnum
import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum
import com.netease.nimlib.sdk.msg.model.CustomNotification
import com.netease.nimlib.sdk.msg.model.IMMessage
import com.netease.nimlib.sdk.msg.model.RevokeMsgNotification
import com.netease.nimlib.sdk.team.TeamServiceObserver
import com.netease.nimlib.sdk.team.model.Team
import com.ydl.ydlcommon.base.BaseApp
import com.ydl.ydlcommon.utils.LogUtil
import com.yidianling.im.api.bean.IMRegisterObserverCustomNotificationCallBack
import com.yidianling.im.api.event.AccountChangeEvent
import com.yidianling.im.api.event.MsgPushEvent
import com.yidianling.im.event.TeamRemoveEvent
import com.yidianling.im.preference.IMCache
import com.yidianling.im.preference.ImTempData
import com.yidianling.im.session.extension.CustomAttachReceivedMoney
import com.yidianling.im.session.extension.CustomAttachRedPacket
import com.yidianling.im.session.extension.CustomAttachmentReceivedSuccess
import com.yidianling.nimbase.api.model.session.MsgForwardFilter
import com.yidianling.nimbase.api.model.session.MsgRevokeFilter
import com.yidianling.uikit.api.NimUIKit
import com.yidianling.uikit.api.wrapper.NimMessageRevokeObserver
import com.yidianling.uikit.business.session.helper.MessageListPanelHelper
import com.yidianling.uikit.business.team.helper.TeamMemberAitHelper
import de.greenrobot.event.EventBus
import java.util.concurrent.Executors

/**
 * Created by haorui on 2019/5/17.
 * Des:
 */
class ImObserversHelper {
    internal val imCustomNotificationCallBack: MutableList<IMRegisterObserverCustomNotificationCallBack> = arrayListOf()

    companion object {
        fun getInstance(): ImObserversHelper {
            return Holder.INSTANCE
        }
    }


    private object Holder {
        val INSTANCE = ImObserversHelper()
    }


    fun registerObserver(register: Boolean) {
        //注册`在线状态变化`观察者
        NIMClient.getService(AuthServiceObserver::class.java).observeOnlineStatus(userStatusObserver, register)
        //注册`消息撤回`观察者
        NIMClient.getService(MsgServiceObserve::class.java).observeRevokeMessage(messageRevokeObserver, register)
        //注册`消息接收`观察者
        NIMClient.getService(MsgServiceObserve::class.java).observeReceiveMessage(incomingMessageObserver, register)
        //注册`移出群`观察者通知
        NIMClient.getService(TeamServiceObserver::class.java).observeTeamRemove(teamObserver, register)
        NIMClient.getService(MsgServiceObserve::class.java).observeCustomNotification(receiveSystemMessageObserver, register)
        //注册`未读消息改变数量`观察者
        registerMsgUnreadInfoObserver(register)
        if (register) {
            //注册`消息转发`过滤器
            NimUIKit.setMsgForwardFilter(msgForwardFilter)
            //注册`消息撤回`过滤器
            NimUIKit.setMsgRevokeFilter(msgRevokeFilter)
        }
    }

    private fun registerMsgUnreadInfoObserver(register: Boolean) {
        if (register) {
            ReminderManager.getInstance().registerUnreadNumChangedCallback(unreadNumChangedCallback)
        } else {
            ReminderManager.getInstance().unregisterUnreadNumChangedCallback(unreadNumChangedCallback)
        }
    }

    private var unreadNumChangedCallback: ReminderManager.UnreadNumChangedCallback = ReminderManager.UnreadNumChangedCallback() {
        MsgReceiveHelper.onMessageReceived()
    }

    private var userStatusObserver: Observer<StatusCode> = Observer { code ->
        if (code.wontAutoLoginForever()) {
            EventBus.getDefault().post(AccountChangeEvent(1))
        }
        if (code == StatusCode.LOGINED) {
            NimUICallInit.initNim2(BaseApp.getApp())
        }
    }

    private var messageRevokeObserver: Observer<RevokeMsgNotification> = NimMessageRevokeObserver()

    private var teamObserver: Observer<Team> = Observer<Team> { t ->
        EventBus.getDefault().post(TeamRemoveEvent(1, t.id))
    }

    private var incomingMessageObserver = Observer<List<IMMessage>> { messages ->
        // 处理新收到的消息，为了上传处理方便，SDK 保证参数 messages 全部来自同一个聊天对象。
        Log.e("hzs", "消息接收观察者-----------mainActivity")
        if (messages == null || messages.isEmpty()) {
            return@Observer
        }
        if (messages.size > 1) {
            //漫游消息 nothing
        } else {
            //单/群聊消息
            for (m in messages) {
                //监听在线消息中是否有@我
                if (TeamMemberAitHelper.isAitMessage(m)) {
                    //缓存@消息
                    ImTempData.getInstance().addAitMsg(m)
                }
                if (CustomAttachmentReceivedSuccess::class.java.isInstance(m.getAttachment())) {
                    //如果是收款提醒消息  则更新历史收款消息的状态
                    //收款成功
                    flushReceivedMoney(m)
                } else {
                    MsgReceiveHelper.onMessageReceived()

                    if (System.currentTimeMillis() - m.time <= 5000) {
                        Executors.newSingleThreadExecutor().execute {
                            val userInfo = NimUIKit.getUserInfoProvider().getUserInfo(m.fromAccount)
                            val event = MsgPushEvent()
                            event.toUid = m.fromAccount
                            when (m.msgType) {
                                MsgTypeEnum.text -> {
                                    event.content = m.content
                                }
                                MsgTypeEnum.image -> {
                                    event.content = "[图片]"
                                }
                                MsgTypeEnum.audio -> {
                                    event.content = "[语音]"
                                }
                                MsgTypeEnum.video -> {
                                    event.content = "[视频]"
                                }
                                else -> {
                                    event.content = "[链接]"
                                }
                            }
                            if (userInfo != null) {
                                event.name = userInfo.name
                                event.headUrl = userInfo.avatar
                            }

                            //                            LogUtil.e("发送事件：$event")
                            EventBus.getDefault().post(event)
                        }
                    }
                }
            }
        }
    }

    private var msgForwardFilter = MsgForwardFilter { message ->
        if (message.direct == MsgDirectionEnum.In && (message.attachStatus == AttachStatusEnum.transferring || message.attachStatus == AttachStatusEnum.fail)) {
            // 接收到的消息，附件没有下载成功，不允许转发
            return@MsgForwardFilter true
        } else if (message.msgType == MsgTypeEnum.custom && message.attachment != null) {
            // 白板消息和阅后即焚消息 不允许转发
            return@MsgForwardFilter true
        }
        false
    }

    private var receiveSystemMessageObserver: Observer<CustomNotification> = Observer<CustomNotification> { notification ->
        LogUtil.e(notification.content)
        imCustomNotificationCallBack.forEach { it.onObserverCustomNotification(notification.fromAccount, notification.sessionId, notification.content) }
    }

    private var msgRevokeFilter = MsgRevokeFilter { message ->
        if (message.attachment != null && message.attachment is AVChatAttachment && message.attachment is CustomAttachRedPacket) {
            // 视频通话消息和白板消息 不允许撤回
            return@MsgRevokeFilter true
        } else if (IMCache.getAccount() != null && IMCache.getAccount() == message.sessionId) {
            // 发给我的电脑 不允许撤回
            return@MsgRevokeFilter true
        }
        false
    }

    //如果是收款提醒消息  则更新历史收款消息的状态
    fun flushReceivedMoney(m: IMMessage) {
        //跟新收款消息
        NIMClient.getService(MsgService::class.java).queryMessageListByType(MsgTypeEnum.custom, m, 100).setCallback(object : RequestCallback<List<IMMessage>> {
            override fun onSuccess(imMessages: List<IMMessage>) {
                for (im in imMessages) {
                    if (im.attachment is CustomAttachReceivedMoney) {
                        val money = im.attachment as CustomAttachReceivedMoney

                        if (money.orPay == 1) return
                        val status = m.attachment as CustomAttachmentReceivedSuccess
                        if (money.orderId == null || status.orderid == null) return
                        if (money.orderId == status.orderid) {

                            money.orPay = 1 //设置为已支付
                            im.attachment = money
                            //更新此消息到sdk
                            NIMClient.getService(MsgService::class.java).updateIMMessageStatus(im)
                            //更新私聊界面聊天信息
                            MessageListPanelHelper.getInstance().notifyModifyMessage(im)
                            return
                        }
                    }
                }
            }

            override fun onFailed(i: Int) {
                //                Log.e("hzs","跟新收款消息失败");
            }

            override fun onException(throwable: Throwable) {
                //                Log.e("hzs","跟新收款消息异常："+throwable);
            }
        })
    }
}
