package com.gh.gamecenter.qa.video.publish

import android.annotation.SuppressLint
import android.app.Application
import android.graphics.Bitmap
import android.media.MediaMetadataRetriever
import android.media.ThumbnailUtils
import android.net.Uri
import android.provider.MediaStore
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
import com.gh.gamecenter.common.entity.CommunityEntity
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.utils.*
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.ObservableUtil
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.feature.entity.ForumVideoEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.google.gson.JsonObject
import com.halo.assistant.HaloApp
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
import java.io.FileOutputStream

class VideoPublishViewModel(application: Application) : AndroidViewModel(application) {
    private val mApi = RetrofitManager.getInstance().api
    private val mNewApi = RetrofitManager.getInstance().newApi
    var type: String = ""
    var communityEntity: CommunityEntity? = null
    var selectActivityLabelEntity: ActivityLabelEntity? = null
    var selectSection: ForumDetailEntity.Section? = null
    var videoPatch: ForumVideoEntity? = null
    var videoDraft: VideoDraftEntity? = null
    var gameEntity: GameEntity? = null
    val postDraftLiveData = MediatorLiveData<Resource<String>>()
    val processDialog = MediatorLiveData<WaitingDialogFragment.WaitingDialogData>()
    val postLiveData = MediatorLiveData<Resource<ForumVideoEntity>>()
    val sectionListLiveData = MutableLiveData<List<ForumDetailEntity.Section>>()
    var isModerator = false

    fun postVideoPosterAndContent(
        isDraft: Boolean,
        videoEntity: ForumVideoEntity,
        updatedPosterPath: String,
        videoPath: String?
    ) {
        processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传视频封面中...", true))
        var videoPoster = ""
        val latch = ObservableUtil.latch(1, {
            UploadImageUtils.compressAndUploadImage(
                UploadImageUtils.UploadType.poster, videoPoster, true,
                object : UploadImageUtils.OnUploadImageListener {
                    override fun onSuccess(imageUrl: String) {
                        videoEntity.poster = imageUrl
                        postContent(isDraft, videoEntity, videoPath)
                    }

                    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(getApplication(), "保存失败，请检查网络正常后再重试")
                        }
                    }

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

        runOnIoThread {
            videoPoster = if (updatedPosterPath.isNotEmpty()) {
                updatedPosterPath
            } else {
                val localVideoPoster =
                    HaloApp.getInstance().cacheDir.absolutePath + File.separator + System.currentTimeMillis() + ".jpg"
                try {
                    val bmp =
                        ThumbnailUtils.createVideoThumbnail(videoPath ?: "", MediaStore.Images.Thumbnails.MINI_KIND)
                    // bmp 可能为空
                    FileOutputStream(localVideoPoster).use { out ->
                        bmp?.compress(Bitmap.CompressFormat.PNG, 100, out)
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                    ToastUtils.toast("视频封面操作失败")
                    processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传视频封面中...", false))
                    return@runOnIoThread
                }
                localVideoPoster
            }
            latch.countDown()
        }
    }

    fun postContent(isDraft: Boolean, videoEntity: ForumVideoEntity, videoPath: String?) {
        if (ClickUtils.isFastDoubleClick(323, 1000)) return

        when {
            isDraft -> {
                val draftData = JSONObject(videoEntity.toJson()).put("local_path", videoPath).toString()
                val body = RequestBody.create(MediaType.parse("application/json"), draftData)
                postDraft(body)
            }
            videoPatch != null -> {
                patchVideo(JSONObject(GsonUtils.toJson(videoEntity)), videoEntity.id)
            }
            else -> {
                val requestJson = JSONObject(GsonUtils.toJson(videoEntity))
                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 videoInfo = JSONObject()
                videoInfo.put("height", videoHeight)
                videoInfo.put("width", videoWidth)
                requestJson.put("video_info", videoInfo)
                requestJson.put("section_id", selectSection?.id ?: "")

                postVideo(requestJson)
            }
        }
    }

    private fun patchVideo(jsonObject: JSONObject, videoId: String) {
        processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
        val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
        mApi.patchBbsVideo(videoId, body)
            .compose(observableToMain())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)
                    processDialog.postValue(WaitingDialogFragment.WaitingDialogData("", false))
                    val poster = jsonObject.getString("poster")
                    val url = jsonObject.getString("url")
                    val length = jsonObject.getLong("length")
                    postLiveData.postValue(
                        Resource.success(
                            ForumVideoEntity(
                                id = videoId,
                                poster = poster,
                                url = url,
                                length = length,
                                status = "pending"
                            )
                        )
                    )
                }

                override fun onFailure(e: HttpException?) {
                    super.onFailure(e)
                    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 postVideo(jsonObject: JSONObject) {
        processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
        val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
        mApi.postBbsVideo(body)
            .compose(observableToMain())
            .subscribe(object : Response<JsonObject>() {
                override fun onResponse(response: JsonObject?) {
                    super.onResponse(response)
                    processDialog.postValue(WaitingDialogFragment.WaitingDialogData("", false))
                    tryWithDefaultCatch {
                        response?.let {
                            val videoId = it.get("_id").asString
                            val poster = it.get("poster").asString
                            val url = it.get("url").asString
                            val length = it.get("length").asLong
                            postLiveData.postValue(
                                Resource.success(
                                    ForumVideoEntity(
                                        id = videoId,
                                        poster = poster,
                                        url = url,
                                        length = length,
                                        status = "pending"
                                    )
                                )
                            )
                        }
                    }
                }

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

    fun getForumSections(bbsId: String) {
        mNewApi.getForumSections(bbsId)
            .compose(observableToMain())
            .subscribe(object : Response<List<ForumDetailEntity.Section>>() {
                override fun onResponse(response: List<ForumDetailEntity.Section>?) {
                    response?.run {
                        sectionListLiveData.postValue(this)
                    }
                }
            })
    }

    @SuppressLint("CheckResult")
    fun getModeratorsInfo(bbsId: String) {
        mApi.getModeratorsInfo(bbsId)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<JsonObject>() {
                override fun onSuccess(data: JsonObject) {
                    isModerator = data["is_moderators"].asBoolean
                }
            })
    }
}