package com.gh.gamecenter.vote

import android.app.Application
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.gh.gamecenter.common.baselist.ListViewModel
import com.gh.gamecenter.common.baselist.LoadType
import com.gh.gamecenter.common.retrofit.ApiResponse
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.feature.entity.InstallGameEntity
import com.gh.gamecenter.entity.VersionVoteEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.PublishSubject
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.json.JSONException
import org.json.JSONObject
import retrofit2.HttpException
import java.util.concurrent.TimeUnit

class VoteViewModel(application: Application, private val mGameId: String = "") :
    ListViewModel<VersionVoteEntity, VersionVoteEntity>(application) {

    var keyword = ""
    val uploadSuccess = MutableLiveData<Boolean>()

    val disposable = CompositeDisposable()

    private val searchKeySubject = PublishSubject.create<String>()
        .also {
        val disposable = it.debounce(300, TimeUnit.MILLISECONDS)
            .distinctUntilChanged()
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe { keyword ->
                searchVersion(keyword)
            }
        this.disposable.add(disposable)
    }


    override fun mergeResultLiveData() {
        mResultLiveData.addSource(mListLiveData) { list ->
            mResultLiveData.postValue(list)
        }
    }

    override fun provideDataObservable(page: Int): Observable<MutableList<VersionVoteEntity>> =
        RetrofitManager.getInstance().api.getVersionVote(mGameId, page, keyword)
            .doOnSubscribe { disposable.add(it) }

    fun postApkInfo(url: String, installGameEntity: InstallGameEntity) {
        val requestMap = HashMap<String, Any>()
        requestMap["url"] = url
        requestMap["package"] = installGameEntity.packageName.toString()
        requestMap["format"] = installGameEntity.format ?: ""
        requestMap["size_code"] = installGameEntity.gameSize.toInt()
        requestMap["version"] = installGameEntity.gameVersion ?: ""
        requestMap["version_code"] = installGameEntity.versionCode

        val body = RequestBody.create(
            "application/json".toMediaTypeOrNull(),
            GsonUtils.toJson(requestMap)
        )
        RetrofitManager.getInstance().api.postPlatformRequestApk(installGameEntity.platformRequestsId, body)
            .doOnSubscribe { disposable.add(it) }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)
                    uploadSuccess.postValue(true)
                }

                override fun onApiFailure(e: ApiResponse<ResponseBody>?) {
                    super.onApiFailure(e)
                    uploadSuccess.postValue(false)
                }
            })
    }

    fun postVersionVote(
        name: String,
        isNewVote: Boolean,
        isVoted: Boolean,
        successCallback: (response: ResponseBody) -> Unit,
        failureCallback: (e: HttpException) -> Unit
    ) {
        val jsonObject = JSONObject()
        try {
            jsonObject.put("name", name)
        } catch (e: JSONException) {
            e.printStackTrace()
        }
        val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
        val responseBodyObservable = if (isNewVote) {
            RetrofitManager.getInstance().api.addVersionVote(body, mGameId)
        } else if (isVoted) {
            RetrofitManager.getInstance().api.postVersionCancelVote(name) // name is id
        } else {
            RetrofitManager.getInstance().api.postVersionVote(name) // name is id
        }
        responseBodyObservable
            .doOnSubscribe { disposable.add(it) }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)
                    try {
                        if (response != null) {
                            successCallback.invoke(response)
                        }
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                override fun onFailure(e: HttpException?) {
                    super.onFailure(e)
                    e?.let { failureCallback.invoke(it) }
                }
            })
    }

    override fun onCleared() {
        disposable.dispose()
    }

    fun searchVersion(keyword: String) {
        this.keyword = keyword
        load(LoadType.REFRESH)
    }

    fun autoSearchVersion(keyword: String) {
        searchKeySubject.onNext(keyword)
    }

    class Factory(private val gameId: String) : ViewModelProvider.NewInstanceFactory() {
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return VoteViewModel(HaloApp.getInstance().application, gameId) as T
        }
    }
}