package com.gh.gamecenter.mygame

import android.content.Context
import android.os.Build
import android.util.SparseArray
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView
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.DialogUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
import com.gh.gamecenter.common.baselist.ListAdapter
import com.gh.gamecenter.common.callback.CancelListener
import com.gh.gamecenter.common.callback.ConfirmListener
import com.gh.gamecenter.common.constant.ItemViewType
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.DrawableView
import com.gh.gamecenter.common.viewholder.FooterViewHolder
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.utils.EmptyCallback
import com.gh.gamecenter.core.utils.NumberUtils
import com.gh.gamecenter.core.utils.StringUtils
import com.gh.gamecenter.databinding.ItemPlayedGameBinding
import com.gh.gamecenter.databinding.ViewSimpleToggleBinding
import com.gh.gamecenter.energy.EnergyBridge
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.game.GameItemViewHolder
import com.lightgame.download.DownloadEntity

open class PlayedGameAdapter(
    private val mContext: Context,
    private val mViewModel: PlayedGameViewModel,
    private val mIsMyPlayedGame: Boolean
) : ListAdapter<GameEntity>(mContext), IExposable {

    private val mPositionAndPackageMap = HashMap<String, Int>()
    private val mEntrance = if (mIsMyPlayedGame) "我的玩过" else "玩过的游戏"
    private val mExposureEventSparseArray: SparseArray<ExposureEvent> = SparseArray()
    private val mDownloadText by lazy { mContext.getString(R.string.download) }
    private val mTryText by lazy { mContext.getString(R.string.attempt) }
    private var mDismissGameTimeLongDialogFlag = false

    override fun setListData(updateData: MutableList<GameEntity>?) {
        if (!updateData.isNullOrEmpty()) {
            if (hasHeader()) {
                if (updateData[0].id.isNotEmpty()) {
                    updateData.add(0, GameEntity()) // add head item
                }
            } else {
                if (updateData[0].id.isEmpty()) {
                    updateData.remove(updateData[0]) // remove head item
                }
            }
        }

        // 记录游戏位置
        if (updateData != null) {
            for (i in 0 until updateData.size) {
                val gameEntity = updateData[i]

                // 一些数据置换
                val apk = gameEntity.getApk()
                if (apk.size > 0 && !apk[0].ghVersion.isNullOrEmpty()) {
                    gameEntity.brief = PlatformUtils.getInstance(mContext).getPlatformName(apk[0].getPlatform())
                }

                var packages = gameEntity.id
                for (apkEntity in apk) {
                    packages += apkEntity.packageName
                }
                mPositionAndPackageMap[packages + i] = i
            }
        }
        super.setListData(updateData)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            ItemViewType.GAME_NORMAL -> {
                MyPlayedGameViewHolder(parent.toBinding())
            }
            ItemViewType.ITEM_HEADER -> {
                UsageStatsViewHolder(parent.toBinding())
            }
            else -> {
                FooterViewHolder(mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false))
            }
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            is MyPlayedGameViewHolder -> {
                val gameEntity = mEntityList[position]

                holder.initServerType(gameEntity)
                holder.binding.gameItemIncluded.run {
                    root.background = R.drawable.reuse_listview_item_style.toDrawable(root.context)
                    gameKaifuType.setBackgroundColor(R.color.theme.toColor(root.context))
                    gameName.setTextColor(R.color.text_title.toColor(root.context))
                    gameDes.setTextColor(R.color.text_subtitleDesc.toColor(root.context))
                    recommendStarPref.setTextColor(R.color.text_subtitleDesc.toColor(root.context))

                    downloadBtn.layoutParams = downloadBtn.layoutParams.apply {
                        width = 56F.dip2px()
                        height = 28F.dip2px()
                    }
                    gameIconView.displayGameIcon(gameEntity)
                    BindingAdapters.setGameName(gameName, gameEntity, false, null)
                    BindingAdapters.setTextSize(gameRating, if (gameEntity.commentCount > 3) 12 else 10)
                    BindingAdapters.setGameTags(labelList, gameEntity)
                    gameRating.setDrawableStart(if (gameEntity.commentCount > 3) R.drawable.game_horizontal_rating.toDrawable() else null)
                    gameRating.setPadding(0, 0, if (gameEntity.commentCount > 3) 8F.dip2px() else 0, 0)
                    gameRating.text = if (gameEntity.commentCount > 3) {
                        if (gameEntity.star == 10.0F) "10" else gameEntity.star.toString()
                    } else ""
                    gameRating.setTextColor(
                        if (gameEntity.commentCount > 3) R.color.theme_font.toColor(mContext) else R.color.theme.toColor(
                            mContext
                        )
                    )
                    gameDes.text = gameEntity.decoratedDes
                    recommendStar.rating = gameEntity.recommendStar.toFloat()
                    GameItemViewHolder.initGameSubtitle(gameEntity, gameSubtitleTv, gameDesSpace, root)
                }

                holder.binding.gameItemIncluded.run {
                    if (gameEntity.playedTime == 0L) {
                        gameDes.post {
                            gameDes.layoutParams = (gameDes.layoutParams as ConstraintLayout.LayoutParams).apply {
                                topMargin = 8F.dip2px()
                            }
                            gameDesSpace.layoutParams = gameDesSpace.layoutParams.apply {
                                height = gameDes.height + 8F.dip2px()
                            }
                        }
                        labelList.visibility = View.GONE
                    } else {
                        gameDes.layoutParams = (gameDes.layoutParams as ConstraintLayout.LayoutParams).apply {
                            topMargin = 5F.dip2px()
                        }
                        gameDesSpace.layoutParams = gameDesSpace.layoutParams.apply {
                            height = 28F.dip2px()
                        }
                        labelList.visibility = View.VISIBLE
                        labelList.removeAllViews()
                        val runTimeView = TextView(mContext)
                        runTimeView.isSingleLine = true
                        runTimeView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 11f)
                        runTimeView.setTextColor(R.color.text_subtitle.toColor(mContext))
                        runTimeView.text = "游戏时长 ${NumberUtils.transSimpleUsageTime(gameEntity.playedTime)}"
                        labelList.addView(runTimeView)
                    }
                }

                val exposureSourceKey = if (mIsMyPlayedGame) "我的游戏" else "玩过的游戏"
                val exposureSourceValue = if (mIsMyPlayedGame) "玩过" else ""
                val exposureEvent = ExposureEvent.createEvent(
                    gameEntity,
                    listOf(ExposureSource(exposureSourceKey, exposureSourceValue))
                )
                mExposureEventSparseArray.append(position, exposureEvent)

                DownloadItemUtils.setOnClickListener(
                    mContext,
                    holder.binding.gameItemIncluded.downloadBtn,
                    gameEntity,
                    position,
                    this,
                    "(${mEntrance})",
                    StringUtils.buildString(mEntrance, ":", gameEntity.name), exposureEvent, object : EmptyCallback {
                        override fun onCallback() {
                            NewFlatLogUtils.logMyGamePlayedTabGameCardClick(
                                "按钮",
                                gameEntity.id,
                                gameEntity.name ?: ""
                            )
                        }
                    }

                )
                DownloadItemUtils.updateItem(
                    mContext,
                    gameEntity,
                    GameViewHolder(holder.binding.gameItemIncluded),
                    true,
                    true
                )

                holder.binding.optionsContainer.goneIf(!mIsMyPlayedGame)

                holder.itemView.setOnClickListener {
                    NewFlatLogUtils.logMyGamePlayedTabGameCardClick(
                        "游戏详情",
                        gameEntity.id,
                        gameEntity.name ?: ""
                    )

                    GameDetailActivity.startGameDetailActivity(mContext, gameEntity.id, "(${mEntrance})", exposureEvent)
                }

                holder.itemView.setOnLongClickListener {
                    val adapterPosition = holder.bindingAdapterPosition
                    if (adapterPosition != RecyclerView.NO_POSITION) {
                        val game = mEntityList[adapterPosition]
                        NewFlatLogUtils.logMyGamePlayedTabClearGameClick(game.id, game.name ?: "")
                        DialogHelper.showDialog(
                            mContext,
                            "清除记录",
                            "清除后将不再展示游戏记录和游玩时长，确定清除记录吗？",
                            "确定清除",
                            "暂不清除",
                            confirmClickCallback = {
                                NewFlatLogUtils.logMyGamePlayedTabClearGameDialogClick("确定清除", game.id, game.name ?: "")
                                mViewModel.deletePlayedGame(game)
                            },
                            cancelClickCallback = {
                                NewFlatLogUtils.logMyGamePlayedTabClearGameDialogClick("暂不清除", game.id, game.name ?: "")
                            },
                            uiModificationCallback = {
                                it.confirmTv.setTextColor(R.color.theme_red.toColor(mContext))
                            },
                            extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
                        )?.setOnCancelListener {
                            NewFlatLogUtils.logMyGamePlayedTabClearGameDialogClick("暂不清除", game.id, game.name ?: "")
                        }
                    }
                    true
                }

                // 很丑陋，但因为上面的下载按钮文案和状态是异步获取更新的，所以这里也只能异步更新了 ：（
                AppExecutor.lightWeightIoExecutor.execute {
                    AppExecutor.uiExecutor.execute {
                        tryWithDefaultCatch {
                            val downloadBtnText = holder.binding.gameItemIncluded.downloadBtn.text
                            val isDownloadable =
                                downloadBtnText.contains(mDownloadText) || downloadBtnText.contains(mTryText)
                            holder.binding.uninstalledTv.visibleIf(isDownloadable)
                        }
                    }
                }
            }
            is UsageStatsViewHolder -> {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
                    holder.binding.switchIv.visibility = View.GONE
                    holder.binding.lottieView.setSwitchAnimation(UsageStatsHelper.checkForPermission())
                    holder.binding.lottieView.setOnClickListener {
                        mDismissGameTimeLongDialogFlag = false
                        NewFlatLogUtils.logMyGameTabOpenTimeLongClick()
                        if (!UsageStatsHelper.checkForPermission()) {
                            DialogUtils.showUsageStatsDialog(
                                mContext, object : ConfirmListener {
                                    override fun onConfirm() {
                                        NewFlatLogUtils.logGameTimeLongDialogClick("去开启")
                                        mDismissGameTimeLongDialogFlag = true
                                        UsageStatsHelper.skipToUsageStats(
                                            mContext,
                                            UsageStatsHelper.USAGE_STATUS_REQUEST_CODE
                                        )
                                    }
                                }, object : CancelListener {
                                    override fun onCancel() {
                                        if (!mDismissGameTimeLongDialogFlag) {
                                            NewFlatLogUtils.logGameTimeLongDialogClick("关闭弹窗")
                                            mDismissGameTimeLongDialogFlag = true
                                        }
                                    }
                                }

                            )
                        }
                    }
                }
            }
            is FooterViewHolder -> {
                holder.initItemPadding()
                holder.initFooterViewHolder(mViewModel, mIsLoading, mIsNetworkError, mIsOver)
                holder.hint.setTextColor(R.color.text_subtitleDesc.toColor(mContext))
            }
        }
    }

    private fun hasHeader(): Boolean {
        return if (mIsMyPlayedGame && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
            !UsageStatsHelper.checkForPermission()
        } else {
            false
        }
    }

    override fun getItemViewType(position: Int): Int {
        if (position == itemCount - 1) {
            return ItemViewType.ITEM_FOOTER
        } else if (mEntityList[0].id.isEmpty() && position == 0) {
            return ItemViewType.ITEM_HEADER
        }
        return ItemViewType.GAME_NORMAL
    }

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

    class MyPlayedGameViewHolder(var binding: ItemPlayedGameBinding) : RecyclerView.ViewHolder(binding.root) {
        fun initServerType(gameEntity: GameEntity) {
            val serverLabel = gameEntity.serverLabel
            when {
                gameEntity.test != null -> {
                    binding.gameItemIncluded.gameKaifuType.visibility = View.GONE
                    binding.gameItemIncluded.gameKaifuType.text = ""
                }
                serverLabel != null && !gameEntity.advanceDownload -> {
                    binding.gameItemIncluded.gameKaifuType.visibility = View.VISIBLE
                    binding.gameItemIncluded.gameKaifuType.text = serverLabel.value
                    if (gameEntity.isUseDefaultServerStyle()) {
                        binding.gameItemIncluded.gameKaifuType.background =
                            R.drawable.server_label_default_bg.toDrawable(binding.root.context)
                        binding.gameItemIncluded.gameKaifuType.setTextColor(R.color.text_server_label.toColor(binding.root.context))
                    } else {
                        binding.gameItemIncluded.gameKaifuType.background =
                            DrawableView.getServerDrawable(serverLabel.color)
                        binding.gameItemIncluded.gameKaifuType.setTextColor(R.color.white.toColor(binding.root.context))
                    }
                }
                else -> binding.gameItemIncluded.gameKaifuType.visibility = View.GONE
            }

            // 由于RecyclerView的复用机制 需要每次测量gameName的宽
            binding.gameItemIncluded.gameName.requestLayout()
        }
    }

    class UsageStatsViewHolder(var binding: ViewSimpleToggleBinding) : RecyclerView.ViewHolder(binding.root)

    fun resetListData() {
        if (!hasHeader()) EnergyBridge.postEnergyTask("open_game_time")
        setListData(mEntityList)
    }

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

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

    fun clearPositionAndPackageMap() {
        mPositionAndPackageMap.clear()
    }

    override fun getEventByPosition(pos: Int): ExposureEvent = mExposureEventSparseArray.get(pos)

    override fun getEventListByPosition(pos: Int) = null

}