package com.gh.gamecenter.subject

import android.content.Context
import android.text.TextUtils
import android.util.SparseArray
import android.view.View
import android.view.ViewGroup
import androidx.core.view.setPadding
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.constant.ItemViewType
import com.gh.common.databind.BindingAdapters
import com.gh.common.exposure.ExposureEvent
import com.gh.common.exposure.ExposureSource
import com.gh.common.exposure.IExposable
import com.gh.common.util.*
import com.gh.common.util.NewLogUtils
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.viewholder.FooterViewHolder
import com.gh.gamecenter.adapter.viewholder.GameImageViewHolder
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
import com.gh.gamecenter.common.baselist.ListAdapter
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.databinding.GameImageItemBinding
import com.gh.gamecenter.databinding.GameItemBinding
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.game.GameItemViewHolder
import com.lightgame.download.DownloadEntity
import java.util.*

class SubjectAdapter(
    context: Context,
    private val mViewModel: SubjectListViewModel,
    private val mSubjectViewModel: SubjectViewModel?,
    private val mEntrance: String?,
    private val mIsColumnCollection: Boolean
) : ListAdapter<GameEntity>(context), IExposable {
    private val mExposureEventSparseArray: SparseArray<ExposureEvent> = SparseArray()

    private val subjectData = mViewModel.subjectData

    val positionAndPackageMap = HashMap<String, Int>()

    override fun setListData(updateData: MutableList<GameEntity>?) {
        positionAndPackageMap.clear()
        // 记录游戏位置
        if (updateData != null) {
            for (i in 0 until updateData.size) {
                val gameEntity = updateData[i]
                var packages = gameEntity.id
                for (apkEntity in gameEntity.getApk()) {
                    packages += apkEntity.packageName
                }
                positionAndPackageMap[packages + i] = i
            }
        }
        super.setListData(updateData)
    }

    override fun areItemsTheSame(oldItem: GameEntity?, newItem: GameEntity?): Boolean {
        return oldItem?.id == newItem?.id
    }

    override fun getItemViewType(position: Int): Int {
        if (position == itemCount - 1) {
            return ItemViewType.ITEM_FOOTER
        }
        if (position == 0 && mEntityList != null && mEntityList.size > 0
            && !TextUtils.isEmpty(mEntityList[0].image)
        ) {
            return ItemViewType.GAME_IMAGE
        }
        return ItemViewType.GAME_NORMAL
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            ItemViewType.GAME_NORMAL -> {
                GameItemViewHolder(GameItemBinding.bind(mLayoutInflater.inflate(R.layout.game_item, parent, false)))
            }
            ItemViewType.GAME_IMAGE -> {
                GameImageViewHolder(
                    GameImageItemBinding.bind(
                        mLayoutInflater.inflate(
                            R.layout.game_image_item,
                            parent,
                            false
                        )
                    )
                )
            }
            else -> {
                FooterViewHolder(mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false))
            }
        }
    }

    override fun getItemCount(): Int {
        return if (mEntityList == null || mEntityList.isEmpty()) return 0 else mEntityList.size + 1
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        if (holder is GameItemViewHolder) {
            val padTop = if (position == 0) 16F.dip2px() else 12F.dip2px()
            val padLeft = if (subjectData.isOrder!!) 0 else 20F.dip2px()
            holder.itemView.setPadding(padLeft, padTop, 20F.dip2px(), 12F.dip2px())

            val gameEntity = mEntityList[position]
            // 专题详情均显示游戏后缀 https://git.ghzs.com/pm/halo-app-issues/-/issues/1098 (3)
            holder.bindGameItem(gameEntity, true, subjectData.briefStyle)
            holder.initServerType(gameEntity)

            if (subjectData.isOrder!!) {
                var index = 1
                if (!TextUtils.isEmpty(mEntityList[0].image)) index = 0
                holder.binding.gameOrder.visibility = View.VISIBLE
                holder.binding.gameOrder.text = (position + index).toString()
                holder.binding.gameOrder.setPadding(0)
                holder.binding.gameOrder.layoutParams?.let {
                    it.height = 24F.dip2px()
                    it.width = 24F.dip2px()
                    if (it is ViewGroup.MarginLayoutParams) {
                        it.leftMargin = 4F.dip2px()
                        it.rightMargin = 4F.dip2px()
                    } else throwExceptionInDebug()
                }
                when (position + index) {
                    1 -> {
                        if (mIsColumnCollection) {
                            holder.binding.gameOrder.setTextColor(R.color.white.toColor())
                            holder.binding.gameOrder.setBackgroundResource(R.drawable.subject_top_first)
                            holder.binding.gameOrder.textSize = 9F
                            holder.binding.gameOrder.setPadding(0, 2F.dip2px(), 0, 0)
                            holder.binding.gameOrder.layoutParams?.let {
                                it.height = 16F.dip2px()
                                it.width = 16F.dip2px()
                                if (it is ViewGroup.MarginLayoutParams) {
                                    it.leftMargin = 8F.dip2px()
                                    it.rightMargin = 8F.dip2px()
                                }
                            }
                        } else {
                            holder.binding.gameOrder.setTextColor(R.color.text_ff5151.toColor())
                        }
                    }
                    2 -> {
                        if (mIsColumnCollection) {
                            holder.binding.gameOrder.setTextColor(R.color.white.toColor())
                            holder.binding.gameOrder.setBackgroundResource(R.drawable.subject_top_second)
                            holder.binding.gameOrder.textSize = 9F
                            holder.binding.gameOrder.setPadding(0, 2F.dip2px(), 0, 0)
                            holder.binding.gameOrder.layoutParams?.let {
                                it.height = 16F.dip2px()
                                it.width = 16F.dip2px()
                                if (it is ViewGroup.MarginLayoutParams) {
                                    it.leftMargin = 8F.dip2px()
                                    it.rightMargin = 8F.dip2px()
                                }
                            }
                        } else {
                            holder.binding.gameOrder.setTextColor(R.color.text_f67722.toColor())
                        }
                    }
                    3 -> {
                        if (mIsColumnCollection) {
                            holder.binding.gameOrder.setTextColor(R.color.white.toColor())
                            holder.binding.gameOrder.setBackgroundResource(R.drawable.subject_top_third)
                            holder.binding.gameOrder.textSize = 9F
                            holder.binding.gameOrder.setPadding(0, 2F.dip2px(), 0, 0)
                            holder.binding.gameOrder.layoutParams?.let {
                                it.height = 16F.dip2px()
                                it.width = 16F.dip2px()
                                if (it is ViewGroup.MarginLayoutParams) {
                                    it.leftMargin = 8F.dip2px()
                                    it.rightMargin = 8F.dip2px()
                                }
                            }
                        } else {
                            holder.binding.gameOrder.setTextColor(R.color.text_ffbf00.toColor())
                        }
                    }
                    else -> {
                        if (mIsColumnCollection) {
                            holder.binding.gameOrder.textSize = 12F
                            holder.binding.gameOrder.background = null
                        }
                        holder.binding.gameOrder.setTextColor(R.color.text_989898.toColor())
                    }
                }
            } else {
                holder.binding.gameOrder.visibility = View.GONE
            }

            var subjectStyle = ""
            var isFilterOn = false

            mSubjectViewModel?.subjectSettingLD?.value?.let { subjectSetting ->
                subjectStyle = subjectSetting.typeEntity.layout
                isFilterOn = subjectSetting.filter == "on"
            }

            val exposureEvent = generateExposureEvent(gameEntity, subjectStyle, isFilterOn)
            val humanReadablePosition = position + 1
            mExposureEventSparseArray.put(position, exposureEvent)

            holder.itemView.setOnClickListener {
                DataCollectionUtils.uploadClick(mContext, "列表", subjectData.subjectName, gameEntity.name)

                GameDetailActivity.startGameDetailActivity(
                    mContext,
                    gameEntity,
                    StringUtils.buildString(
                        mEntrance,
                        "+(",
                        subjectData.subjectName,
                        ":列表[", subjectData.filter,
                        "=",
                        if (subjectData.sort.contains("publish")) "最新"
                        else "最热",
                        "=", (humanReadablePosition).toString(), "])"
                    ),
                    traceEvent = exposureEvent
                )
            }

            DownloadItemUtils.setOnClickListener(
                mContext,
                holder.binding.downloadBtn,
                gameEntity,
                position,
                this,
                StringUtils.buildString(
                    mEntrance,
                    "+(",
                    subjectData.subjectName,
                    ":列表[", subjectData.filter,
                    "=",
                    if (subjectData.sort.contains("publish")) "最新"
                    else "最热",
                    "=", (humanReadablePosition).toString(), "])"
                ),
                StringUtils.buildString(subjectData.subjectName, ":", gameEntity.name),
                exposureEvent
            )

            DownloadItemUtils.updateItem(
                mContext,
                gameEntity,
                GameViewHolder(holder.binding),
                true,
                subjectData.briefStyle
            )
        } else if (holder is GameImageViewHolder) {
            val gameEntity = mEntityList[position]

            val widthPixels = if (mIsColumnCollection) {
                val padBottom = if (gameEntity.des.isNullOrEmpty()) {
                    16F.dip2px()
                } else {
                    holder.binding.gameDes.setPadding(0, 13F.dip2px(), 0, 13F.dip2px())
                    2F.dip2px()
                }
                holder.itemView.setPadding(20F.dip2px(), 12F.dip2px(), 20F.dip2px(), padBottom)
                mContext.resources.displayMetrics.widthPixels - 40F.dip2px() // 40: padding left and right
            } else {
                holder.itemView.setPadding(0F.dip2px(), 0F.dip2px(), 0F.dip2px(), 0F.dip2px())
                mContext.resources.displayMetrics.widthPixels
            }

            holder.binding.run {
                gameContainer.goneIf(!(gameEntity.type == "game" && gameEntity.getApk().isNotEmpty()))
                gameIcon.displayGameIcon(gameEntity)
                gameName.text = gameEntity.name
                gameSize.text = if (gameEntity.getApk().isNotEmpty()) gameEntity.getApk()[0].size.toString() else ""
                BindingAdapters.setDownloadButton(progressBar, gameEntity, null, null, null, "")
            }
            ImageUtils.display(holder.binding.gameImageIcon, gameEntity.image, widthPixels)

            // 大图是游戏的时候添加曝光事件
            if ("game" == gameEntity.type) {
                val exposureSources = ArrayList<ExposureSource>()
                exposureSources.add(ExposureSource("专题", subjectData.subjectName.toString()))
                exposureSources.add(ExposureSource("专题详情", "头图"))
                gameEntity.id = gameEntity.link ?: ""
                val event = ExposureEvent.createEvent(gameEntity, exposureSources)
                mExposureEventSparseArray.put(position, event)
            }

            if (!TextUtils.isEmpty(gameEntity.des)) {
                holder.binding.gameDes.visibility = View.VISIBLE
                holder.binding.gameDes.text = gameEntity.des?.fromHtml()
            }

            holder.itemView.setOnClickListener {
                DataCollectionUtils.uploadClick(mContext, "头图", subjectData.subjectName)
                MtaHelper.onEvent("游戏专题", "头图", subjectData.subjectName + ":" + gameEntity.name)
                val linkEntity = LinkEntity()
                linkEntity.link = gameEntity.link
                linkEntity.type = gameEntity?.type
                linkEntity.text = gameEntity.text
                linkEntity.name = gameEntity.name
                linkEntity.display = gameEntity.display
                linkEntity.community = gameEntity.community
                PageSwitchDataHelper.pushCurrentPageData(
                    hashMapOf(
                        Pair(PageSwitchDataHelper.PAGE_BUSINESS_TYPE, "游戏专题-头图"),
                        Pair(PageSwitchDataHelper.PAGE_BUSINESS_NAME, subjectData.subjectName ?: "")
                    )
                )
                DirectUtils.directToLinkPage(
                    mContext, linkEntity,
                    mEntrance + "(" + subjectData.subjectName + ":头图)", "游戏专题", mExposureEventSparseArray.get(position)
                )
                NewLogUtils.logColumnPictureClick(
                    "头图", subjectData.subjectName ?: "", subjectData.subjectId ?: "",
                    linkEntity.link ?: "", linkEntity.type ?: "", linkEntity.text ?: "", "专题详情", ""
                )
            }
        } else if (holder is FooterViewHolder) {
            holder.initFooterViewHolder(mViewModel, mIsLoading, mIsNetworkError, mIsOver)
        }
    }

    private fun generateExposureEvent(
        gameEntity: GameEntity,
        subjectStyle: String,
        isFilterOn: Boolean
    ): ExposureEvent {
        val exposureSourceList = arrayListOf<ExposureSource>()
        if (!mViewModel.exposureSourceList.isNullOrEmpty()) {
            exposureSourceList.addAll(mViewModel.exposureSourceList!!)
        }
        if (mIsColumnCollection) {
            exposureSourceList.add(ExposureSource("排行榜"))
            exposureSourceList.add(ExposureSource("专题", subjectData.subjectName.toString()))
        } else {
            var sourceString = ""
            exposureSourceList.add(ExposureSource("专题", subjectData.subjectName.toString()))

            when (subjectStyle) {
                "tile" -> {
                    val filter = subjectData.filter.replace("type:", "")
                    sourceString = filter

                    if (isFilterOn) {
                        val sort = when {
                            subjectData.sort.contains("publish") -> "最新"
                            subjectData.sort.contains("star") -> "评分"
                            else -> "最热"
                        }

                        val filterSize = mViewModel.selectedFilterSize.text

                        sourceString =
                            if (sourceString.isEmpty()) "$sort+$filterSize" else "$sourceString+$sort+$filterSize"
                    }

                    exposureSourceList.add(ExposureSource("专题详情", sourceString))
                }
                "rows" -> {
                    val filterList = mViewModel.selectedLabelList

                    for (filter in filterList) {
                        sourceString = if (sourceString.isEmpty()) filter else "$sourceString+$filter"
                    }

                    if (isFilterOn) {
                        val sort = when {
                            subjectData.sort.contains("publish") -> "最新"
                            subjectData.sort.contains("star") -> "评分"
                            else -> "推荐"
                        }

                        val filterSize = mViewModel.selectedFilterSize.text

                        sourceString =
                            if (sourceString.isEmpty()) "$sort+$filterSize" else "$sourceString+$sort+$filterSize"
                    }

                    exposureSourceList.add(ExposureSource("专题详情", sourceString))
                }
                else -> {
                    val sort = when {
                        subjectData.sort.contains("publish") -> "最新"
                        subjectData.sort.contains("star") -> "评分"
                        else -> "推荐"
                    }

                    val filterSize = mViewModel.selectedFilterSize.text

                    sourceString =
                        if (sourceString.isEmpty()) "$sort+$filterSize" else "$sourceString+$sort+$filterSize"
                    if (sourceString.isNotEmpty()) {
                        exposureSourceList.add(ExposureSource("专题详情", sourceString))
                    }
                }
            }
        }

        return ExposureEvent.createEvent(gameEntity, exposureSourceList).apply {
            mViewModel.lastPageDataMap?.let {
                payload.sourcePage = it[PageSwitchDataHelper.PAGE_BUSINESS_TYPE]
                payload.sourcePageId = it[PageSwitchDataHelper.PAGE_BUSINESS_ID]
                payload.sourcePageName = it[PageSwitchDataHelper.PAGE_BUSINESS_NAME]
            }
        }
    }

    override fun getEventByPosition(pos: Int): ExposureEvent? {
        return mExposureEventSparseArray.get(pos)
    }

    override fun getEventListByPosition(pos: Int): List<ExposureEvent>? {
        return null
    }

    fun notifyItemByDownload(download: DownloadEntity) {
        for (key in positionAndPackageMap.keys) {
            if (key.contains(download.packageName) && key.contains(download.gameId)) {
                val position = positionAndPackageMap[key]
                if (position != null && mEntityList != null && position < mEntityList.size) {
                    mEntityList[position].getEntryMap()[download.platform] = download
                    notifyItemChanged(position)
                }
            }
        }
    }

    fun notifyItemAndRemoveDownload(status: EBDownloadStatus) {
        for (key in positionAndPackageMap.keys) {
            if (key.contains(status.packageName) && key.contains(status.gameId)) {
                val position = positionAndPackageMap[key]
                if (position != null && mEntityList != null && position < mEntityList.size) {
                    mEntityList[position].getEntryMap().remove(status.platform)
                    notifyItemChanged(position)
                }
            }
        }
    }
}