package com.gh.gamecenter.cloudarchive

import android.annotation.SuppressLint
import android.app.Application
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.toRequestBody
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.entity.ArchiveEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.utils.ApkActiveUtils
import com.gh.gamecenter.livedata.Event
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import retrofit2.HttpException

class CloudArchiveManagerViewModel(
    application: Application,
    val gameId: String,
    val gameName: String,
    configUrl: String
) : BaseCloudArchiveViewModel(application, gameId, configUrl) {

    companion object {
        private const val SORT_TYPE_CREATE = "time.create:-1"
        private const val UPLOAD_ARCHIVE_LIMIT_COUNT = 5
    }

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

    val uploadSuccess = MutableLiveData<Boolean>()
    val gameEntityLiveData = MutableLiveData<GameEntity>()

    private val compositeDisposable = CompositeDisposable()

    init {
        getGameDigest()
    }

    private fun getGameDigest() {
        mApi.getGameDigest(gameId)
            .map(ApkActiveUtils.filterMapper)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : com.gh.gamecenter.common.retrofit.Response<GameEntity>() {
                override fun onResponse(response: GameEntity?) {
                    response?.let {
                        gameEntityLiveData.postValue(it)
                    }
                }
            })
    }

    @SuppressLint("CheckResult")
    fun postArchive(archiveEntity: ArchiveEntity) {
        val paramsMap = mapOf(
            "name" to archiveEntity.name,
            "url" to archiveEntity.url,
            "config_url" to archiveEntity.configUrl,
            "game_version" to archiveEntity.gameVersion,
            "md5" to archiveEntity.md5
        )
        mNewApi.postMyArchive(gameId, paramsMap.toRequestBody())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    val json = GsonUtils.fromJson(data.string(), Map::class.java)
                    NewFlatLogUtils.logCloudArchiveUploadDialogClick(
                        gameId = gameId,
                        gameName = gameName,
                        cloudSaveId = json["_id"] as String,
                        cloudSaveName = archiveEntity.name,
                        isSuccess = true
                    )
                    uploadSuccess.postValue(true)
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    uploadSuccess.postValue(false)
                    NewFlatLogUtils.logCloudArchiveUploadDialogClick(
                        gameId = gameId,
                        gameName = gameName,
                        cloudSaveId = "",
                        cloudSaveName = archiveEntity.name,
                        isSuccess = false
                    )
                }
            })
    }


    private val _uploadArchiveAction = MutableLiveData<Event<Unit>>()
    val uploadArchiveAction: LiveData<Event<Unit>> = _uploadArchiveAction

    private val _showArchiveLimitAction = MutableLiveData<Event<List<ArchiveEntity>>>()
    val showArchiveLimitAction: LiveData<Event<List<ArchiveEntity>>> = _showArchiveLimitAction

    fun checkLimitReachedBeforeSave() {
        mNewApi.getMyArchives(gameId, 1, SORT_TYPE_CREATE)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : com.gh.gamecenter.common.retrofit.Response<List<ArchiveEntity>>() {

                override fun onSubscribe(d: Disposable) {
                    compositeDisposable.add(d)
                }

                override fun onResponse(response: List<ArchiveEntity>?) {
                    if (response == null || response.size < UPLOAD_ARCHIVE_LIMIT_COUNT) {
                        _uploadArchiveAction.value = Event(Unit)
                    } else {
                        _showArchiveLimitAction.value = Event(response)
                    }
                }

                override fun onFailure(e: HttpException?) {
                    Utils.toast(getApplication(), "上传失败!")
                }
            })


    }

    fun replaceArchive(archiveEntity: ArchiveEntity, archiveId: String) {
        val paramsMap = mapOf(
            "name" to archiveEntity.name,
            "url" to archiveEntity.url,
            "config_url" to archiveEntity.configUrl,
            "game_version" to archiveEntity.gameVersion,
            "md5" to archiveEntity.md5
        )
        val disposable = mNewApi.replaceArchive(gameId, archiveId, paramsMap.toRequestBody())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    uploadSuccess.postValue(true)
                    NewFlatLogUtils.logCloudArchiveUploadDialogClick(
                        gameId = gameId,
                        gameName = gameName,
                        cloudSaveId = archiveId,
                        cloudSaveName = archiveEntity.name,
                        isSuccess = true
                    )
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    uploadSuccess.postValue(false)
                    NewFlatLogUtils.logCloudArchiveUploadDialogClick(
                        gameId = gameId,
                        gameName = gameName,
                        cloudSaveId = archiveId,
                        cloudSaveName = archiveEntity.name,
                        isSuccess = false
                    )
                }
            })
        compositeDisposable.add(disposable)
    }

    override fun onCleared() {
        super.onCleared()
        compositeDisposable.clear()
    }

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