package com.adealink.weparty.im.session.adapter

import android.view.View
import androidx.recyclerview.widget.RecyclerView
import com.adealink.weparty.commonui.recycleview.adapter.ExtMultiTypeAdapter
import com.adealink.weparty.im.constant.SUPPORT_MESSAGE_TYPES
import com.adealink.weparty.im.session.adapter.data.UnSupportMessageBean
import com.adealink.weparty.im.session.adapter.viewbinder.CallingMessageViewBinder
import com.adealink.weparty.im.session.adapter.viewbinder.ImageMessageViewBinder
import com.adealink.weparty.im.session.adapter.viewbinder.InVisibleMessageViewBinder
import com.adealink.weparty.im.session.adapter.viewbinder.OfficialImageTextMessageViewBinder
import com.adealink.weparty.im.session.adapter.viewbinder.OnPlaymateOrderMessageClickListener
import com.adealink.weparty.im.session.adapter.viewbinder.PlaymateOrderMessageViewBinder
import com.adealink.weparty.im.session.adapter.viewbinder.PlaymateSayWelcomeTextMessageViewBinder
import com.adealink.weparty.im.session.adapter.viewbinder.PlaymateSayWelcomeVoiceMessageViewBinder
import com.adealink.weparty.im.session.adapter.viewbinder.SoundMessageViewBinder
import com.adealink.weparty.im.session.adapter.viewbinder.TextMessageViewBinder
import com.adealink.weparty.im.session.adapter.viewbinder.TipsMessageViewBinder
import com.adealink.weparty.im.session.adapter.viewbinder.UnSupportMessageViewBinder
import com.adealink.weparty.im.session.mesasge.InVisibleMessageBean
import com.adealink.weparty.im.session.mesasge.OfficialImageTextMessageBean
import com.adealink.weparty.im.session.mesasge.PlaymateOrderMessageBean
import com.adealink.weparty.im.session.mesasge.PlaymateSayWelcomeTextMessageBean
import com.adealink.weparty.im.session.mesasge.PlaymateSayWelcomeVoiceMessageBean
import com.adealink.weparty.im.session.widget.MessageRecyclerView
import com.adealink.weparty.module.order.data.OrderDetailInfo
import com.tencent.qcloud.tuikit.timcommon.bean.TUIMessageBean
import com.tencent.qcloud.tuikit.timcommon.component.highlight.HighlightPresenter
import com.tencent.qcloud.tuikit.timcommon.interfaces.ICommonMessageAdapter
import com.tencent.qcloud.tuikit.timcommon.interfaces.OnItemClickListener
import com.tencent.qcloud.tuikit.timcommon.interfaces.UserFaceUrlCache
import com.tencent.qcloud.tuikit.timcommon.minimalistui.widget.message.MessageBaseHolder
import com.tencent.qcloud.tuikit.tuichat.bean.message.CallingMessageBean
import com.tencent.qcloud.tuikit.tuichat.bean.message.ImageMessageBean
import com.tencent.qcloud.tuikit.tuichat.bean.message.SoundMessageBean
import com.tencent.qcloud.tuikit.tuichat.bean.message.TextMessageBean
import com.tencent.qcloud.tuikit.tuichat.bean.message.TipsMessageBean
import com.tencent.qcloud.tuikit.tuichat.interfaces.IMessageAdapter
import com.tencent.qcloud.tuikit.tuichat.interfaces.IMessageRecyclerView
import java.util.LinkedList

class SessionAdapter : ExtMultiTypeAdapter(),
    IMessageAdapter,
    ICommonMessageAdapter {

    companion object {
        private const val ITEM_POSITION_UNKNOWN: Int = -1
    }

    private var mLoading: Boolean = true
    private var mRecycleView: MessageRecyclerView? = null

    private var onItemClickListener: OnItemClickListener? = null

    fun setOnItemClickListener(listener: OnItemClickListener?) {
        this.onItemClickListener = listener
    }

    private val onMessageItemClick = object : OnItemClickListener() {
        override fun onMessageLongClick(view: View?, messageBean: TUIMessageBean?) {
            view ?: return
            messageBean ?: return
            onItemClickListener?.onMessageLongClick(view, messageBean)
        }

        override fun onMessageClick(view: View?, messageBean: TUIMessageBean?) {
            view ?: return
            messageBean ?: return
            onItemClickListener?.onMessageClick(view, messageBean)
        }

        override fun onUserIconClick(view: View?, messageBean: TUIMessageBean?) {
            view ?: return
            messageBean ?: return
            onItemClickListener?.onUserIconClick(view, messageBean)
        }

        override fun onUserIconLongClick(view: View?, messageBean: TUIMessageBean?) {
            view ?: return
            messageBean ?: return
            onItemClickListener?.onUserIconLongClick(view, messageBean)
        }

        override fun onReEditRevokeMessage(view: View?, messageBean: TUIMessageBean?) {
            view ?: return
            messageBean ?: return
            onItemClickListener?.onReEditRevokeMessage(view, messageBean)
        }

        override fun onRecallClick(view: View?, messageBean: TUIMessageBean?) {
            view ?: return
            messageBean ?: return
            onItemClickListener?.onRecallClick(view, messageBean)
        }

        override fun onReplyMessageClick(view: View?, messageBean: TUIMessageBean?) {
            view ?: return
            messageBean ?: return
            onItemClickListener?.onReplyMessageClick(view, messageBean)
        }

        override fun onReplyDetailClick(messageBean: TUIMessageBean?) {
            messageBean ?: return
            onItemClickListener?.onReplyDetailClick(messageBean)
        }

        override fun onSendFailBtnClick(view: View?, messageBean: TUIMessageBean?) {
            view ?: return
            messageBean ?: return
            onItemClickListener?.onSendFailBtnClick(view, messageBean)
        }

        override fun onTextSelected(view: View?, position: Int, messageBean: TUIMessageBean?) {
            view ?: return
            messageBean ?: return
            onItemClickListener?.onTextSelected(view, position, messageBean)
        }

        override fun onMessageReadStatusClick(view: View?, messageBean: TUIMessageBean?) {
            view ?: return
            messageBean ?: return
            onItemClickListener?.onMessageReadStatusClick(view, messageBean)
        }
    }


    private var onPlaymateOrderClickListener: OnPlaymateOrderMessageClickListener? = null

    fun setOnPlaymateOrderClickListener(listener: OnPlaymateOrderMessageClickListener?) {
        this.onPlaymateOrderClickListener = listener
    }

    private val onPlaymateOrderClick = object : OnPlaymateOrderMessageClickListener {
        override fun onPlaymateStartService(data: OrderDetailInfo) {
            onPlaymateOrderClickListener?.onPlaymateStartService(data)
        }

        override fun onPlaymateCompleteService(data: OrderDetailInfo) {
            onPlaymateOrderClickListener?.onPlaymateCompleteService(data)
        }
    }

    init {
        //官方消息
        register(
            OfficialImageTextMessageBean::class.java,
            OfficialImageTextMessageViewBinder(onMessageItemClick)
        )
        //普通消息
        register(TextMessageBean::class.java, TextMessageViewBinder(onMessageItemClick))
        register(ImageMessageBean::class.java, ImageMessageViewBinder(onMessageItemClick))
        register(SoundMessageBean::class.java, SoundMessageViewBinder(onMessageItemClick))
        register(TipsMessageBean::class.java, TipsMessageViewBinder(onMessageItemClick))
        register(UnSupportMessageBean::class.java, UnSupportMessageViewBinder(onMessageItemClick))
        register(CallingMessageBean::class.java, CallingMessageViewBinder(onMessageItemClick))

        //陪玩订单
        register(
            PlaymateOrderMessageBean::class.java,
            PlaymateOrderMessageViewBinder(onMessageItemClick, onPlaymateOrderClick)
        )
        //陪玩打招呼
        register(
            PlaymateSayWelcomeTextMessageBean::class.java,
            PlaymateSayWelcomeTextMessageViewBinder(onMessageItemClick)
        )
        register(
            PlaymateSayWelcomeVoiceMessageBean::class.java,
            PlaymateSayWelcomeVoiceMessageViewBinder(onMessageItemClick)
        )

        //不可见隐藏消息
        register(
            InVisibleMessageBean::class.java,
            InVisibleMessageViewBinder()
        )

//        addMessageType(FaceMessageBean::class.java, FaceMessageHolder::class.java)
//        addMessageType(FileMessageBean::class.java, FileMessageHolder::class.java)
//        addMessageType(LocationMessageBean::class.java, LocationMessageHolder::class.java)
//        addMessageType(MergeMessageBean::class.java, MergeMessageHolder::class.java)
//        addMessageType(TextAtMessageBean::class.java, TextMessageHolder::class.java)
//        addMessageType(VideoMessageBean::class.java, VideoMessageHolder::class.java)
//        addMessageType(ReplyMessageBean::class.java, ReplyMessageHolder::class.java)
//        addMessageType(QuoteMessageBean::class.java, QuoteMessageHolder::class.java)
//        addMessageType(CallingMessageBean::class.java, CallingMessageHolder::class.java)
//        addMessageType(CallingTipsMessageBean::class.java, TipsMessageHolder::class.java, true)
//        addMessageType(CustomLinkMessageBean::class.java, CustomLinkMessageHolder::class.java)
//        addMessageType(
//            CustomEvaluationMessageBean::class.java,
//            CustomEvaluationMessageHolder::class.java
//        )
//        addMessageType(CustomOrderMessageBean::class.java, CustomOrderMessageHolder::class.java)
//        addMessageType(MessageTypingBean::class.java, null)
//        addMessageType(EmptyMessageBean::class.java, EmptyMessageHolder::class.java, true)
//        addMessageType(ChatbotMessageBean::class.java, ChatbotMessageHolder::class.java)
//        addMessageType(
//            ChatbotPlaceholderMessageBean::class.java,
//            ChatbotPlaceholderMessageHolder::class.java
//        )
    }

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        super.onAttachedToRecyclerView(recyclerView)
        mRecycleView = recyclerView as MessageRecyclerView
        recyclerView.setItemViewCacheSize(5)
    }

    override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
        if (holder is MessageBaseHolder) {
            holder.setMessageBubbleBackground(null)
            holder.onRecycled()
        }
    }

    fun showLoading() {
        if (mLoading) {
            return
        }
        mLoading = true
        notifyItemChanged(0)
    }

    private fun refreshLoadView() {
        notifyItemChanged(0)
    }

    override fun onDataSourceChanged(dataSource: List<TUIMessageBean?>?) {
        if (dataSource.isNullOrEmpty()) {
            items = emptyList<TUIMessageBean>()
            return
        }
        val itemList = LinkedList<TUIMessageBean>()
        val orderIdMsgSet = mutableSetOf<String>()
        //从最新的一条消息往前遍历
        var i = dataSource.size - 1
        while (i >= 0) {
            val data = dataSource[i--] ?: continue
            if (SUPPORT_MESSAGE_TYPES.contains(data.javaClass)) {
                itemList.addFirst(wrapMessageItem(data, orderIdMsgSet))
            } else {
                itemList.addFirst(UnSupportMessageBean(data))
            }
        }
        items = itemList
    }

    private fun wrapMessageItem(
        messageBean: TUIMessageBean,
        orderIdMsgSet: MutableSet<String>
    ): TUIMessageBean {
        if (messageBean is PlaymateOrderMessageBean) {
            //订单消息
            val data = messageBean.data
            if (data == null) {
                return InVisibleMessageBean().also {
                    it.bean = messageBean
                }
            }
            if (orderIdMsgSet.contains(data.orderId)) {
                //最新的消息有同样的orderId
                return InVisibleMessageBean().also {
                    it.bean = messageBean
                }
            }
            orderIdMsgSet.add(data.orderId)
            return messageBean
        }

        return messageBean
    }

    override fun onViewNeedRefresh(
        type: Int,
        locateMessage: TUIMessageBean?
    ) {
        mLoading = false
        refreshLoadView()
        if (type == IMessageRecyclerView.DATA_CHANGE_LOCATE_TO_POSITION) {
            notifyDataSetChanged()
            val position: Int = getMessagePosition(locateMessage)
            if (position == ITEM_POSITION_UNKNOWN) {
                return
            }
            mRecycleView?.smoothScrollToPosition(position)
            locateMessage?.id?.let { id ->
                HighlightPresenter.startHighlight(id)
            }
        } else if (type == IMessageRecyclerView.SCROLL_TO_POSITION) {
            val position: Int = getMessagePosition(locateMessage)
            if (position == ITEM_POSITION_UNKNOWN) {
                return
            }
            mRecycleView?.smoothScrollToPosition(position)
            locateMessage?.id?.let { id ->
                HighlightPresenter.startHighlight(id)
            }
            mRecycleView?.scrollMessageFinish()
        } else if (type == IMessageRecyclerView.DATA_CHANGE_SCROLL_TO_POSITION) {
            notifyDataSetChanged()
            val position: Int = getMessagePosition(locateMessage)
            if (position == ITEM_POSITION_UNKNOWN) {
                return
            }
            mRecycleView?.scrollToEnd()
            mRecycleView?.smoothScrollToPosition(position)
            locateMessage?.id?.let { id ->
                HighlightPresenter.startHighlight(id)
            }
            mRecycleView?.scrollMessageFinish()
        } else if (type == IMessageRecyclerView.DATA_CHANGE_TYPE_UPDATE) {
            val position: Int = getMessagePosition(locateMessage)
            if (position == ITEM_POSITION_UNKNOWN) {
                return
            }
            onItemChanged(position)
        } else if (type == IMessageRecyclerView.DATA_CHANGE_SCROLL_TO_POSITION_WITHOUT_HIGH_LIGHT) {
            notifyDataSetChanged()
            val position: Int = getMessagePosition(locateMessage)
            if (position == ITEM_POSITION_UNKNOWN) {
                return
            }
            mRecycleView?.smoothScrollToPosition(position)
        }
    }

    override fun onViewNeedRefresh(type: Int, value: Int) {
        mLoading = false
        if (type == IMessageRecyclerView.DATA_CHANGE_TYPE_REFRESH) {
            notifyDataSetChanged()
            mRecycleView?.scrollToEnd()
        } else if (type == IMessageRecyclerView.DATA_CHANGE_TYPE_ADD_BACK) {
            onItemInsert(items.size + 1, value)
        } else if (type == IMessageRecyclerView.DATA_CHANGE_NEW_MESSAGE) {
            onItemInsert(items.size + 1, value)
            mRecycleView?.onMsgAddBack()
        } else if (type == IMessageRecyclerView.DATA_CHANGE_TYPE_UPDATE) {
            notifyDataSetChanged()
        } else if (type == IMessageRecyclerView.DATA_CHANGE_TYPE_ADD_FRONT) {
            // The number of loaded entries is 0, only the animation is updated
            if (value != 0) {
                // During the loading process, it is possible that the time interval between the first item before
                // and the last item newly loaded is not more than 5 minutes, and the time entry needs to be removed,
                // so the refresh here needs one more entry
                onItemInsert(0, value)
            }
        } else if (type == IMessageRecyclerView.DATA_CHANGE_TYPE_LOAD) {
            notifyDataSetChanged()
            mRecycleView?.scrollToEnd()
            mRecycleView?.loadMessageFinish()
        } else if (type == IMessageRecyclerView.DATA_CHANGE_TYPE_DELETE) {
            if (value == ITEM_POSITION_UNKNOWN) {
                return
            }
            onItemRemove(value)
        }
        refreshLoadView()
    }


    private fun getMessagePosition(message: TUIMessageBean?): Int {
        message ?: return ITEM_POSITION_UNKNOWN
        var position = ITEM_POSITION_UNKNOWN
        if (items.isEmpty()) {
            return position
        }

        position = items.indexOfFirst { it == message }
        if (position == -1) {
            return ITEM_POSITION_UNKNOWN
        }
        return position
    }

    override fun getItem(position: Int): TUIMessageBean? {
        return items.getOrNull(position) as? TUIMessageBean
    }

    override fun getFirstMessageBean(): TUIMessageBean? {
        return items.firstOrNull() as? TUIMessageBean
    }

    override fun getLastMessageBean(): TUIMessageBean? {
        return items.lastOrNull() as? TUIMessageBean
    }

    override fun onItemRefresh(messageBean: TUIMessageBean?) {
        onViewNeedRefresh(IMessageRecyclerView.DATA_CHANGE_TYPE_UPDATE, messageBean)
    }

    private fun onItemChanged(position: Int) {
        var start = position - 1
        var end = position + 1
        if (start < 0) {
            start = 0
        }
        if (end > getItemCount()) {
            end = position
        }
        val count = end - start
        notifyItemRangeChanged(start, count)
    }

    private fun onItemInsert(start: Int, count: Int) {
        notifyItemRangeInserted(start, count)
        val startTemp = start - 2
        val endTemp = start + count + 2
        notifyItemRangeChanged(startTemp, endTemp - startTemp)
    }

    private fun onItemRemove(position: Int) {
        val start = position - 1
        val end = position + 1
        if (start >= 0) {
            notifyItemChanged(start)
        }
        if (end <= getItemCount()) {
            notifyItemChanged(end)
        }
        notifyItemRemoved(position)
    }

    override fun getUserFaceUrlCache(): UserFaceUrlCache? {
        // TODO: 不要实现这个方法
        return null
    }
}