package com.gh.gamecenter.minigame.qq

import android.app.Application
import android.text.TextUtils
import androidx.collection.ArrayMap
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.util.GameSubstituteRepositoryHelper
import com.gh.common.util.GameUtils
import com.gh.gamecenter.common.baselist.LoadStatus
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.core.utils.RandomUtils
import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.entity.SubjectRecommendEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.GameSubjectData
import com.gh.gamecenter.feature.utils.ApkActiveUtils
import com.gh.gamecenter.game.BaseGameViewModel
import com.gh.gamecenter.game.GameViewModel
import com.gh.gamecenter.game.data.GameItemData
import com.gh.gamecenter.game.rank.RankCollectionAdapter
import com.gh.gamecenter.home.BlankDividerViewHolder
import com.gh.gamecenter.home.LegacyHomeFragmentAdapterAssistant
import com.gh.gamecenter.minigame.MiniGameRecentlyPlayUseCase
import com.gh.gamecenter.retrofit.RetrofitManager
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import retrofit2.HttpException
import kotlin.math.roundToInt

class QGameViewModel(application: Application, blockData: SubjectRecommendEntity?) :
    BaseGameViewModel(application, blockData) {

    private val mSensitiveApi = RetrofitManager.getInstance().newApi

    private var mSubjectList: MutableList<SubjectEntity> = ArrayList() // 专题

    private val mSubjectChangedMap: ArrayMap<String, List<GameEntity>> = ArrayMap() // 存储换一换的数据

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

    private var mIsLoading = false

    init {
        initData()
        EventBus.getDefault().register(this)// 为了减少对原有逻辑的影响，把EventBus注册在这里
    }

    override fun onInitData() {
        mSubjectList = arrayListOf()
        loadStatus.postValue(LoadStatus.INIT_LOADING)
        getQGameSubjectList()
    }

    override fun changeSubjectGame(subjectId: String) {
        mSensitiveApi
            .getSubjectQGame(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 getQGameSubjectList() {
        if (mIsLoading) return

        mSensitiveApi
            .subjectQGameList
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnNext {
                val hasRecentPlayed = it.any { subject ->
                    subject.type == "qq_game_horizontal_slide"
                }
                if (hasRecentPlayed && MiniGameRecentlyPlayUseCase.qqRecentGamesItemLiveData.value == null) {
                    MiniGameRecentlyPlayUseCase.loadRecentlyPlayedMiniGameList(Constants.QQ_MINI_GAME)
                }
            }
            .subscribe(object : Response<List<SubjectEntity>>() {
                override fun onResponse(response: List<SubjectEntity>?) {
                    if (response != null) {
                        when {
                            response.isEmpty() -> {
                                loadStatus.postValue(LoadStatus.LIST_OVER)
                            }

                            else -> {
                                mSubjectList.addAll(response)
                                loadStatus.postValue(LoadStatus.LIST_OVER)
                                transformItemData()
                            }
                        }
                    }
                    mIsLoading = false
                }

                override fun onFailure(e: HttpException?) {
                    loadStatus.postValue(LoadStatus.LIST_FAILED)
                    mIsLoading = false
                }
            })
    }

    // 随机产生专题数据(换一换)
    private fun initRandomGame(subjectId: String, sourceList: MutableList<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)
        }
        transformItemData()
    }

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

        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()
                }
            }
            //过滤掉游戏数量小于2个的视频横屏滑动专题
            if (item.type == "game_video_horizontal_slide") {
                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

            // 这个 for 循环主要功能是用来标识替换已安装的游戏
            if (!data.isNullOrEmpty()) {
                for (game in data) {
                    mSubjectGameIdList.add(game.id)
                }
            }

            if (!data.isNullOrEmpty()) {
                subjectEntity.relatedColumnId?.let {
                    GameSubstituteRepositoryHelper.replaceGames(data, mSubjectGameIdList, it)
                }
            }
            val shouldShowDivider = subjectEntity.type == "game" || subjectEntity.type == "video"
            // 是否不显示专题标题
            val hideSubjectName = !subjectEntity.showName

            // 判断是否添加顶部间距
            // 顶部 & 显示了分割线的 & 隐藏了专题标题的 item 不添加顶部间距
            if (index != 0
                && !shouldShowDivider
                && !hideSubjectName
                && !(subjectEntity.type == "game_list_collection" && subjectEntity.style == LegacyHomeFragmentAdapterAssistant.GAME_COLLECTION_VERTICAL_REFRESH_STYLE)
            ) {
                mItemDataListCache.add(getBlankSpacingItem())
            }

            if (shouldShowDivider) {
                mItemDataListCache.add(GameItemData().apply { lineDivider = GameViewModel.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 (!hideSubjectName
                && (subjectEntity.type != "column_collection"
                        && subjectEntity.type != "column_test_v2"
                        && subjectEntity.type != "community_article"
                        && subjectEntity.type != "question"
                        && subjectEntity.type != "bbs_video"
                        && subjectEntity.type != "news"
                        && subjectEntity.type != "game"
                        && subjectEntity.type != "video"
                        && subjectEntity.type != "game_explore"
                        && subjectEntity.type != "game_list_collection"
                        && subjectEntity.type != "qq_game_horizontal_slide"
                        && subjectEntity.type != "gallery")
                || (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,
                        )

                        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
            }

            // QQ小游戏-横屏滑动
            if (subjectEntity.type == "qq_game_horizontal_slide") {
                val itemQQHorizontalSlide = GameItemData()
                itemQQHorizontalSlide.qqHorizontalSlide = subjectEntity

                appendAdditionalInfoToSubjectGame(subjectEntity, index)
                mItemDataListCache.add(itemQQHorizontalSlide)

                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 == "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)
                // 小于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 == "gallery" || 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 (subjectEntity.type == "game_video_horizontal_slide") {
                val itemItemData = GameItemData().apply {
                    horizontalSlideVideo = subjectEntity
                }
                mItemDataListCache.add(itemItemData)
                itemItemData.horizontalSlideVideo?.data?.forEach {
                    addGamePositionAndPackage(it)
                }
                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,
                    )
                    val itemDataGame = GameItemData()
                    itemDataGame.game = game
                    mItemDataListCache.add(itemDataGame)
                    addGamePositionAndPackage(game)
                }
            }

            if (subjectEntity.type == "column_test_v2") {
                //新游开测 标题和全部按钮
                val head = GameItemData()
                val rightTopLink = subjectEntity.testV2Data?.rightTop?.link
                val indexRightTop = subjectEntity.testV2Data?.rightTop?.text
                head.columnHead =
                    SubjectEntity(
                        type = subjectEntity.type,
                        name = "新游开测",
                        indexRightTop = indexRightTop,
                        indexRightTopLink = rightTopLink
                    )
                mItemDataListCache.add(head)
                //新游开测 条目
                val item = GameItemData()
                item.gameTestV2Entity = subjectEntity.testV2Data
                mItemDataListCache.add(item)
                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
            }

            appendAdditionalInfoToSubjectGame(subjectEntity, index)
        }

        itemDataList.postValue(mItemDataListCache)
    }

    override fun getSubjectList() {
        loadStatus.postValue(LoadStatus.LIST_OVER)
    }

    override fun onCleared() {
        super.onCleared()
        EventBus.getDefault().unregister(this)
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onQGameSubjectUpdate(event: QGameSubjectUpdateEvent) {
        onInitData()
    }

    override fun replaceRefreshData(itemData: GameItemData): Boolean = false

    override fun refreshDiscoverCardData() = Unit

    override fun changeGameCollectionRefresh(collectionId: String, isRefreshClick: Boolean): Boolean = false

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

    companion object {

        fun notifyQGameSubjectUpdate() {
            EventBus.getDefault().post(QGameSubjectUpdateEvent())
        }
    }
}