package com.gh.common.util

import android.content.Context
import android.text.TextUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.common.utils.toObject
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.manager.PackagesManager
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody

/**
 * 补充游戏库管理类
 */
object GameSubstituteRepositoryHelper {

    private const val SP_GAME_SUB = "sp_game_sub"
    private const val KEY_GAME_REPOSITORY = "game_substitute_repository"

    private var mApi = RetrofitManager.getInstance().api
    private var mApplicationContext = HaloApp.getInstance().application
    private val mGameSubSp by lazy { mApplicationContext.getSharedPreferences(SP_GAME_SUB, Context.MODE_PRIVATE) }

    private var mGameCollectionList: List<SubjectEntity>? = null // 游戏补充库

    /**
     * 获取游戏补充库
     */
    @JvmStatic
    fun updateGameSubstituteRepository() {
        mApi.reserveColumns
            .subscribeOn(Schedulers.io())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)

                    if (response != null) {
                        updateGameRepository(response)
                    }
                }
            })
    }

    private fun updateGameRepository(response: ResponseBody) {
        val responseContent = response.string()
        SPUtils.setString(mGameSubSp, KEY_GAME_REPOSITORY, responseContent)

        if (mGameCollectionList?.isEmpty() == true) {
            mGameCollectionList = responseContent.toObject()
        }
    }

    /**
     * 从补充游戏库相应的专题中取出一个与其它游戏都不相同的游戏，为空时即为游戏用完或不存在该相应专题
     * @param collectionId 补充游戏库相应专题 ID
     * @param gameIdList 该专题里已经包含的游戏 ID 列表
     */
    private fun getValidGame(collectionId: String?, gameIdList: HashSet<String>): GameEntity? {
        collectionId?.let {
            val collection = mGameCollectionList?.find { it.id == collectionId }
            collection?.let {
                val game = collection.data?.find { game -> isThisGameValid(game, gameIdList) }
                game?.let {
                    // 产品说要记录补充专题的曝光数，所以这个游戏附带了所在专题的名字
                    game.subjectName = collection.name
                    game.subjectId = collection.id
                    return game
                }
            }
        }
        return null
    }

    /**
     * 替换游戏，包括 已安装，历史下载，历史已安装等类型
     * @param gameList 需要被替换数据的游戏列表
     * @param displayingGameIdSet 页面正在显示的游戏 ID 列表，避免重复替换
     * @param relatedCollectionId 关联的替换合集 ID
     */
    fun replaceGames(
        gameList: MutableList<GameEntity>?,
        displayingGameIdSet: HashSet<String>,
        relatedCollectionId: String,
    ) {
        if (gameList == null) return

        // 需要被替换的游戏 position 列表
        val positionOfGameToBeReplacedList = arrayListOf<Int>()

        // 标记需要替换的已安装游戏
        for ((index, game) in gameList.withIndex()) {

            // 是大图形式的游戏时不标记替换
            if ((index == 0 && !gameList[0].image.isNullOrEmpty())) {
                continue
            }

            // 广告系统的广告游戏不替换
            if (game.adGroupId.isNotEmpty()) {
                continue
            }

            // 这个 position 的游戏是否需要被替换
            var thisPositionNeedToBeReplaced = false

            // 检查是否已安装该游戏里同包名的 APK
            for (apk in game.getApk()) {
                if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {
                    // 将该位置的游戏标记为需要替换
                    positionOfGameToBeReplacedList.add(index)
                    thisPositionNeedToBeReplaced = true
                    break
                }
            }

            // 检查是否已安装该游戏 id
            if (PackagesManager.getInstalledDataByGameId(game.id) != null) {
                // 将该位置的游戏标记为需要替换
                positionOfGameToBeReplacedList.add(index)
                thisPositionNeedToBeReplaced = true
                break
            }

            // 若此游戏所包含的 apk 没有已安装，那么再检查是否已安装有预设相关包名
            if (!thisPositionNeedToBeReplaced) {
                var relatedPackageList = arrayListOf<String>()
                for (entity in PackageHelper.relatedPackageList) {
                    if (entity.gameId == game.id) {
                        relatedPackageList = ArrayList(entity.packages!!)
                        break
                    }
                }

                for (packageName in relatedPackageList) {
                    if (PackageHelper.validLocalPackageNameSet.contains(packageName)) {
                        positionOfGameToBeReplacedList.add(index)
                        break
                    }
                }
            }
        }

        // 若待替换的位置列表不为空，尝试执行替换
        if (positionOfGameToBeReplacedList.isNotEmpty()) {
            if (mGameCollectionList == null) {
                mGameCollectionList = SPUtils.getString(mGameSubSp, KEY_GAME_REPOSITORY).toObject() ?: arrayListOf()
            }

            if (mGameCollectionList.isNullOrEmpty()) return

            for (position in positionOfGameToBeReplacedList) {
                val validGame = getValidGame(relatedCollectionId, displayingGameIdSet)
                validGame?.let {
                    gameList[position] = it
                    displayingGameIdSet.add(it.id)
                }
            }
        }
    }

    /**
     * 判断该游戏是否有效
     * @param game 需要判断的游戏
     * @param gameIdList 专题里已经包含的游戏 ID 列表
     */
    private fun isThisGameValid(
        game: GameEntity,
        gameIdList: HashSet<String>
    ): Boolean {
        // 该游戏是否与专题里已包含的游戏存在关联关系
        for (relatedId in game.relatedGameIds!!) {
            if (gameIdList.contains(relatedId)) {
                return false
            }
        }

        // 检查本地是否已安装该游戏，已过滤部分框架服务的包名
        for (apk in game.getApk()) {
            if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {
                return false
            }
        }
        return !gameIdList.contains(game.id) && !TextUtils.isEmpty(game.id)
    }

}