package com.gh.gamecenter.manager

import android.text.TextUtils
import com.gh.common.constant.Config
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.entity.GameInstall
import com.gh.gamecenter.entity.GameUpdateEntity
import com.halo.assistant.HaloApp
import java.util.*

/**
 * todo 整理部分与[PackageUtils]冲突的方法
 */
object PackagesManager {

    // 存在网络延迟
    private var updateAndPluginList = ArrayList<GameUpdateEntity>()
    private val installedList = ArrayList<GameInstall>()

    // 实时更新(对应安装/卸载广播)
    private val installedPkgList = Collections.synchronizedList(ArrayList<String>())

    /**
     * 获取更新列表数量
     *
     * @return 更新列表数量
     */
    val updateListSize: Int get() = updateAndPluginList.size

    fun initInstallPkgList(list: List<String>) {
        installedPkgList.clear()
        installedPkgList.addAll(list)
    }

    /**
     * 初始化更新列表
     *
     * @param list 更新列表
     */
    fun initGameUpdate(list: ArrayList<GameUpdateEntity>) {
        updateAndPluginList = list
    }

    /**
     *
     * 初始化已安装列表
     *
     * @param list 已安装列表数据
     */
    fun initGameInstall(list: ArrayList<GameInstall>) {
        installedList.clear()
        installedList.addAll(list)
    }

    /**
     * 获取已安装游戏的包名list
     *
     * @return
     */
    @JvmStatic
    fun getInstalledList(): ArrayList<GameInstall> {
        return installedList
    }

    /**
     * 获取过滤同包名已安装游戏的包名list
     *
     * @return
     */
    @JvmStatic
    fun getFilterSameApkInstalledList(): ArrayList<GameInstall> {
        return filterSameApk(installedList)
    }

    /**
     * 获取过滤同游戏已安装游戏的包名list
     *
     * @return
     */
    @JvmStatic
    fun getFilterSameGameInstalledList(): ArrayList<GameInstall> {
        val map = HashMap<String, GameInstall>()
        for (gameInstall in filterSameApk(installedList)) {
            map[gameInstall.id!!] = gameInstall
        }
        return ArrayList(map.values)
    }

    /**
     * 获取可更新游戏列表
     *
     * @return 可更新游戏列表
     */
    fun getUpdateList(): ArrayList<GameUpdateEntity> {
        return updateAndPluginList
    }

    /**
     * 根据包名 判断是否安装该游戏
     *
     * @param packageName 包名
     * @return true 已安装 false 未安装
     */
    @JvmStatic
    fun isInstalled(packageName: String?): Boolean {
        if (TextUtils.isEmpty(packageName)) {
            return false
        }

        // TODO 检查为什么 4.3.0 以后 arrayList.contains 也会触发 outOfBounds 异常，而以前不会，因为 kotlin 版本更新?
        // 先简单改成 SynchronizedList
        return installedPkgList.contains(packageName) && PackageUtils.isInstalled(HaloApp.getInstance(), packageName)
    }

    /**
     * 根据包名版本号判断是否已安装相应版本的应用
     *
     * @param packageName 包名
     * @param versionName 版本号
     * @return true 已安装 false 未安装
     */
    @JvmStatic
    fun isInstalledWithSpecificVersion(packageName: String?, versionName: String): Boolean {
        if (TextUtils.isEmpty(packageName)) {
            return false
        }

        return if (isInstalled(packageName)) {
            val installData = getInstalledData(packageName)
            installData?.version == versionName
        } else {
            false
        }
    }

    /**
     * 根据包名 获取已安装的信息
     *
     * @param packageName 包名
     * @return 如果为空：未安装
     */
    @JvmStatic
    fun getInstalledData(packageName: String?): GameInstall? {
        if (TextUtils.isEmpty(packageName)) {
            return null
        }
        for (gameInstall in installedList) {
            if (gameInstall.packageName == packageName) {
                return gameInstall
            }
        }
        return null
    }


    /**
     * 判断包名是否可以更新
     *
     * @param packageName 包名
     * @return true 可以更新 false 不可以更新
     */
    fun isCanUpdate(gameId: String?, packageName: String?): Boolean {
        for (entity in updateAndPluginList) {
            if (!entity.isPluggable && entity.packageName == packageName && entity.id == gameId) {
                return true
            }
        }
        return false
    }

    /**
     * 判断包名是否可以插件化
     */
    fun isCanPluggable(gameId: String?, packageName: String?): Boolean {
        if (gameId.isNullOrEmpty() || packageName.isNullOrEmpty()) return false
        for (entity in updateAndPluginList) {
            if (entity.isPluggable && gameId == entity.id && packageName == entity.packageName) {
                return true
            }
        }
        return false
    }

    /**
     * 根据游戏Id获取已安装的游戏数据
     */
    @JvmStatic
    fun findInstallById(gameId: String?): GameInstall? {
        if (TextUtils.isEmpty(gameId)) return null
        for (gameInstall in installedList) {
            if (gameId == gameInstall.id) {
                return gameInstall
            }
        }
        return null
    }


    /**
     * 根据游戏Id获取已安装的游戏数据
     */
    @JvmStatic
    fun findInstallByIdExcludeBlackPackage(gameId: String?): GameInstall? {
        if (TextUtils.isEmpty(gameId)) return null

        val list: List<GameInstall> = filterDownloadBlackPackage(installedList) ?: return null
        for (gameInstall in list) {
            if (gameId == gameInstall.id) {
                return gameInstall
            }
        }
        return null
    }

    /**
     * 过滤同包名游戏,取最后一个
     * @return
     */
    @JvmStatic
    fun filterSameApk(installedList: List<GameInstall>?): ArrayList<GameInstall> {
        val map = HashMap<String, GameInstall>()
        if (installedList != null) {
            for (gameInstall in installedList) {
                map[gameInstall.packageName] = gameInstall
            }
        }
        return ArrayList(map.values)
    }

    @JvmStatic
    fun filterDownloadBlackPackage(installedList: MutableList<GameInstall>?): List<GameInstall>? {
        if (installedList == null) return ArrayList()
        val blackList = Config.getSettings()?.gameDownloadBlackList ?: return installedList

        var i = 0
        while (i < installedList.size) {
            val data = installedList[i]
            if (blackList.contains(data.packageName)) {
                installedList.remove(data)
                i--
            }
            i++
        }

        return ArrayList(installedList)
    }
}
