package com.gh.gamecenter.gamedetail

import android.annotation.SuppressLint
import android.app.Application
import android.net.Uri
import android.os.Build
import android.text.TextUtils
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.history.HistoryHelper
import com.gh.common.util.CheckLoginUtils
import com.gh.common.util.ConcernUtils
import com.gh.common.util.LibaoUtils
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.mvvm.Resource
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.common.utils.toRequestBody
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.UrlFilterUtils
import com.gh.gamecenter.entity.*
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.SimpleGame
import com.gh.gamecenter.feature.utils.ApkActiveUtils
import com.gh.gamecenter.gamedetail.entity.BigEvent
import com.gh.gamecenter.gamedetail.entity.CustomColumn
import com.gh.gamecenter.gamedetail.entity.DetailEntity
import com.gh.gamecenter.gamedetail.entity.NewGameDetailEntity
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import org.json.JSONObject
import retrofit2.HttpException
import tv.danmaku.ijk.media.exo2.ExoSourceManager
import java.util.*

class GameDetailViewModel(
    application: Application,
    var gameId: String?,
    var game: GameEntity?
) : AndroidViewModel(application) {

    private val mApi = RetrofitManager.getInstance().api
    private val mSensitiveApi = RetrofitManager.getInstance().api
    private val mNewApi = RetrofitManager.getInstance().newApi

    val concernLiveData = MutableLiveData<ConcernResponse>()
    val gameLiveData = MutableLiveData<Resource<GameEntity>?>()
    val gameDetailLiveData = MutableLiveData<Resource<NewGameDetailEntity>>()
    val bigEventLiveData = MutableLiveData<List<BigEvent>>()
    val recommendPopupLiveData = MutableLiveData<ArrayList<RecommendPopupEntity>>()
    val archiveStatusLiveData = MutableLiveData<Boolean>()

    // 供外部 fragment (如 GameDetailFragment) 用的合并用户数据后的游戏数据 liveData
    val unifiedGameDetailWithUserRelatedInfoForParentLiveData = MutableLiveData<NewGameDetailEntity>()

    // 供被包裹 fragment (如 FuliFragment) 用的合并用户数据后的游戏数据 liveData
    val unifiedGameDetailWithUserRelatedInfoForChildLiveData = MutableLiveData<NewGameDetailEntity>()

    var videoIsMuted = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
    var displayTopVideo: Boolean = false

    init {
        loadData()
    }

    fun loadData() {
        if (RegionSettingHelper.shouldThisGameBeFiltered(gameId)) {
            gameId = "invalid"
            game?.id = "invalid"
        }

        when {
            game != null -> {
                gameLiveData.postValue(Resource.success(game))
                getGameDetailNew()
                getRecommendPopup(game?.id ?: "")
            }
            gameId != null -> getGameDigest()
            else -> gameLiveData.postValue(null)
        }
    }

    // 获取游戏摘要
    private fun getGameDigest() {
        mSensitiveApi.getGameDigest(gameId)
            .map(ApkActiveUtils.filterMapper)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<GameEntity>() {
                override fun onResponse(response: GameEntity?) {
                    game = response
                    gameLiveData.postValue(Resource.success(game))
                    getGameDetailNew()
                    getRecommendPopup(game?.id ?: "")
                }

                override fun onFailure(e: HttpException?) {
                    gameLiveData.postValue(Resource.error(e))
                }
            })
    }

    //过滤游戏标签
    private fun filterGameTags(data: NewGameDetailEntity) {
        val filterTagString = SPUtils.getString(Constants.SP_FILTER_TAGS)
        val filterTags = GsonUtils.fromJsonList<String>(filterTagString)
        var i = 0
        while (i < data.tagStyle.size) {
            if (filterTags.contains(data.tagStyle[i].name)) {
                data.tagStyle.removeAt(i)
                i--
            }
            i++
        }
    }

    private fun removeLatestServerIfNeeded(data: NewGameDetailEntity) {
        var i = 0
        while (i < data.detailEntity.size) {
            if (data.detailEntity[i].type == DetailEntity.Type.LATEST_SERVER.value) {
                data.detailEntity.removeAt(i)
                return
            }
            i++
        }
    }

    @SuppressLint("CheckResult")
    fun getGameDetailNew() {
        mSensitiveApi.getGameDetailNew(game?.id)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<NewGameDetailEntity>() {
                override fun onSuccess(data: NewGameDetailEntity) {
                    filterGameTags(data)
                    replaceWithMirrorInfoIfNeeded(data)
                    // 4.4以下设备不显示顶部视频
                    displayTopVideo = data.topVideo != null
                            && !data.topVideo?.url.isNullOrEmpty()
                            && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT

                    data.contentCard.forEach {
                        // 显示开服内容卡片时，游戏详情-详情tab不显示“最新开服”
                        if (it.type == "func_server" && data.isShowContentCard(game)) {
                            removeLatestServerIfNeeded(data)
                            return@forEach
                        }
                    }
                    filterRelatedVersionGames(data)
                    gameDetailLiveData.postValue(Resource.success(data))
                    if (CheckLoginUtils.isLogin()) {
                        getUserRelatedInfo(data)
                    }

                    // 初始化礼包按钮状态
                    for (entity in data.detailEntity) {
                        if (entity.type == "libao") {
                            val simpleGame = SimpleGame(gameId, mName = game?.name)
                            if (entity.libao != null) {
                                loadLiBaoStatus(data, entity.libao!!)
                                for (libaoEntity in entity.libao!!) {
                                    libaoEntity.game = simpleGame
                                }
                            }
                            break
                        }
                    }

                    if (data.showArchive) {
                        getArchiveStatus(game?.id ?: "")
                    }
                }

                override fun onFailure(exception: Exception) {
                    if (exception is HttpException) {
                        gameDetailLiveData.postValue(Resource.error(exception))
                    }
                }
            })
    }

    //过滤其他相关游戏中屏蔽的游戏
    private fun filterRelatedVersionGames(data: NewGameDetailEntity) {
        val entity = data.detailEntity.find { it.type == DetailEntity.Type.RELATED_VERSION.value }
        val relatedVersion = entity?.relatedVersion
        if (relatedVersion != null) {
            var i = 0
            while (i < relatedVersion.size) {
                if (RegionSettingHelper.shouldThisGameBeFiltered(relatedVersion[i].gameId)) {
                    relatedVersion.removeAt(i)
                    i--
                }
                i++
            }
            if (relatedVersion.isEmpty()) {
                data.detailEntity.remove(entity)
            }
        }
    }

    private fun replaceWithMirrorInfoIfNeeded(data: NewGameDetailEntity) {
        // 获取镜像相关数据，不存在时不替换
        val mirrorData = getMirrorData(data) ?: return

        val finalItemList: ArrayList<DetailEntity> = arrayListOf()
        val mirrorCustomColumnList = mirrorData.customColumnList ?: arrayListOf()
        mirrorCustomColumnList.sortByDescending { it.order }
        for (item in data.detailEntity) {
            // 去掉所有自定义栏目并把镜像相应权重的自定义栏目放到相应的位置
            if (item.type == DetailEntity.Type.CUSTOM_COLUMN.value) {
                val usedMirrorCustomColumnList = arrayListOf<CustomColumn>()
                for (mirrorCustomColumn in mirrorCustomColumnList) {
                    if ((mirrorCustomColumn.order!! > 0 && item.customColumn?.order!! > 0)
                        || (mirrorCustomColumn.order == item.customColumn?.order)
                    ) {
                        finalItemList.add(
                            DetailEntity(
                                type = DetailEntity.Type.CUSTOM_COLUMN.value,
                                customColumn = mirrorCustomColumn
                            )
                        )
                        usedMirrorCustomColumnList.add(mirrorCustomColumn)
                    }
                }
                mirrorCustomColumnList.removeAll(usedMirrorCustomColumnList)
                continue
            }

            // 历史版本入口
            if (item.type == DetailEntity.Type.UPDATE_CONTENT.value) {
                item.update?.historyApkStatus = "off"
            }

            // 不显示 "玩家评论`", "相关游戏`"
            if (item.type == DetailEntity.Type.COMMENTS.value ||
                item.type == DetailEntity.Type.RELATED_VERSION.value
            ) {
                continue
            }

            // 处理游戏信息区域
            if (item.type == DetailEntity.Type.GAME_INFO.value) {
                item.info?.manufacturer = mirrorData.manufacturer ?: ""
                item.info?.privacyPolicyUrl = mirrorData.privacyPolicyUrl ?: ""
                item.info?.manufacturerType = mirrorData.manufacturerType
                item.info?.publisher = mirrorData.publisher
                item.info?.developer = mirrorData.developer
                item.info?.supplier = mirrorData.supplier
                item.info?.creditCode = mirrorData.creditCode
                item.info?.updateTime = mirrorData.updateTime
                finalItemList.add(item)
                continue
            }

            // 去掉游戏信息里的 "mod 版"
            if (item.type == DetailEntity.Type.GAME_INFO.value) {
                item.info?.topTags?.removeAll { it.name.toLowerCase(Locale.getDefault()) == "mod版" }
            }

            // 替换镜像开服信息
            if (item.type == DetailEntity.Type.LATEST_SERVER.value && mirrorData.server != null) {
                if (mirrorData.server?.status == "hide") {
                    continue
                } else {
                    item.server = mirrorData.server
                }
            }

            // 镜像游戏去掉推荐游戏 (用于构建大家都在玩)
            if (item.type == DetailEntity.Type.RECOMMENDED_GAMES.value) {
                continue
            }

            finalItemList.add(item)
        }

        val funcServer = data.contentCard.find { it.type == "func_server" }
        if (funcServer?.mirrorServer != null) {
            funcServer.server = funcServer.mirrorServer
        }

        // 有多余的镜像自定义栏目没找到位置放，统一按权重为0放到详细信息后，连权重为0也没有就放到列表最后！
        if (!mirrorCustomColumnList.isNullOrEmpty()) {
            var gameInfoPosition = finalItemList.size - 1
            for ((index, item) in finalItemList.withIndex()) {
                if (item.type == DetailEntity.Type.GAME_INFO.value) {
                    gameInfoPosition = index + 1
                    break
                }
            }

            for ((index, remainingMirrorCustomColumn) in mirrorCustomColumnList.withIndex()) {
                finalItemList.add(
                    gameInfoPosition + index,
                    DetailEntity(
                        type = DetailEntity.Type.CUSTOM_COLUMN.value,
                        customColumn = remainingMirrorCustomColumn
                    )
                )
            }
        }

        // 不显示评论 tab
        data.showComment = false

        for (item in finalItemList) {
            item.des = mirrorData.des
            item.gallery = mirrorData.gallery

            item.update?.updateDes = mirrorData.updateDes

            item.info?.size = mirrorData.apk?.firstOrNull()?.size ?: ""
            item.info?.version = mirrorData.apk?.firstOrNull()?.version ?: ""
        }

        data.tagStyle =
            mirrorData.tagStyle.apply { removeAll { it.name.toLowerCase(Locale.getDefault()) == "mod版" } }
        data.detailDialogs = mirrorData.detailDialogs
        data.detailEntity = finalItemList
    }

    /**
     * 获取镜像数据，为空时代表不启用镜像
     */
    private fun getMirrorData(data: NewGameDetailEntity): DetailEntity? {
        // 游戏 id
        val id = game?.id ?: ""

        if (RegionSettingHelper.shouldThisGameDisplayMirrorInfo(id) || game?.useMirrorInfo == true) {
            if (data.mirrorStatus == "on" || data.mirrorStatus2 == "on") {
                when (RegionSettingHelper.getMirrorPosition(id)) {
                    1 -> return data.mirrorData
                    2 -> return data.mirrorData2
                }
            }
        }

        return null
    }

    /**
     * 获取游戏详情内容相应的用户相关信息
     */
    @SuppressLint("CheckResult")
    private fun getUserRelatedInfo(newGameDetailEntity: NewGameDetailEntity) {
        val libaoIdList = arrayListOf<String>()
        val toolkitIdList = arrayListOf<String>()
        val answerIdList = arrayListOf<String>()

        newGameDetailEntity.detailEntity.forEach {
            if (it.type == "libao") {
                for (libao in it.libao!!) {
                    libaoIdList.add(libao.id ?: "")
                }
            }
        }
        if (newGameDetailEntity.zone?.style == "default") {
            newGameDetailEntity.zone?.content?.forEach {
                if (it.type == "toolkit") {
                    for (tool in it.toolkit!!) {
                        toolkitIdList.add(tool.id ?: "")
                    }
                }
                if (it.type == "community_column_content") {
                    for (answer in it.answer!!) {
                        answerIdList.add(answer.id ?: "")
                    }
                }
            }
        }

        val requestMap = hashMapOf<String, List<String>>()
        requestMap["game"] = arrayListOf(game?.id ?: "game id is not supposed to be empty")
        requestMap["toolkit"] = toolkitIdList
        requestMap["libao"] = libaoIdList
        requestMap["community_column_content"] = answerIdList

        mApi.getUserRelatedInfoByPost(UserManager.getInstance().userId, requestMap.toRequestBody())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<UnifiedUserTrendEntity>() {
                override fun onSuccess(data: UnifiedUserTrendEntity) {
                    mergeUnifiedGameDetailWithUserRelatedInfo(newGameDetailEntity, data)
                }
            })
    }

    fun mergeUnifiedGameDetailWithUserRelatedInfo(
        newGameDetailEntity: NewGameDetailEntity,
        unifiedUserTrendEntity: UnifiedUserTrendEntity
    ) {
        var libaoList: List<LibaoEntity>? = null
        unifiedUserTrendEntity.game?.let {
            if (unifiedUserTrendEntity.game.isNullOrEmpty()) return@let
            for (game in it) {
                newGameDetailEntity.me = game.me
                break
            }
        }
        if (newGameDetailEntity.zone?.style == "default") {
            newGameDetailEntity.zone?.content?.forEach {
                if (it.type == "toolkit") {
                    if (unifiedUserTrendEntity.toolkit != null) {
                        for (originalToolkit in it.toolkit!!) {
                            for (toolkit in unifiedUserTrendEntity.toolkit!!) {
                                if (originalToolkit.id == toolkit.id) {
                                    originalToolkit.me = toolkit.me
                                    break
                                }
                            }
                        }
                    }
                }
                if (it.type == "community_column_content") {
                    if (unifiedUserTrendEntity.communityColumnContents != null) {
                        for (originalAnswer in it.answer!!) {
                            for (answer in unifiedUserTrendEntity.communityColumnContents!!) {
                                if (originalAnswer.id == answer.id) {
                                    originalAnswer.me = answer.me
                                    originalAnswer.vote = answer.vote
                                    break
                                }
                            }
                        }
                    }
                }
            }
        }

        newGameDetailEntity.detailEntity.forEach {
            if (it.type == "libao") {
                libaoList = it.libao!!
                if (unifiedUserTrendEntity.libao != null) {
                    for (originalLibao in it.libao!!) {
                        for (libao in unifiedUserTrendEntity.libao!!) {
                            if (originalLibao.id == libao.id) {
                                originalLibao.me = libao.me
                                break
                            }
                        }
                    }
                }
            }
        }

        if (libaoList.isNullOrEmpty()) {
            unifiedGameDetailWithUserRelatedInfoForParentLiveData.postValue(newGameDetailEntity)
            unifiedGameDetailWithUserRelatedInfoForChildLiveData.postValue(newGameDetailEntity)
        } else {
            unifiedGameDetailWithUserRelatedInfoForParentLiveData.postValue(newGameDetailEntity)
            libaoList?.let {
                loadLiBaoStatus(newGameDetailEntity, it)
            }
        }
    }

    //获取礼包状态
    private fun loadLiBaoStatus(newGameDetailEntity: NewGameDetailEntity, libaoList: List<LibaoEntity>) {
        val builder = StringBuilder()
        var i = 0
        val size = libaoList.size
        while (i < size) {
            builder.append(libaoList[i].id)
            builder.append("-")
            i++
        }
        if (builder.isEmpty()) {
            return
        }
        builder.deleteCharAt(builder.length - 1)
        val ids = builder.toString()

        mApi.getLibaoStatus(UrlFilterUtils.getFilterQuery("libao_ids", ids))
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<List<LibaoStatusEntity>>() {
                override fun onResponse(list: List<LibaoStatusEntity>?) {
                    LibaoUtils.initLiBaoEntity(list, libaoList)
                    if (libaoList.isNotEmpty()) {
                        newGameDetailEntity.detailEntity.forEach {
                            if (it.type == "libao") {
                                it.libao = libaoList as ArrayList<LibaoEntity>
                                sortLibaoList(it.libao)
                            }
                        }
                        unifiedGameDetailWithUserRelatedInfoForChildLiveData.postValue(newGameDetailEntity)
                    }
                }

                override fun onFailure(e: HttpException?) {
                    unifiedGameDetailWithUserRelatedInfoForChildLiveData.postValue(newGameDetailEntity)
                }
            })
    }

    //[已领取/已淘号/再领/再淘]的礼包置底显示
    fun sortLibaoList(libaoList: ArrayList<LibaoEntity>?) {
        if (UserManager.getInstance().isLoggedIn && !libaoList.isNullOrEmpty()) {
            val tempList = arrayListOf<LibaoEntity>()
            val iterator = libaoList.iterator()
            while (iterator.hasNext()) {
                val entity = iterator.next()
                if (entity.status == "linged" || entity.status == "taoed" ||
                    entity.status == "repeatLinged" || entity.status == "repeatTao"
                ) {
                    tempList.add(entity)
                    iterator.remove()
                }
            }
            libaoList.addAll(tempList)
        }
    }

    fun concernCommand(isConcern: Boolean) {
        val listener = object : ConcernUtils.OnConcernListener {
            override fun onSuccess() {
                concernLiveData.postValue(ConcernResponse(isConcern, true))
            }

            override fun onError() {
                concernLiveData.postValue(ConcernResponse(isConcern, false))
            }
        }
        game?.id?.let {
            if (isConcern) {
                ConcernUtils.postConcernGameId(it, listener)
            } else {
                ConcernUtils.deleteConcernData(it, listener)
            }
        }
    }

    fun logHistory(data: GameEntity) {
        HistoryHelper.insertGameEntity(data)
    }

    fun removeFromHistory() {
        HistoryHelper.deleteGameEntity(gameId ?: "")
    }

    fun isTopVideoPartlyCached(topVideoUrl: String): Boolean {
        val cache = ExoSourceManager.getCacheSingleInstance(HaloApp.getInstance().application, null)
        val key = Uri.parse(topVideoUrl).toString()
        return if (!TextUtils.isEmpty(key)) {
            val cachedSpans = cache.getCachedSpans(key)
            cachedSpans.size != 0
        } else {
            false
        }
    }

    //获取大事件
    fun getBigEvent() {
        mSensitiveApi.getBigEvent(game?.id)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<List<BigEvent>>() {
                override fun onResponse(response: List<BigEvent>?) {
                    super.onResponse(response)
                    response?.let {
                        for (event in it) {
                            if (event.link?.type == "feedback") {
                                event.link?.name = game?.name
                                event.link?.text = game?.getGameCategory().toString()
                            }
                        }
                        bigEventLiveData.postValue(it)
                    }
                }
            })
    }

    @SuppressLint("CheckResult")
    fun getRecommendPopup(gameId: String) {
        mApi.getRecommendPopup(gameId)
            .compose(singleToMain())
            .subscribe(object : BiResponse<ArrayList<RecommendPopupEntity>>() {
                override fun onSuccess(data: ArrayList<RecommendPopupEntity>) {
                    recommendPopupLiveData.postValue(data)
                }
            })
    }

    @SuppressLint("CheckResult")
    fun getArchiveStatus(gameId: String) {
        mNewApi.getArchiveStatus(gameId)
            .compose(singleToMain())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    val body = JSONObject(data.string())
                    val hasNew = body.optBoolean("has_new")
                    archiveStatusLiveData.postValue(hasNew)
                }
            })
    }

    class Factory(
        private val mApplication: Application,
        private val gameId: String?,
        private val game: GameEntity?
    ) : ViewModelProvider.NewInstanceFactory() {
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return GameDetailViewModel(mApplication, gameId, game) as T
        }
    }

    class ConcernResponse(var isConcern: Boolean = false, var isSuccess: Boolean = false)
}
