package com.gh.gamecenter.gamedetail.rating

import android.app.Application
import android.os.Build
import android.text.TextUtils
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.gh.gamecenter.core.AppExecutor
import com.gh.common.util.*
import com.gh.gamecenter.common.baselist.ListViewModel
import com.gh.gamecenter.common.baselist.LoadParams
import com.gh.gamecenter.common.baselist.LoadStatus
import com.gh.gamecenter.common.baselist.LoadType
import com.gh.gamecenter.common.utils.toObject
import com.gh.gamecenter.core.utils.UrlFilterUtils
import com.gh.gamecenter.entity.ErrorEntity
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.entity.Rating
import com.gh.gamecenter.entity.RatingComment
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.energy.EnergyBridge
import com.gh.gamecenter.retrofit.RetrofitManager
import com.lightgame.utils.Utils
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import retrofit2.HttpException

class RatingViewModel(application: Application, val game: GameEntity, val type: RatingType = RatingType.RATING) :
    ListViewModel<RatingComment, RatingComment>(application) {

    private val mApi = RetrofitManager.getInstance().api

    val ratingLiveData = MutableLiveData<Rating>()
    val filterMap = HashMap<String, String?>()
    var packageNameList = ArrayList<String>()

    init {
        if (type == RatingType.RATING) {
            setOverLimitSize(1)
        }

        if (type == RatingType.RATING) {
            initData()
        } else {
            load(LoadType.NORMAL)
        }
    }

    override fun provideDataObservable(page: Int): Observable<List<RatingComment>>? {
        return if (type == RatingType.RATING) {
            mApi.getGameComments(
                game.id, page,
                UrlFilterUtils.getFilterQuery(
                    FILTER_DEVICE_KEY,
                    filterMap[FILTER_DEVICE_KEY],
                    FILTER_START_KEY,
                    filterMap[FILTER_START_KEY]
                ),
                filterMap[FILTER_SORT_KEY]
            )
        } else {
            mApi.getGameComments(game.id, page, UrlFilterUtils.getFilterQuery("fold", "true"), "")
        }

    }

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

    fun initData() {
        initLoadParams()
        getRatingData()
        initPackNameList()
    }

    private fun initPackNameList() {
        runOnIoThread {
            for (apk in game.getApk()) {
                val packageName = apk.packageName
                if (!TextUtils.isEmpty(packageName)
                    // 过滤黑名单包名
                    && !PackageHelper.commentPackageNameBlackList.contains(packageName)
                    && !PackageHelper.downloadPackageNameBlackList.contains(packageName)
                ) {
                    packageNameList.add(packageName!!)
                }
            }
        }
    }

    fun canUserCommentThisGame(): String? {
        for (packageName in packageNameList) {
            if (PackageHelper.localPackageNameSet.contains(packageName)) {
                return packageName
            }
        }
        return null
    }

    private fun getRatingData() {
        mApi.getGameRating(game.id, Build.MODEL)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<Rating>() {
                override fun onResponse(response: Rating?) {
                    ratingLiveData.value = response
                    load(LoadType.NORMAL)
                }

                override fun onFailure(e: HttpException?) {
                    if (e != null && e.code() == 404) {
                        loadStatusControl(0)
                    } else {
                        loadStatusControl(REQUEST_FAILURE_SIZE)
                    }
                }
            })
    }


    fun voteComment(commentId: String, callback: () -> Unit) {
        mApi.voteGameComment(game.id, commentId)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    Utils.toast(getApplication(), "点赞成功")
                    callback.invoke()

                    EnergyBridge.postEnergyTask("vote_game_comment", commentId)
                }

                override fun onFailure(e: HttpException?) {
                    val string = e?.response()?.errorBody()?.string()
                    val errorEntity = string?.toObject<ErrorEntity>()
                    if (errorEntity?.code == 403008) {
                        onResponse(null)
                        return
                    }
                    ErrorHelper.handleError(getApplication(), string)
                }
            })
    }

    fun unVoteComment(commentId: String, callback: () -> Unit) {
        mApi.unvoteGameComment(game.id, commentId)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)
                    Utils.toast(getApplication(), "取消点赞")
                    callback.invoke()
                }

                override fun onFailure(e: HttpException?) {
                    val string = e?.response()?.errorBody()?.string()
                    ErrorHelper.handleError(getApplication(), string)
                }
            })
    }

    fun filterList(sort: String?, filter: String?) {
        filterMap.clear()

        when (sort) {
            "默认" -> {
                filterMap[FILTER_SORT_KEY] = ""
            }
            "热门" -> {
                filterMap[FILTER_SORT_KEY] = "vote:-1"
            }
            else -> {
                filterMap[FILTER_SORT_KEY] = "time:-1"
            }
        }

        if (filter == "同设备") {
            filterMap[FILTER_DEVICE_KEY] = Build.MANUFACTURER + "|" + Build.MODEL
        } else if (filter != null && filter.contains("星")) {
            filterMap[FILTER_START_KEY] = filter.replace("星", "")
        }

        // 保持列表位置不变刷新页面
        mCurLoadParams = LoadParams(LoadParams.DEFAULT_OFFSET)
        mLoadStatusLiveData.value = LoadStatus.LIST_LOADED
        load(LoadType.NORMAL)
    }

    fun getLinkPageSize(): Int {
        return mCurLoadParams.loadOffset
    }

    class Factory(
        private val mApplication: Application,
        private val game: GameEntity,
        val type: RatingType = RatingType.RATING
    ) : ViewModelProvider.NewInstanceFactory() {
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return RatingViewModel(mApplication, game, type) as T
        }
    }

    companion object {
        private const val FILTER_SORT_KEY = "sort"
        private const val FILTER_DEVICE_KEY = "device"
        private const val FILTER_START_KEY = "star"
    }

    enum class RatingType {
        RATING,//评论列表
        FOLD_RATING//折叠评论
    }
}