package com.kaixed.kchat.ui.adapter

import android.content.Context
import android.graphics.drawable.ColorDrawable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.PopupWindow
import androidx.constraintlayout.widget.ConstraintSet
import androidx.recyclerview.widget.RecyclerView
import com.kaixed.kchat.R
import com.kaixed.kchat.data.objectbox.ObjectBox
import com.kaixed.kchat.data.objectbox.entity.Messages
import com.kaixed.kchat.databinding.ChatRecycleItemCustomBinding
import com.kaixed.kchat.databinding.ChatRecycleItemEmojiBinding
import com.kaixed.kchat.databinding.ChatRecycleItemImageBinding
import com.kaixed.kchat.databinding.ChatRecycleItemLocationBinding
import com.kaixed.kchat.databinding.ChatRecycleItemRedPacketBinding
import com.kaixed.kchat.databinding.ChatRecycleItemTipBinding
import com.kaixed.kchat.databinding.ChatRecycleItemVoiceBinding
import com.kaixed.kchat.databinding.PopwindowsBinding
import com.kaixed.kchat.utils.ConstantsUtil.getUsername
import com.kaixed.kchat.utils.DensityUtil
import com.kaixed.kchat.utils.ImageSpanUtil
import com.kaixed.kchat.utils.MessageType
import io.objectbox.Box
import java.util.LinkedList

class ChatAdapter(
    private val context: Context,
    private val messages: LinkedList<Messages>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    companion object {
        private const val ITEM_TYPE_CUSTOM = 0
        private const val ITEM_TYPE_TIP = 1
        private const val ITEM_TYPE_IMAGE = 2
        private const val ITEM_TYPE_VOICE = 3
        private const val ITEM_TYPE_LOCATION = 4
        private const val ITEM_TYPE_EMOJI = 5
        private const val ITEM_TYPE_RED_PACKET = 6

        private const val TAG = "ChatAdapter"
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            ITEM_TYPE_TIP -> {
                val binding = ChatRecycleItemTipBinding.inflate(
                    LayoutInflater.from(parent.context),
                    parent,
                    false
                )
                TipViewHolder(binding)
            }

            ITEM_TYPE_IMAGE -> {
                val binding = ChatRecycleItemImageBinding.inflate(
                    LayoutInflater.from(parent.context),
                    parent,
                    false
                )
                ImageViewHolder(binding)
            }

            ITEM_TYPE_VOICE -> {
                val binding = ChatRecycleItemVoiceBinding.inflate(
                    LayoutInflater.from(parent.context),
                    parent,
                    false
                )
                VoiceViewHolder(binding)
            }

            ITEM_TYPE_LOCATION -> {
                val binding = ChatRecycleItemLocationBinding.inflate(
                    LayoutInflater.from(parent.context),
                    parent,
                    false
                )
                LocationViewHolder(binding)
            }

            ITEM_TYPE_EMOJI -> {
                val binding = ChatRecycleItemEmojiBinding.inflate(
                    LayoutInflater.from(parent.context),
                    parent,
                    false
                )
                EmojiViewHolder(binding)
            }

            ITEM_TYPE_RED_PACKET -> {
                val binding = ChatRecycleItemRedPacketBinding.inflate(
                    LayoutInflater.from(parent.context),
                    parent,
                    false
                )
                RedPacketViewHolder(binding)
            }

            else -> {
                val binding = ChatRecycleItemCustomBinding.inflate(
                    LayoutInflater.from(parent.context),
                    parent,
                    false
                )
                CustomViewHolder(binding)
            }
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val singleMessage = messages[position]

        when (holder) {
            is TipViewHolder -> {
                holder.bindData(singleMessage)
            }

            is CustomViewHolder -> {
                holder.bindData(singleMessage, context)
            }

            is ImageViewHolder -> {
                holder.bindData(singleMessage)
            }

            is VoiceViewHolder -> {
                holder.bindData(singleMessage)
            }

            is LocationViewHolder -> {
                holder.bindData(singleMessage)
            }

            is EmojiViewHolder -> {
                holder.bindData(singleMessage)
            }

            is RedPacketViewHolder -> {
                holder.bindData(singleMessage)
            }
        }

        holder.itemView.setOnLongClickListener {
            showPopupWindow(it, position)
            true
        }
    }

    class TipViewHolder(val binding: ChatRecycleItemTipBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bindData(message: Messages) {
            if (message.show) {
                binding.tvTip.text = binding.root.context.getString(
                    R.string.withdraw_message_format,
                    message.senderId
                )
            }
        }
    }

    class CustomViewHolder(val binding: ChatRecycleItemCustomBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bindData(message: Messages, context: Context) {
            val isMine: Boolean = message.senderId == getUsername()
            setViewPosition(binding, isMine, context).applyTo(binding.main)

            binding.tvMessageContent.text = ImageSpanUtil.setEmojiSpan(
                context,
                message.content,
                DensityUtil.dpToPx(context, 18)
            )
        }

        private fun setViewPosition(
            binding: ChatRecycleItemCustomBinding,
            isMine: Boolean,
            context: Context
        ): ConstraintSet {
            val constraintSet = ConstraintSet()
            constraintSet.clone(binding.main)

            val avatarId: Int = binding.ifvAvatar.id
            val messageId = binding.tvMessageContent.id
            val margin = DensityUtil.dpToPx(context, 10)

            val (avatarConnectionStart, avatarConnectionEnd) = if (isMine) {
                ConstraintSet.END to ConstraintSet.START
            } else {
                ConstraintSet.START to ConstraintSet.END
            }

            constraintSet.connect(
                avatarId,
                avatarConnectionStart,
                ConstraintSet.PARENT_ID,
                avatarConnectionStart,
                margin
            )

            constraintSet.connect(
                messageId,
                avatarConnectionStart,
                avatarId,
                avatarConnectionEnd,
                margin
            )

            return constraintSet
        }
    }

    class ImageViewHolder(val binding: ChatRecycleItemImageBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bindData(message: Messages) {
        }
    }

    class VoiceViewHolder(val binding: ChatRecycleItemVoiceBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bindData(message: Messages) {
        }
    }

    class LocationViewHolder(val binding: ChatRecycleItemLocationBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bindData(message: Messages) {
        }
    }

    class EmojiViewHolder(val binding: ChatRecycleItemEmojiBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bindData(message: Messages) {
        }
    }

    class RedPacketViewHolder(val binding: ChatRecycleItemRedPacketBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bindData(message: Messages) {
        }
    }

    override fun getItemViewType(position: Int): Int {
        val message = messages[position]
        return when (MessageType.fromValue(message.type.toInt())) {
            MessageType.TIP -> ITEM_TYPE_TIP
            MessageType.IMAGE -> ITEM_TYPE_IMAGE
            MessageType.VOICE -> ITEM_TYPE_VOICE
            MessageType.LOCATION -> ITEM_TYPE_LOCATION
            MessageType.EMOJI -> ITEM_TYPE_EMOJI
            MessageType.RED_PACKET -> ITEM_TYPE_RED_PACKET
            MessageType.CUSTOM -> ITEM_TYPE_CUSTOM
            null -> ITEM_TYPE_CUSTOM
        }
    }

    private fun updateDb(message: Messages) {
        val messagesBox: Box<Messages> = ObjectBox.get().boxFor(Messages::class.java)
        messagesBox.put(message)
    }

    override fun getItemCount(): Int = messages.size

    private fun showPopupWindow(view: View, position: Int) {
        val binding: PopwindowsBinding = PopwindowsBinding.inflate(LayoutInflater.from(context))
        val popupWindow: PopupWindow = PopupWindow(
            binding.root,
            ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT
        ).apply {
            isFocusable = true
            isOutsideTouchable = true
            setBackgroundDrawable(ColorDrawable())
        }

        // 动态计算 PopupWindow 的显示位置
        val location = IntArray(2)
        view.getLocationOnScreen(location)

        // 测量 PopupWindow 的宽度和高度
        binding.root.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
        val popupWidth = binding.root.measuredWidth
        val popupHeight = binding.root.measuredHeight

        // 计算水平居中的偏移量
        val offsetX = (view.width - popupWidth) / 2

        // 上下方显示的 padding
        val somePadding = DensityUtil.dpToPx(context, 10)

        // 获取 view 顶部和底部在屏幕中的绝对位置
        val viewTop = location[1]
        val viewBottom = location[1] + view.height

        // 判断 PopupWindow 显示在上方是否有足够空间
        val isEnoughSpaceAbove = viewTop >= popupHeight + somePadding
        val isEnoughSpaceBelow =
            (context.resources.displayMetrics.heightPixels - viewBottom) >= popupHeight + somePadding

        // 计算 Y 轴的偏移量，根据空间选择上方或下方显示
        val offsetY = if (isEnoughSpaceAbove) {
            -view.height - popupHeight - somePadding
        } else if (isEnoughSpaceBelow) {
            view.height + somePadding
        } else {
            // 如果上下空间都不足，选择最小偏移量的显示（可以根据需求调整）
            view.height / 2
        }

        // 显示 PopupWindow，锚点是 view
        popupWindow.showAsDropDown(view, offsetX, offsetY)

        // 设置点击事件
        binding.ivWithdraw.setOnClickListener {
            messages[position].status = "withdraw"
            updateDb(messages[position])
            notifyItemChanged(position)
            popupWindow.dismiss()
        }
    }
}
