package com.gh.gamecenter.video.detail

import android.annotation.SuppressLint
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.exposure.meta.MetaUtil
import com.gh.common.history.HistoryDatabase
import com.gh.gamecenter.core.runOnIoThread
import com.gh.download.DownloadManager
import com.gh.gamecenter.common.utils.createRequestBodyAny
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.common.utils.tryCatchInRelease
import com.gh.gamecenter.core.utils.UrlFilterUtils
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.entity.MyVideoEntity
import com.gh.gamecenter.entity.User
import com.gh.gamecenter.entity.VideoEntity
import com.gh.gamecenter.eventbus.EBUserFollow
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.google.gson.JsonObject
import com.lightgame.utils.Utils
import io.reactivex.Single
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import org.greenrobot.eventbus.EventBus
import java.lang.ref.WeakReference
import java.util.*
import kotlin.collections.ArrayList
import kotlin.random.Random

@SuppressLint("CheckResult")
class VideoDetailContainerViewModel(application: Application) : AndroidViewModel(application) {

    var startPosition = 0
    var showComment = false
    var currentDisplayingVideo: VideoEntity? = null
    var entrance = ""
    var path = ""
    var entranceDetail = "" // 视频流入口链接, WEB（$页面Url$）

    var refreshFinish = MutableLiveData<Boolean>()
    var noDataError = MutableLiveData<Boolean>()
    var networkError = MutableLiveData<Boolean>()
    var videoList = MutableLiveData<ArrayList<VideoEntity>>()

    var needToUpdateVideoInfo = MutableLiveData<VideoEntity>()
    var followVideoInfo = MutableLiveData<VideoEntity>()
    var uuid = ""
    var location = ""
    var isHomeVideo = false // 是否是视频总入口
    var gameId = ""
    var type = ""//活动type
    var act = ""//活动名称
    var paginationType = "page"//活动分页方式 page(默认) filter
    var fieldId = ""//专区视频板块id
    var sectionName = ""//专区视频专题名
    var positionAndPackageMap = HashMap<String, Int>() // key: packageName + position, value: position
    var isPauseVideo = true
    private var page = 1
    private var cacheVideoIds: MutableList<String>? = null
    private var cacheId = ""
    private var mRecyclerViewRef: WeakReference<RecyclerView>? = null
    private var total = 0

    // 是否为第一次加载(即没有进行加载更多)
    private var mIsFirstLoad = true

    fun setRecyclerView(recyclerView: RecyclerView) {
        mRecyclerViewRef = WeakReference(recyclerView)
    }

    fun collect() {
        collectVideo(currentDisplayingVideo)
    }

    fun undoCollect() {
        undoCollectVideo(currentDisplayingVideo)
    }

    @SuppressLint("CheckResult")
    fun getVideoDetailList(videoId: String, location: String, isLoadNext: Boolean) {
        when (location) {
            Location.VIDEO_CHOICENESS.value -> {
                if (isLoadNext) {
                    getVideoStream(location, videoId, isLoadNext)
                } else {
                    if (isHomeVideo) {
                        page = 1
                        mIsFirstLoad = true
                        cacheVideoIds = null
                        getVideoStream(location, videoId, isLoadNext)
                    }
                }
            }
            Location.VIDEO_HOT.value,
            Location.GAME_DETAIL.value -> {
                if (isLoadNext) {
                    getVideoStream(location, videoId, isLoadNext)
                }
            }
            /* Location.VIDEO_NEWEST.value -> {
                 if (!isLoadNext) {
                     page = 1
                     mIsFirstLoad = true
                 }
                 getNewestVideoStream(isLoadNext)
             }*/
            Location.VIDEO_ATTENTION.value -> {
                if (!isLoadNext) {
                    page = 1
                    mIsFirstLoad = true
                    total = 0
                }
                getAttentionVideoStream(isLoadNext)
            }
            Location.VIDEO_ACTIVITY.value -> {
                //判断是否是老版本活动，老版本活动使用page分页，新版本使用filter
                if (paginationType == "page") {
                    if (isLoadNext) {
                        getActivityVideoStream(videoId, isLoadNext)
                    }
                } else {
                    getNormalVideoStream(videoId, location, isLoadNext)
                }
            }
            else -> {
                getNormalVideoStream(videoId, location, isLoadNext)
            }
        }
    }

    private fun getNormalVideoStream(videoId: String, location: String, isLoadNext: Boolean) {
        val videoListSingle = when (location) {
            Location.GAME_ZONE.value -> {
                RetrofitManager.getInstance()
                    .api.getVideoDetailList(videoId, getFilter(location, isLoadNext), fieldId, sectionName)
            }
            Location.VIDEO_ACTIVITY.value -> {
                RetrofitManager.getInstance()
                    .api.getActivitiesVideoStreamScroll(videoId, type, act, getFilter(location, isLoadNext))
            }
            else -> {
                RetrofitManager.getInstance()
                    .api.getVideoDetailList(videoId, getFilter(location, isLoadNext))
            }
        }

        videoListSingle.subscribeOn(Schedulers.io())
            .subscribe(object : BiResponse<ArrayList<VideoEntity>>() {
                override fun onSuccess(data: ArrayList<VideoEntity>) {
                    if (mIsFirstLoad) {
                        // 无数据时直接显示无数据页面
                        if (data.size == 0) {
                            noDataError.postValue(true)
                            return
                        }
                        val index = data.indexOfFirst { video -> videoId == video.id }
                        startPosition = if (index >= 0) index else 0
                    }

                    if (mIsFirstLoad || !(data.size == 1 && data[0].id == videoId)) {
                        mergeVideoList(data, isLoadNext)
                    }

                    mIsFirstLoad = false
                }

                override fun onFailure(exception: Exception) {
                    if (mIsFirstLoad) {
                        networkError.postValue(true)
                        mIsFirstLoad = false
                    }
                }
            })
    }

    //获取最新排序的视频流
    private fun getNewestVideoStream(isLoadNext: Boolean) {
        RetrofitManager.getInstance()
            .api.getVideoStream(page)
            .subscribeOn(Schedulers.io())
            .subscribe(object : BiResponse<ArrayList<VideoEntity>>() {
                override fun onSuccess(data: ArrayList<VideoEntity>) {
                    if (mIsFirstLoad) {
                        // 无数据时直接显示无数据页面
                        if (data.size == 0) {
                            noDataError.postValue(true)
                            return
                        }
                    }
                    page++
                    //下拉刷新清除列表数据
                    if (isLoadNext) {
                        mergeVideoList(data, isLoadNext)
                    } else if (!isLoadNext && mRecyclerViewRef?.get()?.computeVerticalScrollOffset() == 0) {
                        //下拉刷新并且列表没有滚动清除列表数据，数据发生变化
                        videoList.value?.clear()
                        mergeVideoList(data, isLoadNext)
                    } else {
                        //下拉刷新并且列表滚动中关闭下拉刷新动画，数据不变
                        refreshFinish.postValue(true)
                    }

                    mIsFirstLoad = false
                }

                override fun onFailure(exception: Exception) {
                    if (mIsFirstLoad) {
                        networkError.postValue(true)
                        mIsFirstLoad = false
                    }
                }
            })
    }

    //获取关注用户的视频流
    private fun getAttentionVideoStream(isLoadNext: Boolean) {
        if (!mIsFirstLoad && total <= videoList.value?.size ?: 0) return
        val requestMap = hashMapOf<String, Any>()
        getAttentionCacheVideoIds().flatMap {
            requestMap["cache_video_ids"] = it
            val body = requestMap.createRequestBodyAny()
            if (page == 1) {
                deleteAttentionCacheVideo()
                RetrofitManager.getInstance()
                    .api.getAttentionVideoStreamRefresh(UserManager.getInstance().userId, body, page)
            } else {
                RetrofitManager.getInstance()
                    .api.getAttentionVideoStream(UserManager.getInstance().userId, body, page)
            }
        }
            .compose(singleToMain())
            .subscribe(object : BiResponse<retrofit2.Response<ArrayList<VideoEntity>>>() {
                override fun onSuccess(data: retrofit2.Response<ArrayList<VideoEntity>>) {
                    val headers = data.headers()
                    total = headers.get("total")?.toInt() ?: 0

                    val videoEntities = data.body() ?: arrayListOf()

                    if (mIsFirstLoad) {
                        // 无数据时直接显示无数据页面
                        if (videoEntities.isEmpty()) {
                            noDataError.postValue(true)
                            return
                        }
                    }
                    page++
                    if (isLoadNext) {
                        mergeVideoList(videoEntities, isLoadNext)
                    } else if (!isLoadNext && mRecyclerViewRef?.get()?.computeVerticalScrollOffset() == 0) {
                        //下拉刷新并且列表没有滚动清除列表数据，数据发生变化
                        videoList.value?.clear()
                        mergeVideoList(videoEntities, isLoadNext)
                    } else {
                        //下拉刷新并且列表滚动中关闭下拉刷新动画，数据不变
                        refreshFinish.postValue(true)
                    }

                    mIsFirstLoad = false
                }

                override fun onFailure(exception: Exception) {
                    if (mIsFirstLoad) {
                        networkError.postValue(true)
                        mIsFirstLoad = false
                    }
                }
            })
    }

    private fun getVideoStream(type: String, videoId: String, isLoadNext: Boolean) {
        val requestMap = hashMapOf<String, Any>()
        getCacheVideoIds().flatMap {
            cacheVideoIds = it
            requestMap["cache_video_ids"] = it
            val body = requestMap.createRequestBodyAny()
            if (cacheId.isEmpty()) {
                cacheId = "${MetaUtil.getIMEI()}${System.currentTimeMillis()}${Random.nextInt(9999)}"
            }
            if (type == Location.GAME_DETAIL.value) {
                RetrofitManager.getInstance()
                    .api.getGameDetailVideoStream(type, body, videoId, gameId, page)
            } else {
                RetrofitManager.getInstance()
                    .api.getVideoStream(type, body, videoId, cacheId, page)
            }
        }.subscribeOn(Schedulers.io())
            .subscribe(object : BiResponse<ArrayList<VideoEntity>>() {
                override fun onSuccess(data: ArrayList<VideoEntity>) {
                    if (mIsFirstLoad) {
                        // 无数据时直接显示无数据页面
                        if (data.size == 0) {
                            noDataError.postValue(true)
                            return
                        }
                        startPosition = 0
                    }
                    page++
                    //总播放算法-当获取的数据总数少于page_size时，重新将page设为1再重新循环
                    if (type == Location.VIDEO_CHOICENESS.value && data.size < 20) {
                        page = 1
                    }
                    if (mIsFirstLoad || !(data.size == 1 && data[0].id == videoId)) {
                        //下拉刷新清除列表数据
                        if (isLoadNext) {
                            mergeVideoList(data, isLoadNext)
                        } else if (!isLoadNext && mRecyclerViewRef?.get()?.computeVerticalScrollOffset() == 0) {
                            //下拉刷新并且列表没有滚动清除列表数据，数据发生变化
                            videoList.value?.clear()
                            mergeVideoList(data, isLoadNext)
                        } else {
                            //下拉刷新并且列表滚动中关闭下拉刷新动画，数据不变
                            refreshFinish.postValue(true)
                        }
                    }

                    mIsFirstLoad = false
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    if (mIsFirstLoad) {
                        networkError.postValue(true)
                        mIsFirstLoad = false
                    }
                }
            })
    }

    //获取活动的视频流
    private fun getActivityVideoStream(videoId: String, isLoadNext: Boolean) {
        RetrofitManager.getInstance()
            .api.getActivitiesVideoStream(videoId, page, type, act)
            .subscribeOn(Schedulers.io())
            .subscribe(object : BiResponse<ArrayList<VideoEntity>>() {
                override fun onSuccess(data: ArrayList<VideoEntity>) {
                    if (mIsFirstLoad) {
                        // 无数据时直接显示无数据页面
                        if (data.size == 0) {
                            noDataError.postValue(true)
                            return
                        }
                    }
                    page++
                    mergeVideoList(data, isLoadNext)
                    mIsFirstLoad = false
                }

                override fun onFailure(exception: Exception) {
                    if (mIsFirstLoad) {
                        networkError.postValue(true)
                        mIsFirstLoad = false
                    }
                }
            })
    }

    //获取视频缓存ids
    private fun getCacheVideoIds(): Single<MutableList<String>> {
        return if (cacheVideoIds != null) {
            Single.create { emitter -> emitter.onSuccess(cacheVideoIds!!) }
        } else {
            HistoryDatabase.instance.videoHistoryDao()
                .getVideoStreamRecord(100, 0)
        }
    }

    //获取关注视频缓存ids
    private fun getAttentionCacheVideoIds(): Single<MutableList<String>> {
        return HistoryDatabase.instance.videoHistoryDao()
            .getAttentionVideoRecord()
    }

    private fun deleteAttentionCacheVideo() {
        runOnIoThread {
            HistoryDatabase.instance.videoHistoryDao().deleteAttentionVideoRecord()
        }
    }

    fun mergeVideoList(receivedDataList: ArrayList<VideoEntity>, isLoadNext: Boolean = true) {
        if (receivedDataList.isNullOrEmpty()) return

        val onDisplayingVideoList = videoList.value
        positionAndPackageMap.clear()
        if (onDisplayingVideoList.isNullOrEmpty()) {
            videoList.postValue(receivedDataList)
            for (i in 0 until receivedDataList.size) {
                addGamePositionAndPackage(receivedDataList[i].game, i)
            }
        } else {
            if (isLoadNext) {
                onDisplayingVideoList.addAll(receivedDataList)
            } else {
                onDisplayingVideoList.addAll(0, receivedDataList)
                startPosition += receivedDataList.size
            }
            videoList.postValue(onDisplayingVideoList)
            for (i in 0 until onDisplayingVideoList.size) {
                addGamePositionAndPackage(onDisplayingVideoList[i].game, i)
            }
        }
    }

    fun getFilter(location: String, isLoadNext: Boolean = true): String {
        return if (location == Location.SINGLE_VIDEO.value) {
            UrlFilterUtils.getFilterQuery("location", location, "next", "0", "last", "0")
        } else {
            if (mIsFirstLoad) {
                if (location == Location.HOTTEST_GAME_VIDEO.value || location == Location.NEWEST_GAME_VIDEO.value || location == Location.GAME_ZONE.value) {
                    UrlFilterUtils.getFilterQuery("location", location, "next", "20", "last", "20", "game_id", gameId)
                } else {
                    UrlFilterUtils.getFilterQuery("location", location, "next", "20", "last", "20")
                }
            } else {
                if (isLoadNext) {
                    if (location == Location.HOTTEST_GAME_VIDEO.value || location == Location.NEWEST_GAME_VIDEO.value || location == Location.GAME_ZONE.value) {
                        UrlFilterUtils.getFilterQuery("location", location, "next", "20", "game_id", gameId)
                    } else {
                        UrlFilterUtils.getFilterQuery("location", location, "next", "20")
                    }
                } else {
                    if (location == Location.HOTTEST_GAME_VIDEO.value || location == Location.NEWEST_GAME_VIDEO.value || location == Location.GAME_ZONE.value) {
                        UrlFilterUtils.getFilterQuery("location", location, "last", "20", "game_id", gameId)
                    } else {
                        UrlFilterUtils.getFilterQuery("location", location, "last", "20")
                    }
                }
            }
        }
    }

    fun voteVideo(videoDetail: VideoEntity?) {
        RetrofitManager.getInstance()
            .api.voteVideo(videoDetail!!.id)
            .subscribeOn(Schedulers.io())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    //Utils.toast(getApplication(), "已点赞")
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    videoDetail.let {
                        it.vote--
                        it.me.isVoted = false
                    }
                    needToUpdateVideoInfo.postValue(videoDetail)
                }
            })
    }

    fun undoVoteVideo(videoDetail: VideoEntity?) {
        RetrofitManager.getInstance()
            .api.undoVoteVideo(videoDetail!!.id)
            .subscribeOn(Schedulers.io())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    Utils.toast(getApplication(), "取消点赞")
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    videoDetail.let {
                        it.vote++
                        it.me.isVoted = true
                    }
                    needToUpdateVideoInfo.postValue(videoDetail)
                }
            })
    }


    private fun collectVideo(videoDetail: VideoEntity?) {
        RetrofitManager.getInstance()
            .api.collectVideo(UserManager.getInstance().userId, videoDetail!!.id)
            .subscribeOn(Schedulers.io())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    videoDetail.me.isVideoFavorite = true
                    needToUpdateVideoInfo.postValue(videoDetail)
                    Utils.toast(getApplication(), "收藏成功")
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    Utils.toast(getApplication(), exception.localizedMessage)
                }
            })
    }

    private fun undoCollectVideo(videoDetail: VideoEntity?) {
        RetrofitManager.getInstance()
            .api.undoCollectVideo(UserManager.getInstance().userId, videoDetail!!.id)
            .subscribeOn(Schedulers.io())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    videoDetail.me.isVideoFavorite = false
                    needToUpdateVideoInfo.postValue(videoDetail)
                    Utils.toast(getApplication(), "取消收藏")
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    Utils.toast(getApplication(), exception.localizedMessage)
                }
            })
    }

    fun addHistoryRecord(videoEntity: VideoEntity) {
        val videoHistory = MyVideoEntity().apply {
            id = videoEntity.id
            poster = videoEntity.poster
            url = videoEntity.url
            vote = videoEntity.vote
            length = videoEntity.length
            time = System.currentTimeMillis()
            title = videoEntity.title
            user = User(
                videoEntity.user.id ?: "", videoEntity.user.name
                    ?: "", videoEntity.user.icon ?: ""
            )
            commentCount = videoEntity.commentCount
            videoStreamRecord = when (location) {
                Location.VIDEO_CHOICENESS.value, Location.VIDEO_HOT.value -> {
                    1
                }
                Location.VIDEO_ATTENTION.value -> {
                    2
                }
                else -> {
                    0
                }
            }
        }

        runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.videoHistoryDao().addVideo(videoHistory) } }
    }

    fun shareVideoStatistics(videoEntity: VideoEntity?) {
        if (videoEntity == null) return

        RetrofitManager.getInstance()
            .api.shareVideoStatistics(videoEntity.id)
            .subscribeOn(Schedulers.io())
            .subscribe(object : BiResponse<JsonObject>() {
                override fun onSuccess(data: JsonObject) {
                    val msg = data.get("msg").asString
                    if ("success" == msg) {
                        videoEntity.let {
                            it.shareCount++
                        }
                        needToUpdateVideoInfo.postValue(videoEntity)
                    }
                }
            })

    }

    fun follow(videoEntity: VideoEntity?) {
        RetrofitManager.getInstance()
            .api.postFollowing(videoEntity!!.user.id)
            .subscribeOn(Schedulers.io())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)
                    videoEntity.me.isFollower = true
                    followVideoInfo.postValue(videoEntity)
                    Utils.toast(getApplication(), "关注成功")
                    EventBus.getDefault().post(EBUserFollow(videoEntity.user.id, true))
                }
            })

    }

    private fun addGamePositionAndPackage(game: GameEntity?, position: Int) {
        if (game == null) return

        var packages = ""
        for (apkEntity in game.getApk()) {
            packages += apkEntity.packageName
        }
        packages += game.simulator?.apk?.packageName
        positionAndPackageMap[packages + position] = position
        game.gameLocation = GameEntity.GameLocation.INDEX
        game.setEntryMap(DownloadManager.getInstance().getEntryMap(game.name))
    }

    fun reset() {
        startPosition = 0
        page = 1
        total = 0
        mIsFirstLoad = true
        videoList.value?.clear()
    }

    /**
     * 后台定义的类型 [https://gitlab.ghzs.com/halo/halo-api/wikis/v3.7/%E6%B8%B8%E6%88%8F%E8%A7%86%E9%A2%91#get-videosvideo_id]
     * hottest_game_video 视频合集(最热),
     * newest_game_video 视频合集(最新),
     * user_video 用户上传视频（已通过审核的）,
     * user_favorite_video 用户收藏视频，
     * user_uploaded_video 用户已投稿视频(包含所有状态)
     *
     * 当 location = videoId 时是取只加载视频列表在该视频以下的部分
     *
     * APP 自定义的类型
     * single_video 仅当前视频(即只拿一个视频)
     *
     * v372新增 [https://gitlab.ghzs.com/halo/halo-api/wikis/v3.7.2/API-v3.7.2#get-videosstream]
     * choiceness 总播放算法，使用场景：导航栏视频总入口、新首页-轮播图、新首页-内容管理、问答-推荐入口
     * hot 单个游戏播放算法，使用场景：游戏详情、回答详情、文章详情
     *
     * v375新增 [https://gitlab.ghzs.com/halo/halo-api/wikis/v3.7.5/api-v3.7.5#get-videosstream]
     * newest 获取最新排序的视频流
     * activity_video 获取活动的视频流
     *
     * v400新增[https://gitlab.ghzs.com/halo/halo-api/-/wikis/v4.0.0/API-v4.0.0#post-videosstream]
     * game_detail 游戏详情视频流播放算法，使用场景：游戏详情
     *
     * v410新增
     * game_zone 游戏专区视频播放算法
     *
     * v480新增
     * attention 首页关注视频流
     */
    enum class Location(val value: String) {
        HOTTEST_GAME_VIDEO("hottest_game_video"),

        NEWEST_GAME_VIDEO("newest_game_video"),

        USER_VIDEO("user_video"),

        USER_FAVORITE_VIDEO("user_favorite_video"),

        USER_UPLOADED_VIDEO("user_uploaded_video"),

        SINGLE_VIDEO("single_video"),

        VIDEO_CHOICENESS("choiceness"),

        VIDEO_HOT("hot"),

        VIDEO_NEWEST("newest"),

        VIDEO_ACTIVITY("activity_video"),

        GAME_DETAIL("game_detail"),

        GAME_ZONE("game_zone"),

        VIDEO_ATTENTION("attention")
    }

}