package com.gh.gamecenter.video.upload.view

import android.annotation.SuppressLint
import android.app.Application
import android.media.MediaMetadataRetriever
import android.net.Uri
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
import com.gh.common.util.*
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.common.utils.toJson
import com.gh.gamecenter.common.utils.tryCatchInRelease
import com.gh.gamecenter.common.utils.tryWithDefaultCatch
import com.gh.gamecenter.entity.*
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.common.mvvm.Resource
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.UploadImageUtils
import com.gh.gamecenter.energy.EnergyBridge
import com.gh.gamecenter.retrofit.RetrofitManager
import com.google.gson.JsonObject
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.RequestBody
import okhttp3.ResponseBody
import org.json.JSONObject
import retrofit2.HttpException
import java.io.File

class UploadVideoViewModel(application: Application) : AndroidViewModel(application) {

    private val mApi = RetrofitManager.getInstance().api

    val tagsLiveData = MutableLiveData<List<VideoTagEntity>>()
    val categoryLiveData = MutableLiveData<List<VideoTagEntity>>()
    val processDialog = MediatorLiveData<WaitingDialogFragment.WaitingDialogData>()
    val postLiveData = MediatorLiveData<Resource<MyVideoEntity>>()
    val postDraftLiveData = MediatorLiveData<Resource<String>>()
    val deleteDraftLiveData = MutableLiveData<String>()
    val activityTagLiveData = MutableLiveData<Boolean>()

    var videoPatch: VideoEntity? = null
    var videoDraft: VideoDraftEntity? = null
    var gameEntity: SimpleGameEntity? = null

    init {
        getVideoTags()
        getVideoCategory()
        //v5.0.0关闭选择活动标签入口
        //getActivityTagStatus()
    }

    private fun postVideo(jsonObject: JSONObject) {
        processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
        val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
        mApi.postVideo(body)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<ResponseBody>() {

                override fun onResponse(response: ResponseBody?) {
                    processDialog.postValue(WaitingDialogFragment.WaitingDialogData("", false))
                    tryWithDefaultCatch {
                        val videoId = JSONObject(response?.string().toString()).getString("_id")

                        val poster = jsonObject.getString("poster")
                        val url = jsonObject.getString("url")
                        val length = jsonObject.getLong("length")
                        postLiveData.postValue(
                            Resource.success(
                                MyVideoEntity(
                                    id = videoId,
                                    poster = poster,
                                    url = url,
                                    length = length,
                                    status = "pending"
                                )
                            )
                        )

                        EnergyBridge.postEnergyTask("upload_video", videoId)
                    }
                }

                override fun onFailure(e: HttpException?) {
                    processDialog.postValue(WaitingDialogFragment.WaitingDialogData("", false))
                    postLiveData.postValue(Resource.error(e))
                }
            })
    }

    @SuppressLint("CheckResult")
    private fun postDraft(body: RequestBody) {
        processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
        val postVideoDraft = if (videoDraft != null) {
            mApi.patchVideoDraft(UserManager.getInstance().userId, body, videoDraft?.id)
        } else {
            mApi.postVideoDraft(UserManager.getInstance().userId, body)
        }

        postVideoDraft
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    processDialog.postValue(WaitingDialogFragment.WaitingDialogData("", false))
                    postDraftLiveData.postValue(Resource.success(""))
                }

                override fun onFailure(exception: Exception) {
                    processDialog.postValue(WaitingDialogFragment.WaitingDialogData("", false))
                    postDraftLiveData.postValue(Resource.error(null))
                }

            })
    }


    private fun patchVideo(jsonObject: JSONObject, videoId: String) {
        processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
        val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
        mApi.patchVideo(body, videoId)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<ResponseBody>() {

                override fun onResponse(response: ResponseBody?) {
                    processDialog.postValue(WaitingDialogFragment.WaitingDialogData("", false))
                    val poster = jsonObject.getString("poster")
                    val url = jsonObject.getString("url")
                    val length = jsonObject.getLong("length")
                    postLiveData.postValue(
                        Resource.success(
                            MyVideoEntity(
                                id = videoId,
                                poster = poster,
                                url = url,
                                length = length,
                                status = "pending"
                            )
                        )
                    )
                }

                override fun onFailure(e: HttpException?) {
                    processDialog.postValue(WaitingDialogFragment.WaitingDialogData("", false))
                    postLiveData.postValue(Resource.error(e))
                }
            })
    }

    fun postVideoPosterAndContent(
        isDraft: Boolean,
        content: VideoEntity,
        videoPath: String?,
        videoPoster: String,
        watermark: Boolean = false
    ) {
        processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传视频封面中...", true))
        val application: Application = getApplication()
        UploadImageUtils.compressAndUploadImage(
            UploadImageUtils.UploadType.poster, videoPoster, true,
            object : UploadImageUtils.OnUploadImageListener {
                override fun onSuccess(imageUrl: String) {
                    content.poster = imageUrl
                    postContent(isDraft, content, videoPath, watermark)
                }

                override fun onError(e: Throwable?) {
                    processDialog.postValue(WaitingDialogFragment.WaitingDialogData("", false))
                    if (e != null && e is HttpException && e.code() == 403) {
                        Utils.toast(getApplication(), "图片违规，请重新编辑")
                    } else {
                        Utils.toast(application, "保存失败，请检查网络正常后再重试")
                    }
                }

                override fun onProgress(total: Long, progress: Long) {
                }
            })
    }

    fun postContent(isDraft: Boolean, videoEntity: VideoEntity, videoPath: String?, watermark: Boolean = false) {
        if (videoPatch != null) {
            patchVideo(JSONObject(GsonUtils.toJson(videoEntity)), videoEntity.id)
        } else if (isDraft) {
            val draftData = JSONObject(videoEntity.toJson()).put("local_path", videoPath).toString()
            val body = RequestBody.create(MediaType.parse("application/json"), draftData)
            postDraft(body)
        } else {
            var videoHeight = 0
            var videoWidth = 0
            videoPath.let {
                tryCatchInRelease {
                    val retriever = MediaMetadataRetriever()
                    retriever.setDataSource(getApplication(), Uri.fromFile(File(it)))
                    videoWidth =
                        Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH))
                    videoHeight =
                        Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT))
                    retriever.release()
                }
            }

            val requestJson = JSONObject(GsonUtils.toJson(videoEntity))
            requestJson.put("watermark", watermark)
            requestJson.put("height", videoHeight)
            requestJson.put("width", videoWidth)

            postVideo(requestJson)
        }
    }

    @SuppressLint("CheckResult")
    private fun getActivityTagStatus() {
        mApi.activityTagStatus
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<JsonObject>() {
                override fun onSuccess(data: JsonObject) {
                    val status = data.get("status").asString//on, off
                    activityTagLiveData.postValue(status == "on")
                }

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

    @SuppressLint("CheckResult")
    private fun getVideoTags() {
        mApi.videoTags
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<List<VideoTagEntity>>() {
                override fun onSuccess(data: List<VideoTagEntity>) {
                    tagsLiveData.postValue(data)
                }

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


    @SuppressLint("CheckResult")
    private fun getVideoCategory() {
        mApi.videoCategories
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<List<VideoTagEntity>>() {
                override fun onSuccess(data: List<VideoTagEntity>) {
                    categoryLiveData.postValue(data)
                }

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

    fun deleteDraft(id: String) {
        mApi.deleteVideoDraft(UserManager.getInstance().userId, id)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    deleteDraftLiveData.postValue(response?.string() ?: "")
                }

                override fun onFailure(e: HttpException?) {
                    ErrorHelper.handleError(getApplication(), e?.response()?.errorBody()?.string())
                    deleteDraftLiveData.postValue(e?.response()?.errorBody()?.string() ?: "")
                }
            })
    }
}