package com.gh.gamecenter.discovery

import android.annotation.SuppressLint
import android.app.Application
import com.gh.common.util.PackageUtils
import com.gh.download.DownloadManager
import com.gh.gamecenter.common.baselist.ListViewModel
import com.gh.gamecenter.common.baselist.LoadStatus
import com.gh.gamecenter.common.baselist.LoadType
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.observableToMain
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.common.utils.toRequestBody
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.entity.DiscoveryGameCardLabel
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.entity.InterestedGameEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.Observable
import okhttp3.ResponseBody
import retrofit2.HttpException

class DiscoveryViewModel(application: Application) : ListViewModel<GameEntity, DiscoveryItemData>(application) {

    val positionAndPackageMap = HashMap<String, Int>()
    private val mApi = RetrofitManager.getInstance().api
    private var mGameTags: ArrayList<LinkEntity>? = null
    private var mUserTags: ArrayList<InterestedGameEntity.TypeTag.Tag>? = null
    private var mDiscoveryGameCardLabels: ArrayList<DiscoveryGameCardLabel>? = null
    private var mDiscoveryGameCardLabelMap: LinkedHashMap<String, ArrayList<DiscoveryGameCardLabel>> = linkedMapOf()

    init {
        getCardLabels()
    }

    override fun mergeResultLiveData() {
        mResultLiveData.addSource(mListLiveData) {
            mergeResultItemData(it)
        }
    }

    private fun mergeResultItemData(games: MutableList<GameEntity>) {
        val itemDataList = arrayListOf<DiscoveryItemData>()
        var insertCount = 0
        var i = 0
        while (i < games.size) {
            val gameEntity = games[i]
            //删除已安装的游戏
            if (gameEntity.getApk().isNotEmpty() && PackageUtils.isInstalled(
                    HaloApp.getInstance().application,
                    gameEntity.getApk()[0].packageName
                )
            ) {
                games.removeAt(i)
                i--
            }
            i++
        }
        games.forEachIndexed { index, gameEntity ->
            itemDataList.add(DiscoveryItemData(gameEntity))
            //第6、12、18、24个游戏后面固定插入兴趣推荐卡片
            when (index) {
                5 -> {
                    itemDataList.add(
                        DiscoveryItemData(
                            cardPosition = 1,
                            interestCardLabels = mDiscoveryGameCardLabelMap["卡片一"]
                        )
                    )
                    insertCount++
                }
                11 -> {
                    itemDataList.add(
                        DiscoveryItemData(
                            cardPosition = 2,
                            interestImageCardLabel = mDiscoveryGameCardLabelMap["卡片二"]?.get(0)
                        )
                    )
                    insertCount++
                }
                17 -> {
                    itemDataList.add(
                        DiscoveryItemData(
                            cardPosition = 3,
                            interestCardLabels = mDiscoveryGameCardLabelMap["卡片三"]
                        )
                    )
                    insertCount++
                }
                23 -> {
                    itemDataList.add(
                        DiscoveryItemData(
                            cardPosition = 4,
                            interestCardLabels = mDiscoveryGameCardLabelMap["卡片四"]
                        )
                    )
                    insertCount++
                }
                else -> {
                    //do nothing
                }
            }
            addGamePositionAndPackage(index + insertCount, gameEntity)
        }
        mResultLiveData.postValue(itemDataList)
    }

    override fun provideDataObservable(page: Int): Observable<MutableList<GameEntity>>? {
        val paramsMap = if (SPUtils.getBoolean(Constants.SP_DISCOVER_FORCE_REFRESH)) {
            mapOf("refresh" to "true")
        } else {
            mapOf()
        }
        return mApi.getDiscoveryGames(page, paramsMap).map {
            SPUtils.setBoolean(Constants.SP_DISCOVER_FORCE_REFRESH, false)
            if (page == 1) {
                mGameTags = it.gameTags
                mUserTags = it.userTags
                groupingDiscoveryLabel()
            }
            it.games
        }
    }

    //按照card字段分组
    private fun groupingDiscoveryLabel() {
        mDiscoveryGameCardLabelMap.clear()
        var gameTagIndex = 0
        var userTagIndex = 0
        mDiscoveryGameCardLabels?.forEach {
            if (mDiscoveryGameCardLabelMap.contains(it.card)) {
                mDiscoveryGameCardLabelMap[it.card]?.add(it)
            } else {
                mDiscoveryGameCardLabelMap[it.card] = arrayListOf(it)
            }
        }
        //如果link_type为空需要在mUserTags/mGameTags中依次获取
        mDiscoveryGameCardLabelMap.keys.forEach {
            val labels = mDiscoveryGameCardLabelMap[it]
            labels?.forEach { label ->
                if (!mUserTags.isNullOrEmpty() && mUserTags!!.size > userTagIndex && label.type.isNullOrEmpty()) {
                    val userTag = mUserTags!![userTagIndex]
                    label.link = userTag.id
                    label.type = "tag"
                    label.linkText = userTag.name
                    label.title = userTag.name
                    userTagIndex++
                } else if (!mGameTags.isNullOrEmpty() && mGameTags!!.size > gameTagIndex && label.type.isNullOrEmpty()) {
                    val gameTag = mGameTags!![gameTagIndex]
                    label.link = gameTag.link
                    label.type = gameTag.type
                    label.linkText = gameTag.linkText
                    label.title = gameTag.linkText
                    gameTagIndex++
                }
            }

        }
    }

    private fun getCardLabels() {
        mApi.cardLabels
            .compose(observableToMain())
            .subscribe(object : Response<ArrayList<DiscoveryGameCardLabel>>() {
                override fun onResponse(response: ArrayList<DiscoveryGameCardLabel>?) {
                    super.onResponse(response)
                    mDiscoveryGameCardLabels = response
                    initLoadParams()
                    loadData()
                }

                override fun onFailure(e: HttpException?) {
                    super.onFailure(e)
                    mLoadStatusLiveData.value = LoadStatus.INIT_FAILED
                }
            })
    }

    @SuppressLint("CheckResult")
    fun discoveryFeedback(gameId: String, reason: String, type: String, callback: () -> Unit) {
        val paramsMap = mapOf(
            "reason" to reason,
            "type" to type
        )
        mApi.discorveryFeedback(gameId, paramsMap.toRequestBody())
            .compose(singleToMain())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    callback.invoke()
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    ToastUtils.showToast("反馈失败")
                }
            })
    }

    private fun addGamePositionAndPackage(position: Int, game: GameEntity) {
        var packages = ""
        for (apkEntity in game.getApk()) {
            packages += apkEntity.packageName
        }
        positionAndPackageMap[packages + (position)] = position
        game.setEntryMap(DownloadManager.getInstance().getEntryMap(game.name))
    }

    override fun load(loadType: LoadType?) {
        if (loadType == LoadType.REFRESH) {
            getCardLabels()
        } else {
            super.load(loadType)
        }
    }


}