package com.gh.gamecenter.servers.gametest2

import android.content.Context
import android.content.DialogInterface
import android.os.Build
import android.os.Bundle
import android.util.SparseArray
import android.view.View
import android.view.ViewGroup
import androidx.collection.ArrayMap
import androidx.collection.arrayMapOf
import androidx.core.view.updateLayoutParams
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.exposure.ExposureListener
import com.gh.common.exposure.IExposable
import com.gh.common.util.DialogUtils
import com.gh.common.util.DownloadItemUtils
import com.gh.common.xapk.XapkInstaller
import com.gh.common.xapk.XapkUnzipStatus
import com.gh.download.DownloadManager
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.common.base.fragment.BaseBottomDialogFragment
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.toBinding
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.view.VerticalItemDecoration
import com.gh.gamecenter.common.viewholder.FooterViewHolder
import com.gh.gamecenter.databinding.DialogCollapsedGamesBinding
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.PageLocation
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.lightgame.adapter.BaseRecyclerAdapter
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import com.lightgame.utils.AppManager

class CollapsedGamesDialogFragment : BaseBottomDialogFragment<DialogCollapsedGamesBinding>() {
    private lateinit var gameList: ArrayList<GameEntity>
    private lateinit var exposureListener: ExposureListener
    private val adapter by lazy { CollapsedGamesAdapter() }
    private val locationMap: ArrayMap<String, ArrayList<Int>> = arrayMapOf()
    private var linkText = ""
    private var pageLocation: PageLocation? = null
    var exposureInvoke: ((GameEntity, Int) -> ExposureEvent)? = null

    private val dataWatcher: DataWatcher = object : DataWatcher() {
        override fun onDataChanged(downloadEntity: DownloadEntity) {
            val locationList = locationMap[downloadEntity.packageName]
            if (locationList != null) {
                for (location in locationList) {
                    gameList.getOrNull(location)?.let { gameEntity ->
                        DownloadItemUtils.processDate(gameEntity, downloadEntity, adapter, location)
                    }
                }
                if (XapkUnzipStatus.FAILURE.name == downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS]) {
                    for (position in locationList) {
                        val targetView = mBinding.gameRv.layoutManager?.findViewByPosition(position)
                        if (targetView != null) {
                            DialogUtils.showUnzipFailureDialog(requireContext(), downloadEntity)
                            break
                        }
                    }
                }
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        gameList = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            arguments?.getParcelableArrayList(EntranceConsts.KEY_GAME, GameEntity::class.java) ?: arrayListOf()
        } else {
            arguments?.getParcelableArrayList(EntranceConsts.KEY_GAME) ?: arrayListOf()
        }
        linkText = arguments?.getString(EntranceConsts.KEY_NAME, "") ?: ""
        pageLocation = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            arguments?.getParcelable(PageLocation::class.java.simpleName, PageLocation::class.java)
        } else {
            arguments?.getParcelable(PageLocation::class.java.simpleName)
        }
        initLocationMap()
    }

    private fun initLocationMap() {
        locationMap.clear()
        var list: ArrayList<Int>?
        gameList.forEachIndexed { index, gameEntity ->
            if (gameEntity.getApk().isNotEmpty()) {
                for (apk in gameEntity.getApk()) {
                    list = locationMap[apk.packageName]
                    if (list == null) {
                        list = ArrayList()
                        locationMap[apk.packageName] = list
                    }
                    list?.add(index)
                }
            }
        }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        mBinding.titleTv.text = "其他${gameList.size}款游戏"
        mBinding.closeIv.setOnClickListener {
            dismissAllowingStateLoss()
        }

        exposureListener = ExposureListener(this, adapter)
        mBinding.gameRv.run {
            layoutManager = LinearLayoutManager(requireContext())
            adapter = this@CollapsedGamesDialogFragment.adapter
            (itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
            addItemDecoration(VerticalItemDecoration(requireContext(), 12F, false, com.gh.gamecenter.common.R.color.transparent))
            addOnScrollListener(exposureListener)
        }
    }

    override fun onResume() {
        super.onResume()
        DownloadManager.getInstance().addObserver(dataWatcher)
    }

    override fun onPause() {
        super.onPause()
        DownloadManager.getInstance().removeObserver(dataWatcher)
    }

    override fun onDismiss(dialog: DialogInterface) {
        super.onDismiss(dialog)
        SensorsBridge.trackColumnTestClick(
            location = "其他游戏弹窗",
            recommendType = linkText,
            text = "关闭其他游戏弹窗",
            bottomTab = pageLocation?.bottomTab,
            multiTabName = pageLocation?.severalTabPageName,
            multiTabId = pageLocation?.severalTabPageId,
            position = pageLocation?.tabPosition,
            tabContent = pageLocation?.tabContent
        )
    }

    override fun onDarkModeChanged() {
        super.onDarkModeChanged()
        adapter.notifyItemRangeChanged(0, adapter.itemCount)
    }

    inner class CollapsedGamesAdapter : BaseRecyclerAdapter<RecyclerView.ViewHolder>(context), IExposable {
        private val exposureEventArray: SparseArray<ExposureEvent> = SparseArray()
        override fun getItemViewType(position: Int): Int {
            return if (position == itemCount - 1) {
                ITEM_FOOTER
            } else {
                ITEM_GAME
            }
        }

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
            return if (viewType == ITEM_GAME) {
                GameServerTestV2ItemViewHolder(parent.toBinding())
            } else {
                FooterViewHolder(mLayoutInflater.inflate(com.gh.gamecenter.common.R.layout.refresh_footerview, parent, false))
            }
        }

        override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
            if (holder is GameServerTestV2ItemViewHolder) {
                val gameEntity = gameList[position]
                pageLocation?.let {
                    val exposureEvent = exposureInvoke?.invoke(gameEntity, position)
                    exposureEventArray.put(position, exposureEvent)
                    holder.bindAttachGame(
                        holder,
                        gameEntity,
                        this,
                        "新游开测",
                        exposureEvent,
                        "其他游戏弹窗",
                        linkText,
                        it
                    )
                }
            }
            if (holder is FooterViewHolder) {
                holder.run {
                    itemView.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_background.toColor(mContext))
                    itemView.updateLayoutParams<ViewGroup.LayoutParams> {
                        height = 24F.dip2px()
                    }
                    loading.visibility = View.GONE
                    itemView.isClickable = false
                    hint.setText(com.gh.gamecenter.common.R.string.load_over_hint)
                }
            }
        }

        override fun getItemCount(): Int = if (gameList.isNotEmpty()) gameList.size + 1 else 0
        override fun getEventByPosition(pos: Int): ExposureEvent? = exposureEventArray.get(pos)
        override fun getEventListByPosition(pos: Int): List<ExposureEvent>? = null
    }

    companion object {
        private const val ITEM_GAME = 0
        private const val ITEM_FOOTER = 1

        @JvmStatic
        fun show(context: Context?, gameList: ArrayList<GameEntity>, linkText: String, pageLocation: PageLocation, exposureInvoke: (GameEntity, Int) -> ExposureEvent) {
            val fragmentActivity: FragmentActivity = if (context is FragmentActivity) {
                context
            } else if (BuildConfig.DEBUG) {
                throw IllegalStateException("CollapsedGamesDialogFragment context must be FragmentActivity")
            } else {
                val currentActivity = AppManager.getInstance().currentActivity()
                if (currentActivity is FragmentActivity) {
                    currentActivity
                } else {
                    throw IllegalStateException("current activity context must be FragmentActivity")
                }
            }

            // 防止重复弹出
            if (hasDialogInCurrentActivity(fragmentActivity)) return

            val addGamesDialog = CollapsedGamesDialogFragment().apply {
                val bundle = Bundle()
                bundle.putParcelableArrayList(EntranceConsts.KEY_GAME, gameList)
                bundle.putString(EntranceConsts.KEY_NAME, linkText)
                bundle.putParcelable(PageLocation::class.simpleName, pageLocation)
                arguments = bundle
                this.exposureInvoke = exposureInvoke
            }
            addGamesDialog.show(fragmentActivity.supportFragmentManager, CollapsedGamesDialogFragment::class.java.name)
        }

        private fun hasDialogInCurrentActivity(fragmentActivity: FragmentActivity): Boolean {
            val fragments: List<Fragment> = fragmentActivity.supportFragmentManager.fragments
            fragments.forEach { fragment ->
                if (fragment is CollapsedGamesDialogFragment) return true
            }
            return false
        }
    }
}