package com.gh.gamecenter.message

import android.annotation.SuppressLint
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import com.gh.gamecenter.common.constant.Constants
import com.gh.common.util.CheckLoginUtils
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.common.utils.createRequestBody
import com.gh.gamecenter.db.GameTrendsDao
import com.gh.gamecenter.db.info.GameTrendsInfo
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.entity.*
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.retrofit.service.ApiService
import com.google.gson.reflect.TypeToken
import com.halo.assistant.HaloApp
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Function4
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import retrofit2.HttpException

object MessageUnreadRepository {

    private var mApi: ApiService = RetrofitManager.getInstance().api
    private var isLoading: Boolean = false

    val unreadLiveData = MediatorLiveData<MessageUnreadEntity>()
    var firstTimeInit: Boolean = true  // 用来标记本类是否是第一次调用 [loadMessageUnreadData] 方法
    val mGameTrendsDao = GameTrendsDao(HaloApp.getInstance().application)
    val unreadMessageTotal = MutableLiveData<Boolean>()//我的光环小红点通知
    val zixunConcern = MutableLiveData<Boolean>()//游戏动态通知
    val addonsUnread = MutableLiveData<AddonsUnreadEntity>()

    fun loadMessageUnreadData() {
        if (isLoading && UserManager.getInstance().token == null) return
        isLoading = true

        mApi.getMessageUnread(UserManager.getInstance().userId)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<MessageUnreadEntity>() {
                override fun onResponse(response: MessageUnreadEntity?) {
                    isLoading = false
                    unreadLiveData.postValue(response)
                }

                override fun onFailure(e: HttpException?) {
                    isLoading = false
                }
            })
    }

    @SuppressLint("CheckResult")
    fun loadMessageUnreadTotal(isRecordData: Boolean = false) {
        Observable.zip(getMessageUnread(), getDiscoveryData(), getNewAddonsData(), getAddonsUnreadCount(),
            Function4<Int, Int, Int, Int, Boolean> { t1, t2, t3, t4 ->
                zixunConcern.postValue(t2 > 0)
                if (isRecordData) {
                    addUnreadRecord(t1, t2, t3, t4)
                    SPUtils.setString(
                        Constants.SP_PRIVACY_MINE_MD5, SPUtils.getString(
                            Constants.SP_PRIVACY_CURRENT_MD5
                        )
                    )
                }
                val isSameAsLast = checkDataIsSameAsLast(t1, t2, t3, t4)
                val privacyIsSame = checkPrivacyIsSame()
                unreadMessageTotal.postValue(!isSameAsLast || !privacyIsSame)
                t1 > 0 || t2 > 0 || t3 > 0 || t4 > 0
            }).subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {}

    }

    private fun getMessageUnread(): Observable<Int> {
        return Observable.create {
            if (CheckLoginUtils.isLogin()) {
                mApi.getMessageUnread(UserManager.getInstance().userId)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : Response<MessageUnreadEntity>() {
                        override fun onResponse(response: MessageUnreadEntity?) {
                            it.onNext(response?.total ?: 0)
                            it.onComplete()
                        }

                        override fun onFailure(e: HttpException?) {
                            it.onNext(0)
                            it.onComplete()
                        }
                    })
            } else {
                it.onNext(0)
                it.onComplete()
            }
        }
    }

    private fun getDiscoveryData(): Observable<Int> {
        return Observable.create {
            if (CheckLoginUtils.isLogin()) {
                mApi.getZiXunConcern(UserManager.getInstance().userId, 1)
                    .subscribeOn(Schedulers.io())
                    .subscribe(object : Response<List<ConcernEntity>>() {
                        override fun onResponse(response: List<ConcernEntity>?) {
                            super.onResponse(response)
                            if (response != null && response.isNotEmpty()) {
                                val entity = response[0]
                                val internetPostTime = entity.time
                                val trendsInfo = mGameTrendsDao.findGameTrendsInfo(UserManager.getInstance().userId)
                                val localInternetPostTime = trendsInfo?.internetPostTime ?: 0
                                // 当上一个条产生小红点的条目不存在或者有新的条目时更新数据库
                                if (localInternetPostTime == 0L || localInternetPostTime < internetPostTime) {
                                    mGameTrendsDao.add(
                                        GameTrendsInfo(
                                            UserManager.getInstance().userId,
                                            internetPostTime,
                                            0,
                                            entity.gameIcon
                                        )
                                    )
                                    it.onNext(1)
                                } else {
                                    if (trendsInfo != null) {
                                        if (trendsInfo.readPostTime > 0) {
                                            it.onNext(0)
                                        } else {
                                            it.onNext(1)
                                        }
                                    }
                                }
                                it.onComplete()
                            } else {
                                it.onNext(0)
                                it.onComplete()
                            }
                        }
                    })
            } else {
                it.onNext(0)
                it.onComplete()
            }
        }

    }

    @SuppressLint("CheckResult")
    private fun getNewAddonsData(): Observable<Int> {
        var count = 0
        return Observable.create {
            mApi.newHaloAddons
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : BiResponse<ArrayList<HaloAddonEntity>>() {
                    override fun onSuccess(data: ArrayList<HaloAddonEntity>) {
                        val funcHaveReadRecord: HashSet<String> =
                            SPUtils.getStringSet(Constants.SP_ADDONS_FUNCS_HAVE_READ) as HashSet<String>
                        val recommendHaveReadRecord: HashSet<String> =
                            SPUtils.getStringSet(Constants.SP_ADDONS_RECOMMEND_HAVE_READ) as HashSet<String>
                        data.forEach { group ->
                            if (group.groupType == "more_features") {
                                group.addons.forEach { addonLinkEntity ->
                                    if (addonLinkEntity.remind && !funcHaveReadRecord.contains(addonLinkEntity.id)) {
                                        count++
                                    }
                                }
                            }
                            if (group.groupType == "recommend") {
                                group.addons.forEach { addonLinkEntity ->
                                    if (addonLinkEntity.remind && !recommendHaveReadRecord.contains(addonLinkEntity.id)) {
                                        count++
                                    }
                                }
                            }
                        }
                        it.onNext(count)
                        it.onComplete()
                    }
                })
        }
    }

    private fun getAddonsUnreadCount(): Observable<Int> {
        return Observable.create {
            if (CheckLoginUtils.isLogin()) {
                mApi.addonsUnread
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : BiResponse<AddonsUnreadEntity>() {
                        override fun onSuccess(data: AddonsUnreadEntity) {
                            it.onNext(data.favorite)
                            it.onComplete()
                            addonsUnread.postValue(data)
                        }
                    })
            } else {
                it.onNext(0)
                it.onComplete()
            }
        }
    }

    private fun checkPrivacyIsSame(): Boolean {
        val currentMd5 = SPUtils.getString(Constants.SP_PRIVACY_CURRENT_MD5)
        val mineMd5 = SPUtils.getString(Constants.SP_PRIVACY_MINE_MD5)
        return currentMd5 == mineMd5
    }

    private fun checkDataIsSameAsLast(t1: Int, t2: Int, t3: Int, t4: Int): Boolean {
        val lastRecord = SPUtils.getString(Constants.SP_GH_RED_POINT_REMIND, "")
        val lastRecordList = if (!lastRecord.isNullOrEmpty()) {
            val type = object : TypeToken<ArrayList<Int>>() {}.type
            GsonUtils.gson.fromJson<ArrayList<Int>>(lastRecord, type)
                ?: arrayListOf(0, 0, 0, 0)
        } else {
            arrayListOf(0, 0, 0, 0)
        }
        if (lastRecordList.size == 4 && t1 == lastRecordList[0] && t2 == lastRecordList[1] && t3 == lastRecordList[2] && t4 == lastRecordList[3]) {
            return true
        }
        return false
    }

    private fun addUnreadRecord(t1: Int, t2: Int, t3: Int, t4: Int) {
        val list = arrayListOf(t1, t2, t3, t4)
        val toJson = GsonUtils.toJson(list)
        SPUtils.setString(Constants.SP_GH_RED_POINT_REMIND, toJson)
    }

    @SuppressLint("CheckResult")
    fun refreshUnreadCount(type: UnreadMessageType) {
        val requestMap = HashMap<String, String>()
        requestMap["type"] = type.value
        mApi.refreshUnreadCount(requestMap.createRequestBody())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    loadMessageUnreadTotal(true)
                }
            })
    }

    enum class UnreadMessageType(val value: String) {
        FAVORITE("favorite")
    }
}