package com.gh.gamecenter.game

import android.annotation.SuppressLint
import android.app.Application
import android.text.TextUtils
import androidx.collection.ArrayMap
import androidx.lifecycle.*
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.util.*
import com.gh.download.DownloadManager
import com.gh.gamecenter.common.baselist.LoadStatus
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.entity.ExposureEntity
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.countOccurrences
import com.gh.gamecenter.common.utils.debugOnly
import com.gh.gamecenter.common.utils.observableToMain
import com.gh.gamecenter.core.iinterface.IOffsetable
import com.gh.gamecenter.core.utils.RandomUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.UrlFilterUtils
import com.gh.gamecenter.entity.*
import com.gh.gamecenter.game.data.GameItemData
import com.gh.gamecenter.game.data.GameSubjectData
import com.gh.gamecenter.game.rank.RankCollectionAdapter
import com.gh.gamecenter.gamecollection.square.GameCollectionListItemData
import com.gh.gamecenter.home.BlankDividerViewHolder
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import retrofit2.HttpException
import kotlin.collections.set
import kotlin.math.roundToInt

class GameViewModel(application: Application, var blockData: SubjectRecommendEntity?) : AndroidViewModel(application),
    IOffsetable {

    private var mSlideList = ArrayList<LinkEntity>() // 轮播图
    private var mNavigationList = ArrayList<GameNavigationEntity>() // 导航栏
    private var mSubjectList: MutableList<SubjectEntity> = ArrayList() // 专题
    private var mSubjectDigestList = ArrayList<SubjectRecommendEntity>() // 专题入口

    private val mItemDataListCache: MutableList<GameItemData> = ArrayList()
    private val mSubjectChangedMap: ArrayMap<String, List<GameEntity>> = ArrayMap() // 存储换一换的数据
    private val mSubjectRefreshMap: ArrayMap<String, MutableList<GameEntity>> = ArrayMap() // 存储专题刷新数据
    private var mSmartSubject: SubjectEntity? = null // 猜你喜欢专题
    private var mDiscoveryGameCard: DiscoveryGameCardEntity? = null
    private var mDiscoveryGameCardLabels: List<DiscoveryGameCardLabel>? = null

    private var mSubjectPage = 1 // 专题分页
    private var mIsLoading = false
    private var mIsDiscoveryDataLoading = false // 是否正在获取发现页数据

    private val mSensitiveApi = RetrofitManager.getInstance().api

    private var mOffsetMap: HashMap<Int, Int> = hashMapOf()

    var entrance: String = ""
    var itemDataList: MediatorLiveData<List<GameItemData>> = MediatorLiveData()
    val loadStatus = MutableLiveData<LoadStatus>()
    val commandScrollTop = MutableLiveData<Any>()

    var positionAndPackageMap = HashMap<String, Int>() // key: packageName + position, value: position

    // 所有专题里的所有游戏 ID 的集合，供替换时排重用
    private var mSubjectGameIdList = hashSetOf<String>()

    init {
        if (blockData == null) {
            // 读取默认板块
            blockData = HomeBottomBarHelper.getDefaultGameBarData()
        }

        if (!blockData?.link.isNullOrEmpty()) {
            initData()
        }
    }

    fun initData() {
        mSlideList = arrayListOf()
        mNavigationList = arrayListOf()
        mSubjectList = arrayListOf()
        mSubjectGameIdList = hashSetOf()
        mSubjectDigestList = arrayListOf()
        mItemDataListCache.clear()

        loadStatus.postValue(LoadStatus.INIT_LOADING)

        getTopData(true)
        // 游戏库才需要展示"猜你喜欢"专题
        if (blockData?.text == "游戏库"
            && blockData?.name == "游戏库"
            && SPUtils.getBoolean(Constants.SP_PERSONAL_RECOMMEND, true)
        ) {
            getSmartColumn()
        }

        // 触发列表刷新行为时亦刷新内存中的备用游戏库列表
        GameSubstituteRepositoryHelper.refreshRepositoryFromLocal()
    }

    fun getTopData(initData: Boolean) {
        if (blockData == null) return
        if (blockData!!.display.navigation) {
            getGameNavigationData(initData)
        } else {
            getSlideData(initData)
        }
    }

    private fun getSlideData(initData: Boolean) {
        if (blockData != null && !blockData!!.display.slide) {
            if (initData) getSubjectDigest(initData)
            return
        }
        val observable = mSensitiveApi.getBlockSlides(blockData?.link)
        observable.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<List<LinkEntity>>() {
                override fun onResponse(response: List<LinkEntity>?) {
                    if (response != null) mSlideList = response as ArrayList<LinkEntity>
                    if (initData) getSubjectDigest(initData)
                }

                override fun onFailure(e: HttpException?) {
                    if (initData) getSubjectDigest(initData)
                }
            })
    }

    private fun getGameNavigationData(initData: Boolean) {
        if (blockData != null && !blockData!!.display.navigation) {
            if (initData) getSubjectDigest(initData)
            return
        }
        mSensitiveApi.getGameNavigations(blockData?.link)
            .compose(observableToMain())
            .subscribe(object : Response<GameNavigationWrapper>() {
                override fun onResponse(response: GameNavigationWrapper?) {
                    super.onResponse(response)
                    if (response != null) mNavigationList = response.data as ArrayList<GameNavigationEntity>
                    if (initData) getSubjectDigest(initData)
                }

                override fun onFailure(e: HttpException?) {
                    super.onFailure(e)
                    if (initData) getSubjectDigest(initData)
                }
            })
    }

    private fun getSmartColumn() {
        mSensitiveApi.blockSmartColumn
            .map {
                it.data = RegionSettingHelper.filterGame(it.data)
                val gameList = it.data
                if (gameList != null) {
                    for (game in gameList) {
                        ApkActiveUtils.filterHideApk(game)
                    }
                }
                it
            }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<SubjectEntity>() {
                override fun onResponse(response: SubjectEntity?) {
                    mSmartSubject = response
                }
            })
    }

    fun getSubjectDigest(initData: Boolean) {
        if (blockData != null && !blockData!!.display.recommend) {
            if (initData) getSubjectList(initData)
            return
        }

        mSensitiveApi.getBlockRecommends(blockData?.link)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<List<SubjectRecommendEntity>>() {
                override fun onResponse(response: List<SubjectRecommendEntity>?) {
                    if (response != null) mSubjectDigestList = response as ArrayList<SubjectRecommendEntity>
                    transformationItemData()
                    if (initData) {
                        getSubjectList(initData)
                    }
                }

                override fun onFailure(e: HttpException?) {
                    transformationItemData()
                    if (initData) {
                        getSubjectList(initData)
                    }
                }
            })
    }

    fun getSubjectList(initData: Boolean) {
        if (mIsLoading && !initData || loadStatus.value == LoadStatus.LIST_OVER) return
        mIsLoading = true

        if (initData) {
            mSubjectPage = 1
        } else {
            loadStatus.postValue(LoadStatus.LIST_LOADING)
        }

        mSensitiveApi.getBlockColumns(blockData?.link, mSubjectPage)
            .map {
                for (subjectEntity in it) {
                    subjectEntity.data = RegionSettingHelper.filterGame(subjectEntity.data)
                    val gameList = subjectEntity.data
                    if (gameList != null) {
                        for (game in gameList) {
                            ApkActiveUtils.filterHideApk(game)

                            // 当页面是由启动弹窗过来的第一或第二个页面的时候添加启动弹窗信息
                            if (entrance.contains(EntranceConsts.ENTRANCE_WELCOME)
                                && entrance.countOccurrences("+") <= 1
                            ) {
                                game.setWelcomeDialogInfoIfAvailable()
                            }
                        }
                    }
                }
                it
            }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<List<SubjectEntity>>() {
                override fun onResponse(response: List<SubjectEntity>?) {
                    if (response != null) {
                        when {
                            initData -> {
                                mSubjectList = response as MutableList<SubjectEntity>
                                loadStatus.postValue(LoadStatus.INIT_LOADED)
                                transformationItemData()
                            }
                            response.isEmpty() -> {
                                loadStatus.postValue(LoadStatus.LIST_OVER)
                            }
                            else -> {
                                mSubjectList.addAll(response)
                                loadStatus.postValue(LoadStatus.LIST_LOADED)
                                transformationItemData()
                            }
                        }
                        if (blockData?.display?.refresh == true) {
                            getBlockSubjectRefresh(response)
                        }

                    }
                    mSubjectPage++
                    mIsLoading = false
                }

                override fun onFailure(e: HttpException?) {
                    if (initData && mSlideList.isEmpty() && mSubjectDigestList.isEmpty()) {
                        loadStatus.postValue(LoadStatus.INIT_FAILED)
                    } else {
                        loadStatus.postValue(LoadStatus.LIST_FAILED)
                    }
                    mIsLoading = false
                }
            })
    }

    @SuppressLint("CheckResult")
    private fun getBlockSubjectRefresh(subjects: List<SubjectEntity>) {
        var columnIds = ""
        for (i in subjects.indices) {
            val subject = subjects[i]
            if ((subject.type == "game_horizontal_slide" || subject.type == "game_horizontal")
                && !mSubjectRefreshMap.contains(subject.id)
            ) {
                columnIds += subject.id
                if (i != subjects.size - 1) columnIds += "-"
            }
        }

        if (columnIds.isEmpty()) return
        mSensitiveApi.getBlockSubjectRefresh(UrlFilterUtils.getFilterQuery("column_ids", columnIds))
            .map {
                for (refreshEntity in it) {
                    for (game in refreshEntity.games) {
                        ApkActiveUtils.filterHideApk(game)

                        // 当页面是由启动弹窗过来的第一或第二个页面的时候添加启动弹窗信息
                        if (entrance.contains(EntranceConsts.ENTRANCE_WELCOME)
                            && entrance.countOccurrences("+") <= 1
                        ) {
                            game.setWelcomeDialogInfoIfAvailable()
                        }
                    }
                    RegionSettingHelper.filterGame(refreshEntity.games)
                }
                it
            }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<List<SubjectRefreshEntity>>() {
                override fun onSuccess(data: List<SubjectRefreshEntity>) {
                    for (entity in data) {
                        // 添加原始列表数据
                        for (subject in subjects) {
                            if (subject.id == entity.columnId) {
                                subject.data?.let {
                                    val originalList = ArrayList(it)
                                    if (originalList.isNotEmpty() && !originalList[0].image.isNullOrEmpty()) {
                                        originalList.removeAt(0) // 把游戏大图移出刷新内容
                                    }
                                    mSubjectRefreshMap[subject.id] = originalList
                                }

                                break
                            }
                        }

                        // 添加专题后续数据
                        val subjectRefreshData = mSubjectRefreshMap[entity.columnId]
                        if (subjectRefreshData != null) {
                            subjectRefreshData.addAll(entity.games)
                        } else {
                            mSubjectRefreshMap[entity.columnId] = entity.games as MutableList<GameEntity>
                        }
                    }
                }
            })
    }

    // 目前只需替换横向专题和横向滑动专题
    fun replaceRefreshData(itemData: GameItemData): Boolean {
        val horizontalColumn = itemData.horizontalColumn
        if (horizontalColumn != null) {
            return replaceHorizontalSubjectRefreshData(horizontalColumn)
        }

        val horizontalSlide = itemData.horizontalSlide
        if (horizontalSlide != null) {
            return replaceHorizontalSubjectRefreshData(horizontalSlide)
        }
        return false
    }

    private fun replaceHorizontalSubjectRefreshData(horizontalColumn: SubjectEntity): Boolean {
        val originalData = horizontalColumn.data ?: return false
        val refreshList = mSubjectRefreshMap[horizontalColumn.id] ?: return false

        // 注意:专题大图也在当前列表，替换时需要保留
        val originalImageData = if (originalData.isNotEmpty() && !originalData[0].image.isNullOrEmpty()) {
            originalData[0]
        } else null
        if (originalData.size == refreshList.size) return false

        val lastGameId = originalData[originalData.size - 1].id
        val replaceList: MutableList<GameEntity> = ArrayList()
        if (originalImageData != null) replaceList.add(originalImageData)

        // 在断点处开始取数据
        var beginFetchData = false
        for (refreshData in refreshList) {
            if (beginFetchData) replaceList.add(refreshData)
            if (refreshData.id == lastGameId) beginFetchData = true
            if (replaceList.size >= originalData.size) break
        }

        // 数据不足，按顺序重新获取
        if (originalData.size > replaceList.size) {
            replaceList.clear()
            if (originalImageData != null) replaceList.add(originalImageData)
            for (refreshData in refreshList) {
                replaceList.add(refreshData)
                if (replaceList.size >= originalData.size) break
            }
        }

        // 此时数据依然不足，数据处理出现错误
        if (originalData.size > replaceList.size) {
            debugOnly {
                throw IllegalStateException(
                    "error replacing subject refresh data ==> " +
                            " originalData size:" + originalData.size +
                            " replaceList size:" + replaceList.size
                )
            }
            return false
        }

        // 在此补充大图时原始数据和替换数据判断会有问题
//        if (originalData.isNotEmpty() && !originalData[0].image.isNullOrEmpty()) {
//            replaceList.add(0, originalData[0])
//            replaceList.removeAt(replaceList.size - 1)
//        }

        horizontalColumn.data = replaceList
        return true
    }

    fun changeSubjectGame(subjectId: String) {
        val list = mSubjectChangedMap[subjectId]
        if (list != null) {
            initRandomGame(subjectId, ArrayList(list))
        } else {
            getChangeSubjectGame(subjectId)
        }
    }

    //换一批
    private fun getChangeSubjectGame(subjectId: String) {
        mSensitiveApi
            .getSubjectGame(subjectId)
            .map(RegionSettingHelper.filterGame)
            .map(ApkActiveUtils.filterMapperList)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<List<GameEntity>>() {
                override fun onResponse(response: List<GameEntity>?) {
                    if (response != null) {
                        mSubjectChangedMap[subjectId] = response
                        initRandomGame(subjectId, java.util.ArrayList(response))
                    }
                }

                override fun onFailure(e: HttpException?) {
                    Utils.toast(getApplication(), "网络异常")
                }
            })

    }

    // 随机产生专题数据(换一换)
    private fun initRandomGame(subjectId: String, sourceList: List<GameEntity>?) {

        var rawList: MutableList<GameEntity>? = null
        for (entity in mSubjectList) {
            if (entity.id == subjectId) rawList = entity.data
        }
        if (rawList == null) return

        var sourceList = sourceList

        var size = rawList.size // 判断是否有大图

        var i = 0
        while (i < rawList.size) { //删除原数据，排除大图
            if (TextUtils.isEmpty(rawList[i].image)) {
                rawList.removeAt(i)
                i--
            } else {
                size--
            }
            i++
        }

        if (size * 2 <= sourceList!!.size) {
            sourceList = GameUtils.removeDuplicateData(rawList, sourceList)//排除重复
        }

        val indexes = RandomUtils.getRandomArray(size, sourceList!!.size)
        for (index in indexes) {
            val gameEntity = sourceList[index]
            rawList.add(gameEntity)
        }
        transformationItemData()
    }

    // 获取发现卡片数据
    private fun getDiscoverCardData() {
        val paramsMap = if (SPUtils.getBoolean(Constants.SP_DISCOVER_FORCE_REFRESH)) {
            mapOf("refresh" to "true")
        } else {
            mapOf()
        }
        val discoveryGamesObservable = mSensitiveApi.getDiscoveryGames(1, paramsMap).compose(observableToMain())
        val cardLabelsObservable = mSensitiveApi.cardLabels.compose(observableToMain())
        when {
            mDiscoveryGameCard == null && mDiscoveryGameCardLabels == null -> {
                Observable.mergeDelayError(cardLabelsObservable, discoveryGamesObservable)
                    .subscribe(object : Response<Any>() {
                        override fun onNext(response: Any) {
                            when (response) {
                                is ArrayList<*> -> mDiscoveryGameCardLabels =
                                    response as ArrayList<DiscoveryGameCardLabel>
                                is DiscoveryGameCardEntity -> mDiscoveryGameCard =
                                    response.apply {
                                        SPUtils.setBoolean(Constants.SP_DISCOVER_FORCE_REFRESH, false)
                                    }
                            }
                        }

                        override fun onFailure(e: HttpException?) {
                            mIsDiscoveryDataLoading = false
                        }

                        override fun onComplete() {
                            mIsDiscoveryDataLoading = false
                            filterDiscoverGames()
                            filterDiscoveryLabel()
                            transformationItemData()
                        }
                    })
            }
            mDiscoveryGameCard == null -> {
                discoveryGamesObservable.compose(observableToMain())
                    .subscribe(object : Response<DiscoveryGameCardEntity>() {
                        override fun onResponse(response: DiscoveryGameCardEntity?) {
                            mIsDiscoveryDataLoading = false
                            SPUtils.setBoolean(Constants.SP_DISCOVER_FORCE_REFRESH, false)
                            mDiscoveryGameCard = response
                            filterDiscoverGames()
                            filterDiscoveryLabel()
                            transformationItemData()
                        }
                    })
            }
            mDiscoveryGameCardLabels == null -> {
                cardLabelsObservable.compose(observableToMain())
                    .subscribe(object : Response<ArrayList<DiscoveryGameCardLabel>>() {
                        override fun onResponse(response: ArrayList<DiscoveryGameCardLabel>?) {
                            mIsDiscoveryDataLoading = false
                            mDiscoveryGameCardLabels = response
                            filterDiscoveryLabel()
                            transformationItemData()
                        }
                    })
            }
        }
    }

    fun refreshDiscoverCardData() {
        if (mDiscoveryGameCard != null) {
            val paramsMap = if (SPUtils.getBoolean(Constants.SP_DISCOVER_FORCE_REFRESH)) {
                mapOf("refresh" to "true")
            } else {
                mapOf()
            }
            val discoveryGamesObservable = mSensitiveApi.getDiscoveryGames(1, paramsMap).compose(observableToMain())
            val cardLabelsObservable = mSensitiveApi.cardLabels.compose(observableToMain())
            Observable.mergeDelayError(cardLabelsObservable, discoveryGamesObservable)
                .subscribe(object : Response<Any>() {
                    override fun onNext(response: Any) {
                        when (response) {
                            is ArrayList<*> -> mDiscoveryGameCardLabels =
                                response as ArrayList<DiscoveryGameCardLabel>
                            is DiscoveryGameCardEntity -> mDiscoveryGameCard =
                                response.apply {
                                    SPUtils.setBoolean(Constants.SP_DISCOVER_FORCE_REFRESH, false)
                                }
                        }
                    }

                    override fun onComplete() {
                        filterDiscoverGames()
                        filterDiscoveryLabel()
                        transformationItemData()
                    }
                })
        }
    }

    // 在保证游戏数量不少于18情况下过滤掉已安装游戏
    private fun filterDiscoverGames() {
        mDiscoveryGameCard?.run {
            val tempList = arrayListOf<GameEntity>()
            tempList.addAll(games)
            var i = 0
            // 删除已安装的游戏
            while (i < tempList.size) {
                val gameEntity = tempList[i]
                if (gameEntity.getApk().isNotEmpty() && PackageUtils.isInstalled(
                        HaloApp.getInstance().application,
                        gameEntity.getApk()[0].packageName
                    )
                ) {
                    tempList.removeAt(i)
                    i--
                }
                i++
            }
            games = if (tempList.size >= 18) {
                ArrayList(tempList.take(18))
            } else {
                ArrayList(games.take(18))
            }
        }
    }

    // 过滤分组，现只需要"卡片一"分组
    private fun filterDiscoveryLabel() {
        mDiscoveryGameCardLabels = mDiscoveryGameCardLabels?.filter { it.card == "卡片一" }
        // 如果link_type为空需要在mUserTags/mGameTags中依次获取
        val gameTags = mDiscoveryGameCard?.gameTags
        val userTags = mDiscoveryGameCard?.userTags
        var gameTagIndex = 0
        var userTagIndex = 0
        mDiscoveryGameCardLabels?.forEach { label ->
            if (!userTags.isNullOrEmpty() && userTags.size > userTagIndex && label.type.isNullOrEmpty()) {
                val userTag = userTags[userTagIndex]
                label.link = userTag.id
                label.type = "tag"
                label.linkText = userTag.name
                label.title = userTag.name
                userTagIndex++
            } else if (!gameTags.isNullOrEmpty() && gameTags.size > gameTagIndex && label.type.isNullOrEmpty()) {
                val gameTag = gameTags[gameTagIndex]
                label.link = gameTag.link
                label.type = gameTag.type
                label.linkText = gameTag.linkText
                label.title = gameTag.linkText
                gameTagIndex++
            }
        }
    }

    private fun transformationItemData() {
        mItemDataListCache.clear()
        positionAndPackageMap.clear()

        // 是否显示了"轮播图+导航栏+专题入口"
        var isTopItemShown = false

        // 轮播图+导航栏+专题入口
        if (blockData == null || blockData?.display?.recommend!! || blockData?.display?.slide!! || blockData?.display?.navigation!!) {
            isTopItemShown = true
            val itemDataTop = GameItemData()
            itemDataTop.slideList = mSlideList
            itemDataTop.navigationList = mNavigationList
            itemDataTop.subjectRecommend = mSubjectDigestList
            mItemDataListCache.add(itemDataTop)
        }

        // 专题列表插入"猜你喜欢"专题，"sort"代表插入位置
        if (mSmartSubject != null && mSubjectList.size > mSmartSubject!!.sort) {
            mSubjectList.add(mSmartSubject!!.sort, mSmartSubject!!)
            mSmartSubject = null // 防止重复插入
        }

        val iterator = mSubjectList.iterator()
        while (iterator.hasNext()) {
            val item = iterator.next()
            // 双列卡片专题过滤掉无封面图游戏
            if (item.type == "game_double_card") {
                item.data = item.data?.filter { it.columnImage.isNotBlank() }?.toMutableList()
                // 游戏数量小于2个不显示专题，所以直接去掉
                if ((item.data?.size ?: 0) < 2) {
                    iterator.remove()
                }
            }
        }

        // 专题 "type": "image/game_vertical/game_horizontal"
        for ((index, subjectEntity) in mSubjectList.withIndex()) {
            var containsImageBeforeHead = false // 在专题名上面是否有大图

            val data = subjectEntity.data
//            if (data == null || data.isEmpty()) continue

            // 这个 for 循环主要功能是用来标识替换已安装的游戏
            if (!data.isNullOrEmpty()) {
                for (game in data) {
                    mSubjectGameIdList.add(game.id)
                    // 应用专题是否显示游戏名后缀的配置
                    game.shouldShowNameSuffix = subjectEntity.showSuffix
                }
            }

            if (!data.isNullOrEmpty()) {
                subjectEntity.relatedColumnId?.let {
                    GameSubstituteRepositoryHelper.replaceGames(data, mSubjectGameIdList, it, false)
                }
            }
            val shouldShowDivider = subjectEntity.type == "game" || subjectEntity.type == "video"

            // 若在顶端则不添加空白间距
            if (!(!isTopItemShown && index == 0) && !shouldShowDivider) {
                mItemDataListCache.add(getBlankSpacingItem())
            }
            if (shouldShowDivider) {
                mItemDataListCache.add(GameItemData().apply { lineDivider = DEFAULT_DIVIDER })
            }

            if (!data.isNullOrEmpty() && !data[0].image.isNullOrEmpty() && subjectEntity.type != "column_collection") {
                val itemDataImage = GameItemData()
                val gameEntity = data[0]
                var isBigImageWithGame = false

                if (gameEntity.id.isNullOrEmpty()) gameEntity.id = gameEntity.link ?: ""

                appendAdditionalInfoToSubjectGame(subjectEntity, index)

                //  图片专题样式(后台操作->只显示(滑动))
                if (data[0].type == "column" && subjectEntity.type == "image_slide") {
                    itemDataImage.imageSlide = gameEntity
                    gameEntity.games?.let {
                        for ((i, g) in it.withIndex()) {
                            g.sequence = i
                            g.outerSequence = index
                        }
                    }
                } else {
                    itemDataImage.image = gameEntity
                    itemDataImage.image?.subjectData =
                        GameSubjectData(id = subjectEntity.id, name = subjectEntity.name, isOrder = false)
                    if (gameEntity.type == "game") {
                        isBigImageWithGame = true
                    }
                }

                containsImageBeforeHead = true
                mItemDataListCache.add(itemDataImage)

                // 确保下载按钮更新
                if (isBigImageWithGame) {
                    addGamePositionAndPackage(gameEntity)
                }

                mItemDataListCache.add(getBlankSpacingItem()) // 图片风格 item 后需要空白间距
                if (subjectEntity.type == "image" || subjectEntity.type == "image_slide") continue
            }

            if ((subjectEntity.type != "gallery"
                        && subjectEntity.type != "column_collection"
                        && subjectEntity.type != "community_article"
                        && subjectEntity.type != "question"
                        && subjectEntity.type != "bbs_video"
                        && subjectEntity.type != "news"
                        && subjectEntity.type != "game"
                        && subjectEntity.type != "video")
                || (subjectEntity.type == "column_collection" && subjectEntity.style != "top")
            ) {
                val itemDataHead = GameItemData()

                // 专题名称与大图间需要额外的空白间距
                if (containsImageBeforeHead) {
                    mItemDataListCache.add(getBlankSpacingItem())
                }

                appendAdditionalInfoToSubjectGame(subjectEntity, index)

                itemDataHead.columnHead = subjectEntity
                mItemDataListCache.add(itemDataHead)
            }

            // 裁剪排行榜数据数量
            if (subjectEntity.type == "column_collection" && subjectEntity.style == "top") {
                subjectEntity.columns.let { columns ->
                    for (column in columns) {
                        column.data =
                            ArrayList(column.data?.take(RankCollectionAdapter.MAX_RANK_ITEM_COUNT) ?: listOf())
                    }
                }
            }

            if (!data.isNullOrEmpty()) {
                if (subjectEntity.type == "game_vertical_slide") {
                    val itemVerticalSlide = GameItemData()
                    itemVerticalSlide.verticalSlide = subjectEntity
                    mItemDataListCache.add(itemVerticalSlide)

                    appendAdditionalInfoToSubjectGame(subjectEntity, index)

                    for (i in 0 until data.size) {
                        val game = data[i]
                        if (!game.image.isNullOrEmpty()) continue
                        game.subjectData = GameSubjectData(
                            id = subjectEntity.id,
                            name = subjectEntity.name,
                            tag = subjectEntity.tag,
                            position = i + if (data[0].image.isNullOrEmpty()) 1 else 0,
                            isOrder = subjectEntity.isOrder,
                            briefStyle = subjectEntity.briefStyle,
                            isShowSuffix = subjectEntity.showSuffix
                        )

                        addGamePositionAndPackage(game)
                    }
                    continue
                }
            }

            if (subjectEntity.type == "game_horizontal_slide") {
                val itemHorizontalSlide = GameItemData()
                itemHorizontalSlide.horizontalSlide = subjectEntity

                // 开测表数据，把全部转化为右上角跳转
                if (subjectEntity.indexRightTop == "all") {
                    subjectEntity.indexRightTopLink =
                        LinkEntity(text = subjectEntity.name, link = subjectEntity.id, type = "column_test")
                }

                appendAdditionalInfoToSubjectGame(subjectEntity, index)
                mItemDataListCache.add(itemHorizontalSlide)
                continue
            }

            if (subjectEntity.type == "game_horizontal") {
                val itemDataSubject = GameItemData()
                itemDataSubject.horizontalColumn = subjectEntity
                appendAdditionalInfoToSubjectGame(subjectEntity, index)
                mItemDataListCache.add(itemDataSubject)
                continue
            }

            if (subjectEntity.type == "column_collection" && subjectEntity.style != "top") {
                val itemColumnCollection = GameItemData()
                itemColumnCollection.columnCollection = subjectEntity
                appendAdditionalInfoToSubjectGame(subjectEntity, index)
                mItemDataListCache.add(itemColumnCollection)
                continue
            }

            if (subjectEntity.type == "column_collection" && subjectEntity.style == "top") {
                val itemColumnCollection = GameItemData()
                itemColumnCollection.rankCollection = subjectEntity
                mItemDataListCache.add(itemColumnCollection)
                appendAdditionalInfoToRankSubjectGame(subjectEntity, index)
                continue
            }

            if (subjectEntity.type == "common_collection") {
                if (subjectEntity.homePageStyle == "1-2") {
                    // 样式为一行两个的时候把数据拆分为若干个一行两个的小item，根据 offset 来在原数据中的获取数据
                    var lineCount = (((subjectEntity.commonCollectionList?.size ?: 0).toDouble()) / 2).roundToInt()
                    if (!TextUtils.isEmpty(subjectEntity.verticalLine)) {
                        val serverSideLineCount = subjectEntity.verticalLine.toInt()
                        if (lineCount == 0 || serverSideLineCount < lineCount) {
                            lineCount = serverSideLineCount
                        }
                    }

                    for (i in 0 until lineCount) {
                        if (i == 0) {
                            mItemDataListCache.add(GameItemData().apply { blankDivider = 12F })
                        } else {
                            if (subjectEntity.style == "img-list") {
                                mItemDataListCache.add(GameItemData().apply { blankDivider = 12F })
                            }
                        }

                        val itemDataSubject = GameItemData()
                        itemDataSubject.commonLinkCollection12 = subjectEntity
                        appendAdditionalInfoToSubjectGame(subjectEntity, index)
                        itemDataSubject.offset = i * 2
                        mItemDataListCache.add(itemDataSubject)
                    }
                } else {
                    val itemCommonCollection = GameItemData()
                    itemCommonCollection.commonLinkCollection = subjectEntity
                    appendAdditionalInfoToSubjectGame(subjectEntity, index)
                    mItemDataListCache.add(itemCommonCollection)
                }

                continue
            }

            if (subjectEntity.type == "gallery") {
                val itemItemData = GameItemData()
                itemItemData.gallery = subjectEntity
                appendAdditionalInfoToSubjectGame(subjectEntity, index)
                // 小于7就不要展示了
                if (subjectEntity.data != null && subjectEntity.data!!.size >= 7) {
                    for ((index, game) in subjectEntity.data!!.withIndex()) {
                        game.sequence = index
                    }
                    mItemDataListCache.add(itemItemData)
                }
                continue
            }

            if (subjectEntity.type == "gallery_slide") {
                val itemItemData = GameItemData()
                itemItemData.gallerySlide = subjectEntity
                appendAdditionalInfoToSubjectGame(subjectEntity, index)
                // 小于3就不要滚动了
                if (subjectEntity.data != null && subjectEntity.data!!.size > 3) {
                    for ((index, game) in subjectEntity.data!!.withIndex()) {
                        game.sequence = index
                    }
                    mItemDataListCache.add(itemItemData)
                }
                continue
            }

            if (subjectEntity.type == "game_double_card") {
                val gameCount = subjectEntity.data?.size ?: continue

                for (i in 0 until gameCount) {
                    if (i % 2 == 0) {
                        if (i == 0) {
                            mItemDataListCache.add(GameItemData().apply { blankDivider = 12F })
                        }

                        val itemDataSubject = GameItemData()
                        itemDataSubject.doubleCardColumn = subjectEntity
                        itemDataSubject.offset = i
                        mItemDataListCache.add(itemDataSubject)
                    }
                }

                mItemDataListCache.add(GameItemData().apply { blankDivider = 12F })
                continue
            }

            if (subjectEntity.type == "community_article"
                || subjectEntity.type == "question"
                || subjectEntity.type == "bbs_video"
                || subjectEntity.type == "news"
            ) {
                val itemDataSubject = GameItemData()
                itemDataSubject.bigImageRecommend = subjectEntity
                mItemDataListCache.add(itemDataSubject)
                continue
            }

            if (!data.isNullOrEmpty()) {
                for (i in 0 until data.size) {
                    val game = data[i]
                    if (!game.image.isNullOrEmpty()) continue

                    // 第一个普通游戏顶部需要增加半高的填充间距
                    if (i == 0) {
                        mItemDataListCache.add(GameItemData().apply {
                            blankDivider = BlankDividerViewHolder.DEFAULT_BLANK_HEIGHT
                        })
                    }

                    game.subjectData = GameSubjectData(
                        id = subjectEntity.id,
                        name = subjectEntity.name,
                        tag = subjectEntity.tag,
                        position = i + if (data[0].image.isNullOrEmpty()) 1 else 0,
                        isOrder = subjectEntity.isOrder,
                        briefStyle = subjectEntity.briefStyle,
                        isShowSuffix = subjectEntity.showSuffix
                    )
                    val itemDataGame = GameItemData()
                    itemDataGame.game = game
                    mItemDataListCache.add(itemDataGame)
                    addGamePositionAndPackage(game)
                }
            }

            if (subjectEntity.type == "game_list_collection") {
                val gameCollectionItem = GameItemData()
                val itemDataList = arrayListOf<GameCollectionListItemData>().apply {
                    if (!subjectEntity.gameListCollection.isNullOrEmpty()) {
                        var position = 0
                        for (item in subjectEntity.gameListCollection!!) {
                            add(
                                GameCollectionListItemData(
                                    gameCollectionItem = item,
                                    gameStartPosition = position,
                                    outerSequence = subjectEntity.outerSequence + 1
                                )
                            )
                            position += if (item.count?.game!! > 2) 3 else if (item.games?.size == 0) 0 else
                                item.count?.game ?: 0
                        }
                    }
                }
                gameCollectionItem.gameCollection = itemDataList
                appendAdditionalInfoToSubjectGame(subjectEntity, index)
                mItemDataListCache.add(gameCollectionItem)
                continue
            }

            if (subjectEntity.type == "game" || subjectEntity.type == "video") {
                val itemItemData = GameItemData()
                itemItemData.attachGame = subjectEntity
                appendAdditionalInfoToSubjectGame(subjectEntity, index)
                mItemDataListCache.add(itemItemData)
                subjectEntity.linkGame?.let {
                    addGamePositionAndPackage(it)
                }
                continue
            }

            if (subjectEntity.type == "game_explore") {
                if (mDiscoveryGameCard == null || mDiscoveryGameCardLabels == null) {
                    if (!mIsDiscoveryDataLoading) {
                        mIsDiscoveryDataLoading = true
                        getDiscoverCardData()
                    }
                } else {
                    val itemItemData = GameItemData().apply {
                        discoverCard = DiscoveryCardEntity(
                            mDiscoveryGameCard?.games ?: arrayListOf(),
                            mDiscoveryGameCardLabels ?: listOf()
                        )
                    }
                    mItemDataListCache.add(itemItemData)
                    mDiscoveryGameCard?.games?.forEach {
                        addGamePositionAndPackage(it)
                    }
                }
                continue
            }

            appendAdditionalInfoToSubjectGame(subjectEntity, index)
        }

        itemDataList.postValue(mItemDataListCache)
    }

    private fun addGamePositionAndPackage(game: GameEntity) {
        var packages = ""
        for (apkEntity in game.getApk()) {
            packages += apkEntity.packageName
        }
        positionAndPackageMap[packages + (mItemDataListCache.size - 1)] = mItemDataListCache.size - 1
        game.gameLocation = GameEntity.GameLocation.INDEX
        game.setEntryMap(DownloadManager.getInstance().getEntryMap(game.name))
    }

    /**
     * 获取填充间距的空白 item
     */
    private fun getBlankSpacingItem() =
        GameItemData().apply { blankDivider = BlankDividerViewHolder.DEFAULT_BLANK_HEIGHT * 2 }

    override fun getOffset(position: Int) = mOffsetMap[position] ?: 0

    override fun updateOffset(position: Int, offset: Int) {
        mOffsetMap[position] = offset
    }

    override fun resetOffset() {
        mOffsetMap.clear()
    }

    private fun appendAdditionalInfoToSubjectGame(subject: SubjectEntity, outerPosition: Int) {
        subject.outerSequence = outerPosition
        subject.data?.let {
            for ((index, game) in it.withIndex()) {
                // 开测表不是专题不需要补充专题 id
                if (subject.tag != "test") {
                    game.subjectId = subject.id
                }
                game.sequence = index
                game.containerId = blockData?.link
                game.containerType = ExposureEntity.BLOCK_ID
                game.outerSequence = outerPosition
            }
        }
    }

    private fun appendAdditionalInfoToRankSubjectGame(subject: SubjectEntity, outerPosition: Int) {
        subject.columns.forEach {
            it.data?.forEachIndexed { index, game ->
                if (subject.tag != "test") {
                    game.subjectId = subject.id
                }
                game.sequence = index
                game.outerSequence = outerPosition
                game.containerId = blockData?.link
                game.containerType = ExposureEntity.BLOCK_ID
                addGamePositionAndPackage(game)
            }
        }
    }

    /**
     * 是否显示为游戏库
     */
    fun isGameRepo(): Boolean {
        return blockData?.name?.contains("游戏库") == true
    }

    class Factory(val mApplication: Application, val blockData: SubjectRecommendEntity?) :
        ViewModelProvider.NewInstanceFactory() {
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return GameViewModel(mApplication, blockData) as T
        }
    }

    companion object {
        const val DEFAULT_DIVIDER = 1F
    }
}