package com.gh.gamecenter.search

import android.annotation.SuppressLint
import android.app.Application
import com.gh.common.constant.Config
import com.gh.gamecenter.BuildConfig
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.utils.SensorsBridge
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.entity.SearchSubjectEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import org.json.JSONException
import org.json.JSONObject
import java.net.URLEncoder

class SearchGameResultViewModel(application: Application) : ListViewModel<GameEntity, SearchItemData>(application) {

    private var mApi = RetrofitManager.getInstance().api
    private var mPage = 0
    var mSearchSubjects = arrayListOf<SearchSubjectEntity>()
    var key = ""

    @SuppressLint("CheckResult")
    override fun mergeResultLiveData() {
        mResultLiveData.addSource(mListLiveData) { list ->
            val itemDataList = ArrayList(list.map { SearchItemData(game = it) })

            mApi.getSearchSubject(key, mPage)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ mutableList ->
                    mSearchSubjects.addAll(mutableList)
                    mSearchSubjects.forEach {
                        itemDataList.add(
                            if (it.location <= 0 || it.location >= itemDataList.size) 0 else it.location - 1,
                            SearchItemData(subject = it)
                        )
                    }
                    // 处理初始化列表且游戏列表size为0的情况
                    handleLoadStatusWhenGameListIsEmpty(list, itemDataList)
                    mResultLiveData.postValue(itemDataList)

                    val trackEvent = JSONObject()
                    try {
                        trackEvent.put("search_result", !(mPage == 1 && list.isEmpty()))
                    } catch (e: JSONException) {
                        e.printStackTrace()
                    }
                    SensorsBridge.trackEvent("SearchResultReturn", trackEvent)
                }, {
                    it.printStackTrace()
                    handleLoadStatusWhenGameListIsEmpty(list, itemDataList)
                    mResultLiveData.postValue(itemDataList)
                })
        }
    }

    private fun handleLoadStatusWhenGameListIsEmpty(list: List<GameEntity>, itemDataList: ArrayList<SearchItemData>) {
        if (mPage == 1 && list.isEmpty()) {
            mLoadStatusLiveData.value = if (itemDataList.isEmpty()) LoadStatus.INIT_EMPTY else LoadStatus.INIT_OVER
        }
    }

    override fun loadStatusControl(size: Int) {
        if (mCurLoadParams.loadOffset == LoadParams.DEFAULT_OFFSET) { // 初始化列表
            if (size == 0) {
//              初始化列表size为0情况放到mergeResultLiveData方法处理
            } else if (size == REQUEST_FAILURE_SIZE) {
                mLoadStatusLiveData.setValue(LoadStatus.INIT_FAILED)
            } else if (size < mOverLimitSize) { // 避免一个屏幕出现两次分页
                mLoadStatusLiveData.setValue(LoadStatus.INIT_OVER)
            } else {
                mLoadStatusLiveData.setValue(LoadStatus.INIT_OVER)
            }
        } else {
            if (size == REQUEST_FAILURE_SIZE) {
                mLoadStatusLiveData.setValue(LoadStatus.LIST_FAILED)
            } else if (size == 0) {
                mLoadStatusLiveData.setValue(LoadStatus.LIST_OVER)
            } else {
                mLoadStatusLiveData.setValue(LoadStatus.LIST_LOADED)
            }
        }

        if (size == REQUEST_FAILURE_SIZE) {
            mRetryParams = mCurLoadParams
        } else {
            mRetryParams = null
            mCurLoadParams.setLoadOffset(mCurLoadParams.getLoadOffset() + 1) // 页数 + 1
        }
    }

    override fun provideDataObservable(page: Int): Observable<List<GameEntity>> {
        // 可能会有特殊字符，需要 encode 处理
        val encodedKey = URLEncoder.encode(key, "utf-8")
        mPage = page
        return mApi.getSearchGame(
            Config.API_HOST + "games:search?keyword=" +
                    encodedKey + "&view=digest&page=" + page +
                    "&channel=" + HaloApp.getInstance().channel +
                    "&version=" + BuildConfig.VERSION_NAME
        )
    }
}