package com.gh.gamecenter.packagehelper

import android.annotation.SuppressLint
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.toRequestBody
import com.gh.gamecenter.common.utils.tryWithDefaultCatch
import com.gh.gamecenter.entity.PackageFilter
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.room.AppDatabase
import com.halo.assistant.HaloApp
import io.reactivex.schedulers.Schedulers

class PackageFilterManager {

    private var mPackageKey = "" // 用于下次获取包名-游戏信息的 key

    val packageKey: String
        get() = mPackageKey

    /**
     * 更新收录游戏的包名列表
     * @param packageList 列表
     * @param appendOnly 是否仅添加部分数据，不清空旧数据
     * @param callbackClosure 结果回调
     */
    @SuppressLint("CheckResult")
    fun updateFilterPackages(
        packageList: List<String>,
        appendOnly: Boolean = true,
        callbackClosure: ((list: ArrayList<String>) -> Unit)? = null
    ) {

        val finalPackageList = ArrayList(packageList)

        if (appendOnly) {
            // 添加因为异常而没能正常更新的包名列表
            synchronized(PackageRepository.mPendingPackageNameSet) {
                finalPackageList.addAll(PackageRepository.mPendingPackageNameSet)
            }
        }

        RetrofitManager.getInstance()
            .newApi
            .postInstalledAppList(finalPackageList.toRequestBody())
            .subscribeOn(Schedulers.io())
            .subscribe(object : BiResponse<PackageFilter>() {
                override fun onSuccess(data: PackageFilter) {
                    mPackageKey = data.key
                    synchronized(PackageRepository.mPendingPackageNameSet) {
                        PackageRepository.mPendingPackageNameSet.removeAll(finalPackageList)
                    }

                    val partialPackageList = arrayListOf<String>()

                    if (!appendOnly) {
                        PackageRepository.mValidPackageNameSet.clear()
                        tryWithDefaultCatch {
                            AppDatabase.getInstance().packageFilterDao().deleteAllPackageName()
                        }
                    }

                    for (packageName in data.packages) {
                        tryWithDefaultCatch {
                            AppDatabase.getInstance().packageFilterDao().addPackageName(
                                FilterPackageNameEntity(packageName)
                            )
                        }

                        partialPackageList.add(packageName)
                        PackageRepository.mValidPackageNameSet.add(packageName)
                    }

                    if (appendOnly) {
                        callbackClosure?.invoke(ArrayList(partialPackageList))
                    } else {
                        callbackClosure?.invoke(ArrayList(PackageRepository.mValidPackageNameSet))
                    }
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)

                    if (appendOnly) {
                        synchronized(PackageRepository.mPendingPackageNameSet) {
                            PackageRepository.mPendingPackageNameSet.addAll(finalPackageList)
                        }
                        callbackClosure?.invoke(ArrayList(PackageRepository.mValidPackageNameSet))
                    } else {
                        if (exception is retrofit2.HttpException && exception.code() == 403) {
                            // 403 代表 key 过期，需要重新获取
                            callbackClosure?.invoke(arrayListOf())
                            return
                        }

                        // 接口访问失败时从数据库读取上一次缓存的已安装收录列表进行更新
                        val packageEntityList =
                            AppDatabase.getInstance().packageFilterDao().getAllPackageName()
                        for (packageEntity in packageEntityList) {
                            // 依然为已安装状态才加入到有效包名列表中
                            if (PackageUtils.isInstalled(HaloApp.getInstance(), packageEntity.packageName)) {
                                PackageRepository.mValidPackageNameSet.add(packageEntity.packageName)
                            }
                        }

                        callbackClosure?.invoke(ArrayList(PackageRepository.mValidPackageNameSet))
                    }
                }
            })
    }
}