package com.gh.gamecenter.home.custom.model

import androidx.annotation.MainThread
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.asLiveData
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.Constants.SP_HIDDEN_NOTIFICATIONS
import com.gh.gamecenter.common.utils.observableToMain
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.common.utils.toJson
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.entity.DiscoveryCardEntity
import com.gh.gamecenter.entity.DiscoveryGameCardEntity
import com.gh.gamecenter.entity.DiscoveryGameCardLabel
import com.gh.gamecenter.feature.entity.AcctRecord
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.gamedetail.accelerator.AccelerationDataBase
import com.gh.gamecenter.retrofit.RetrofitManager
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.halo.assistant.HaloApp
import io.reactivex.disposables.CompositeDisposable

/**
 * 由于多个自定义页面可能共用同一份数据，这里使用单例来全局保存多个页面共享的数据
 * 如：光环推荐
 */
class CustomPageShareRepository private constructor() {

    private val apiService = RetrofitManager.getInstance().api

    private val compositeDisposable = CompositeDisposable()

    private val _discoverData = MutableLiveData<DiscoveryCardEntity>()
    val discoverData: LiveData<DiscoveryCardEntity> = _discoverData

    fun loadDiscoverCard() {
        val paramsMap = if (SPUtils.getBoolean(Constants.SP_DISCOVER_FORCE_REFRESH)) {
            mapOf("refresh" to "true")
        } else {
            mapOf()
        }
        apiService.getDiscoveryGames(1, paramsMap)
            .zipWith(apiService.cardLabels) { t1, t2 ->
                SPUtils.setBoolean(Constants.SP_DISCOVER_FORCE_REFRESH, false)
                DiscoveryCardEntity(
                    RegionSettingHelper.filterGame(t1.filterDiscoverGames()),
                    filterDiscoveryLabel(t1, t2)
                )
            }
            .compose(observableToMain())
            .subscribe(_discoverData::setValue) {
                /* no implement */
            }
            .let(compositeDisposable::add)


    }

    private fun DiscoveryGameCardEntity.filterDiscoverGames(): List<GameEntity> {
        val tempList = arrayListOf<GameEntity>()
        tempList.addAll(games)
        // 删除已安装的游戏
        tempList.removeAll {
            it.getApk().isNotEmpty() &&
                    PackageUtils.isInstalled(HaloApp.getInstance().application, it.getApk()[0].packageName)
        }
        return tempList.take(18)
    }

    // 过滤分组，现只需要"卡片一"分组
    private fun filterDiscoveryLabel(
        discoveryGameCardEntity: DiscoveryGameCardEntity,
        discoveryLabels: List<DiscoveryGameCardLabel>
    ): List<DiscoveryGameCardLabel> {

        // 如果link_type为空需要在mUserTags/mGameTags中依次获取
        val gameTags = discoveryGameCardEntity.gameTags
        val userTags = discoveryGameCardEntity.userTags
        var gameTagIndex = 0
        var userTagIndex = 0
        val filteredLabels = discoveryLabels
            .filter {
                it.card == "卡片一"
            }
        filteredLabels.forEach { label ->
            when {
                userTagIndex in userTags.indices && label.type.isNullOrEmpty() -> {
                    val userTag = userTags[userTagIndex]
                    label.link = userTag.id
                    label.type = "tag"
                    label.linkText = userTag.name
                    label.title = userTag.name
                    userTagIndex++
                }

                gameTagIndex in gameTags.indices && label.type.isNullOrEmpty() -> {
                    val gameTag = gameTags[gameTagIndex]
                    label.link = gameTag.link
                    label.type = gameTag.type
                    label.linkText = gameTag.linkText
                    label.title = gameTag.linkText
                    gameTagIndex++
                }
            }

        }
        return filteredLabels
    }

    /**
     * 全局保存
     */
    private val _hiddenNotifications = MutableLiveData<HashMap<String, MutableSet<String>>>()
    val hiddenNotifications: LiveData<HashMap<String, MutableSet<String>>> = _hiddenNotifications

    fun initHiddenNotifications() {
        val json = SPUtils.getString(SP_HIDDEN_NOTIFICATIONS)
        if (json.isNotBlank()) {
            val typeToken = object : TypeToken<HashMap<String, MutableSet<String>>>() {}
            val map: HashMap<String, MutableSet<String>> = Gson().fromJson(json, typeToken.type)
            _hiddenNotifications.postValue(map)
        } else {
            _hiddenNotifications.postValue(hashMapOf())
        }
    }

    @MainThread
    fun hideNotificationItem(id: String, itemId: String) {
        var hasUpdated = false
        val notifications = _hiddenNotifications.value ?: hashMapOf()
        val itemSet = notifications[id]
        if (itemSet == null) {
            notifications[id] = mutableSetOf(itemId)
            hasUpdated = true
        } else {
            hasUpdated = itemSet.add(itemId)
        }
        if (hasUpdated) {
            val json = notifications.toJson()
            SPUtils.setString(SP_HIDDEN_NOTIFICATIONS, json)

            _hiddenNotifications.value = notifications
        }
    }

    private val _recentlyAcctRecord = MutableLiveData<List<AcctRecord>>()
    val recentlyAcctRecord: LiveData<List<AcctRecord>> = _recentlyAcctRecord
    private fun loadAcctRecordsFlow() {
        if (recentlyAcctRecord.value == null) {
            AccelerationDataBase.instance.accelerationDao().loadAcctRecordsObservable()
                .compose(observableToMain())
                .subscribe({
                    _recentlyAcctRecord.value = it
                }) {
                    /* no implement */
                }.let(compositeDisposable::add)
        }
    }

    /**
     * 请注意，这个方法只能在子线程调用
     * 此方法用于与自定义页面同步返回数据使用
     */
    fun loadRecentlyAcctGameInfos(): List<AcctRecord> {
        loadAcctRecordsFlow()
        return try {
            AccelerationDataBase.instance.accelerationDao().loadAcctRecords()
        } catch (e: Exception) {
            emptyList()
        }
    }


    // 这个方法要在用户退出首页时调用
    fun onClear() {
        compositeDisposable.clear()
    }

    companion object {

        val instance by lazy {
            CustomPageShareRepository()
        }
    }
}