package com.gh.gamecenter.cloudarchive

import android.annotation.SuppressLint
import android.app.Application
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.common.baselist.ListViewModel
import com.gh.gamecenter.common.baselist.LoadType
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.toRequestBody
import com.gh.gamecenter.entity.ArchiveEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.vspace.VArchiveHelper
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.*
import java.io.IOException

class CloudArchiveManagerViewModel(
    application: Application,
    private val mType: MyArchiveFragment.Type = MyArchiveFragment.Type.MY_ARCHIVE,
    val gameId: String,
    val configUrl: String
) :
    ListViewModel<ArchiveEntity, ArchiveEntity>(application) {

    var archiveConfigStr = ""
    private val mApi = RetrofitManager.getInstance().newApi

    val uploadSuccess = MutableLiveData<Boolean>()
    val shareSuccess = MutableLiveData<Boolean>()

    init {
        if (configUrl.isNotEmpty()) getArchiveConfigString(configUrl)
    }

    override fun mergeResultLiveData() {
        mResultLiveData.addSource(mListLiveData) { list ->
            list.forEach { it.gameId = gameId }
            mResultLiveData.postValue(list)
        }
    }

    override fun provideDataObservable(page: Int): Observable<List<ArchiveEntity>>? = when (mType) {
        MyArchiveFragment.Type.MY_ARCHIVE -> {
            mApi.getMyArchives(gameId, page)
        }
        MyArchiveFragment.Type.MY_DOWNLOAD_ARCHIVE -> null
        MyArchiveFragment.Type.MY_SHARE_ARCHIVE -> mApi.getMyShareArchives(gameId, page)
    }

    override fun provideDataSingle(page: Int): Single<MutableList<ArchiveEntity>>? {
        return if (mType == MyArchiveFragment.Type.MY_DOWNLOAD_ARCHIVE) {
            Single.create { emitter ->
                val downloadList = VArchiveHelper.vArchiveEntityListLiveData.value
                val archiveEntityList = arrayListOf<ArchiveEntity>()
                if (downloadList != null) {
                    for (vArchiveEntity in downloadList) {
                        if (vArchiveEntity.gameId == gameId && vArchiveEntity.type == 1) {
                            archiveEntityList.add(
                                ArchiveEntity(
                                    id = vArchiveEntity.id,
                                    name = vArchiveEntity.name,
                                    gameId = vArchiveEntity.gameId,
                                    desc = vArchiveEntity.descContent,
                                    url = vArchiveEntity.url,
                                    configUrl = vArchiveEntity.configUrl,
                                    md5 = vArchiveEntity.md5,
                                    time = ArchiveEntity.Time(update = vArchiveEntity.time),
                                    gameVersion = vArchiveEntity.gameVersion
                                )
                            )
                        }
                    }
                }
                emitter.onSuccess(archiveEntityList)
            }
        } else {
            null
        }
    }

    @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
        )
        mApi.postMyArchive(gameId, paramsMap.toRequestBody())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    uploadSuccess.postValue(true)
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    uploadSuccess.postValue(false)
                }
            })
    }

    @SuppressLint("CheckResult")
    fun shareArchive(archiveEntity: ArchiveEntity, shareName: String, shareDesc: String) {
        val paramsMap = mapOf(
            "share_name" to shareName,
            "share_desc" to shareDesc,
            "is_shared" to true
        )
        mApi.patchMyArchive(gameId, archiveEntity.id, paramsMap.toRequestBody())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    shareSuccess.postValue(true)
                    Utils.toast(getApplication(), "分享成功")
                    NewFlatLogUtils.logCloudArchiveShareDialogResult("分享成功")
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    shareSuccess.postValue(false)
                    Utils.toast(getApplication(), "分享失败")
                    NewFlatLogUtils.logCloudArchiveShareDialogResult("分享失败")
                }
            })
    }

    @SuppressLint("CheckResult")
    fun cancelShareArchive(archiveEntity: ArchiveEntity) {
        val paramsMap = mapOf(
            "is_shared" to false
        )
        mApi.patchMyArchive(gameId, archiveEntity.id, paramsMap.toRequestBody())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    load(LoadType.REFRESH)
                    Utils.toast(getApplication(), "取消分享成功")
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    Utils.toast(getApplication(), "取消分享失败")
                }
            })
    }

    @SuppressLint("CheckResult")
    fun editMyArchive(archiveEntity: ArchiveEntity) {
        val paramsMap = mapOf(
            "name" to archiveEntity.name
        )
        mApi.patchMyArchive(gameId, archiveEntity.id, paramsMap.toRequestBody())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    load(LoadType.REFRESH)
                }
            })
    }

    @SuppressLint("CheckResult")
    fun deleteArchive(archiveEntity: ArchiveEntity) {
        mApi.deleteMyArchive(gameId, archiveEntity.id)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    load(LoadType.REFRESH)
                    Utils.toast(getApplication(), "删除成功")
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    Utils.toast(getApplication(), "删除失败")
                }
            })
    }


    // 通过url获取config字符串内容
    private fun getArchiveConfigString(url: String) {
        OkHttpClient().newCall(
            Request.Builder()
                .url(url)
                .build()
        )
            .enqueue(object : Callback {
                override fun onFailure(call: Call, e: IOException) {
                    e.printStackTrace()
                }

                override fun onResponse(call: Call, response: Response) {
                    archiveConfigStr = response.body()?.string() ?: ""
                }
            })
    }

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