package com.gh.common.util

import android.annotation.SuppressLint
import android.text.TextUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.common.utils.doOnMainProcessOnly
import com.gh.gamecenter.common.utils.toJson
import com.gh.gamecenter.common.utils.toObject
import com.gh.gamecenter.core.utils.MtaHelper
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import io.reactivex.schedulers.Schedulers

/**
 * 首页补充游戏库辅助类
 */
object GameSubstituteRepositoryHelper {

    private const val KEY_GAME_REPOSITORY = "game_substitute_repository"

    private var mSubstitutableGameIdSet = hashSetOf<String>()
    private var mApi = RetrofitManager.getInstance().api
    private var mApplicationContext = HaloApp.getInstance().application

    var gameCollectionList: List<SubjectEntity> = arrayListOf()

    init {
        loadSavedRepository()
    }

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

                    updateGameRepository(response)
                }
            })
    }

    @JvmStatic
    @SuppressLint("CheckResult")
    fun updateSubstitutableGames() {
        mApplicationContext.doOnMainProcessOnly {
            val single = if (UserManager.getInstance().isLoggedIn) {
                mApi.getIdListOfPlayedGames(UserManager.getInstance().userId, Utils.getTime(mApplicationContext))
            } else {
                mApi.getIdListOfDownloadedGames(HaloApp.getInstance().gid, Utils.getTime(mApplicationContext))
            }
            single.subscribeOn(Schedulers.io()).subscribe(object : BiResponse<List<String>>() {
                override fun onSuccess(data: List<String>) {
                    mSubstitutableGameIdSet = data.toHashSet()
                }
            })
        }
    }

    /**
     * 刷新内存中的游戏库（即从 SP 中再读一次）
     */
    @JvmStatic
    fun refreshRepositoryFromLocal() = loadSavedRepository()

    private fun loadSavedRepository() {
        gameCollectionList = SPUtils.getString(KEY_GAME_REPOSITORY).toObject() ?: arrayListOf()
    }

    private fun updateGameRepository(subjects: List<SubjectEntity>?) {
        if (subjects == null) return

        SPUtils.setString(KEY_GAME_REPOSITORY, subjects.toJson())

        gameCollectionList = subjects
    }

    /**
     * 从补充游戏库相应的专题中取出一个与其它游戏都不相同的游戏，为空时即为游戏用完或不存在该相应专题
     * @param collectionId 补充游戏库相应专题 ID
     * @param gameIdList 该专题里已经包含的游戏 ID 列表
     */
    private fun getOneUniqueGame(collectionId: String?, gameIdList: HashSet<String>): GameEntity? {
        collectionId?.let {
            val collection = gameCollectionList.find { it.id == collectionId }
            collection?.let {
                val game = collection.data?.find { game -> isThisGameUnique(game, gameIdList) }
                game?.let {
                    collection.data?.remove(game)
//                    collection.data?.size?.let { remainingSize ->
//                        // 记录被替换游戏的数量，10个以上的时候触发
//                        if (remainingSize % 10 == 0) {
//                            SentryHelper.onEvent("game_substitute", "substituted_size", "${50 - remainingSize}")
//                        }
//                    }
                    // 产品说要记录补充专题的曝光数，所以这个游戏附带了所在专题的名字
                    game.subjectName = collection.name
                    game.subjectId = collection.id
                    return game
                }
            }
        }
        return null
    }

    /**
     * 替换游戏，包括 已安装，历史下载，历史已安装等类型
     */
    fun replaceGames(
        gameList: MutableList<GameEntity>,
        alreadyDisplayedGameIdSet: HashSet<String>,
        relatedCollectionId: String,
        shouldLogReplaceEvent: Boolean
    ) {
        val positionOfTheGameToReplaceList = arrayListOf<Int>()

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

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

            var isThisPositionLabeled = false

            // 从 游戏ID 判断当前游戏是否需要被替换
            if (mSubstitutableGameIdSet.contains(game.id)) {
                positionOfTheGameToReplaceList.add(index)
                isThisPositionLabeled = true
            }

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

            // 若此游戏所包含的 apk 没有已安装，那么再检查是否已安装有预设相关包名
            if (!isThisPositionLabeled) {
                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)) {
                        positionOfTheGameToReplaceList.add(index)
                        break
                    }
                }
            }
        }

        if (positionOfTheGameToReplaceList.isNotEmpty()) {
            if (shouldLogReplaceEvent) {
                MtaHelper.onEvent("首页_加载", "启动光环", "替换游戏")
            }
            for (position in positionOfTheGameToReplaceList) {
                val replacingGame = getOneUniqueGame(relatedCollectionId, alreadyDisplayedGameIdSet)
                replacingGame?.let {
                    gameList[position] = replacingGame
                }
            }
        }
    }

    private fun isThisGameUnique(game: GameEntity, gameIdList: HashSet<String>): Boolean {
        // 判断该游戏是否出现在已安装列表
        if (mSubstitutableGameIdSet.contains(game.id)) return false

        // 该补充游戏是否已经存在关联关系
        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)
    }

}