package com.gh.gamecenter.forum.home.follow.viewmodel

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import com.gh.common.util.CheckLoginUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.baselist.LoadStatus
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.JSONObjectResponse
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.observableToMain
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.entity.FollowUserEntity
import com.gh.gamecenter.eventbus.EBUserFollow
import com.gh.gamecenter.feature.entity.*
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.forum.home.follow.FollowArticleItem
import com.gh.gamecenter.forum.home.follow.FollowItem
import com.gh.gamecenter.forum.home.follow.FollowPostCardItem
import com.gh.gamecenter.forum.home.follow.FollowUserItem
import com.gh.gamecenter.forum.home.follow.eventlistener.OnFollowHomeEventListener
import com.gh.gamecenter.forum.home.follow.fragment.FollowHomeFragment.Companion.LOCATION_FOLLOW_PAGE
import com.gh.gamecenter.forum.home.follow.model.FollowRepository
import com.gh.gamecenter.home.custom.CommonContentCollectionUseCase
import com.gh.gamecenter.home.custom.CustomPageTracker
import com.gh.gamecenter.home.custom.model.CustomPageData
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.commonContentLayoutToComponentName
import com.gh.gamecenter.livedata.Event
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import org.greenrobot.eventbus.EventBus
import org.json.JSONException
import org.json.JSONObject
import retrofit2.HttpException

class FollowHomeViewModel(application: Application) : AndroidViewModel(application), OnFollowHomeEventListener {

    private var pageNo = 1

    private val compositeDisposable = CompositeDisposable()

    private val repository = FollowRepository.newInstance()

    val commonContentCollectionUseCase = CommonContentCollectionUseCase.newInstance()

    private var dynamicType = ""

    var videoList = listOf<ForumVideoEntity>()

    private val _dataList = MutableLiveData<List<FollowItem>>()
    val dataList: LiveData<List<FollowItem>> = _dataList

    private val _loadStatus = MutableLiveData<Pair<LoadStatus, Boolean>>()
    val loadStatus: LiveData<Pair<LoadStatus, Boolean>> = _loadStatus

    private val _hasFollowedUser = MutableLiveData<Boolean>()
    val hasFollowedUser: LiveData<Boolean> = _hasFollowedUser

    fun loadFirst(isLogin: Boolean, type: String = "", isPullToRefresh: Boolean) {
        pageNo = 1
        dynamicType = type
        _loadStatus.value = LoadStatus.INIT_LOADING to isPullToRefresh
        repository.loadHomeData(isLogin, dynamicType, pageNo)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<List<FollowItem>>() {
                override fun onSuccess(data: List<FollowItem>) {
                    findVideoList(data)
                    _hasFollowedUser.value = (data.firstOrNull() as? FollowUserItem)?.data?.isNotEmpty() == true
                    _loadStatus.value = LoadStatus.INIT_LOADED to isPullToRefresh
                    pageNo++
                    _dataList.value = data
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    _loadStatus.value = LoadStatus.INIT_LOADED to isPullToRefresh
                }

            }).let(compositeDisposable::add)
    }

    fun loadMore() {
        _loadStatus.value = LoadStatus.LIST_LOADING to false
        repository.loadMore(dynamicType, pageNo)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<List<FollowItem>>() {
                override fun onSuccess(data: List<FollowItem>) {
                    if (data.isNotEmpty()) {
                        _loadStatus.value = LoadStatus.LIST_LOADED to false
                        addData(data)
                    } else {
                        _loadStatus.value = LoadStatus.LIST_OVER to false
                    }

                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    _loadStatus.value = LoadStatus.LIST_FAILED to false
                }

            }).let(compositeDisposable::add)
    }

    private fun findVideoList(data: List<FollowItem>) {
        videoList = data.map {
            if (it is FollowPostCardItem) {
                it.data.transformForumVideoEntity()
            } else {
                ForumVideoEntity()
            }
        }
    }

    fun loadFollowedUsers() {
        repository.loadFollowedUsers()
            .compose(singleToMain())
            .subscribe(object : BiResponse<List<FollowUserEntity>>() {
                override fun onSuccess(data: List<FollowUserEntity>) {
                    val oldData = _dataList.value ?: return
                    val headItem = oldData.getOrNull(0)
                    if (headItem is FollowUserItem) {
                        val newHeadItem = headItem.copy(data = data)
                        val newData = oldData.toMutableList()
                        newData[0] = newHeadItem
                        _dataList.value = newData
                    }
                }
            }).let(compositeDisposable::add)
    }

    private fun addData(newData: List<FollowItem>) {
        val oldData = dataList.value
        val data = if (oldData == null) {
            newData
        } else {
            oldData + newData
        }
        findVideoList(data)
        _dataList.value = data
        pageNo++
    }


    private val _followedDetailDestination = MutableLiveData<Event<Pair<Int, List<FollowUserEntity>>>>()
    val followedDetailDestination: LiveData<Event<Pair<Int, List<FollowUserEntity>>>> = _followedDetailDestination

    override fun viewItemFollowed(position: Int, data: List<FollowUserEntity>) {
        val item = data.getOrNull(position) ?: return
        SensorsBridge.trackFollowPageUserAndForumDataClick(
            item.user.id ?: "",
            item.bbs.id,
            item.bbs.name,
            item.bbs.type
        )
        _followedDetailDestination.value = Event(position to data)
    }


    private val _myFollowedListDestination = MutableLiveData<Event<Unit>>()
    val myFollowedListDestination: LiveData<Event<Unit>> = _myFollowedListDestination
    override fun viewAllFollowed() {
        _myFollowedListDestination.value = Event(Unit)
    }

    private val _loginDestination = MutableLiveData<Event<Unit>>()
    val loginDestination: LiveData<Event<Unit>> = _loginDestination
    override fun login() {
        _loginDestination.value = Event(Unit)
    }

    override fun followUser(userId: String, isFollow: Boolean) {
        val isLogin = CheckLoginUtils.isLogin()
        if (isLogin) {
            repository.followUser(userId, isFollow)
                .compose(observableToMain())
                .subscribe(object : Response<ResponseBody>() {
                    override fun onResponse(response: ResponseBody?) {
                        if (isFollow) {
                            Utils.toast(getApplication(), com.gh.gamecenter.feature.R.string.concern_success)
                        } else {
                            Utils.toast(getApplication(), R.string.concern_cancel)
                        }
                        EventBus.getDefault().post(EBUserFollow(userId, isFollow))
                    }

                    override fun onFailure(e: HttpException?) {
                        super.onFailure(e)
                        Utils.toast(getApplication(), com.gh.gamecenter.feature.R.string.loading_failed_hint)
                    }
                })
        } else {
            login()
        }
    }

    private val _linkDestination = MutableLiveData<Event<Pair<LinkEntity, ExposureEvent?>>>()
    val linkDestination: LiveData<Event<Pair<LinkEntity, ExposureEvent?>>> = _linkDestination

    override fun navigateToLinkPageInCommonContent(
        position: Int,
        link: LinkEntity,
        data: CustomPageData.CommonContentCollection,
        text: String,
        exposureEvent: ExposureEvent?
    ) {
        SensorsBridge.trackLinkContentCollectionClick(
            LOCATION_FOLLOW_PAGE,
            "",
            "",
            data.name,
            data.id,
            position,
            link.type ?: "",
            link.link ?: "",
            link.text ?: "",
            text,
            commonContentLayoutToComponentName[data.layout] ?: "",
        )
        _linkDestination.value = Event(link to exposureEvent)
    }

    private val _gameDetailDestination = MutableLiveData<Event<GameEntity>>()
    val gameDetailDestination: LiveData<Event<GameEntity>> = _gameDetailDestination
    override fun navigateToGameDetailPage(position: Int, game: GameEntity, text: String) {
        _gameDetailDestination.value = Event(game)
    }

    private val _commonCollectionDestination = MutableLiveData<Event<CustomPageData.CommonContentCollection>>()
    val commonCollectionDestination: LiveData<Event<CustomPageData.CommonContentCollection>> =
        _commonCollectionDestination

    override fun navigateToCommonCollectionDetailPage(data: CustomPageData.CommonContentCollection) {
        _commonCollectionDestination.value = Event(data)
    }

    private val _userHomeDestination = MutableLiveData<Event<String>>()
    val userHomeDestination: LiveData<Event<String>> = _userHomeDestination
    override fun navigateToUserHomePage(userId: String) {
        _userHomeDestination.value = Event(userId)
    }

    private val _postCardClickAction = MutableLiveData<Event<Pair<Int, ArticleEntity>>>()
    val postCardClickAction: LiveData<Event<Pair<Int, ArticleEntity>>> = _postCardClickAction
    override fun onPostCardClick(position: Int, article: ArticleEntity) {
        _postCardClickAction.value = Event(position to article)
    }

    private val _libaoDetailDestination = MutableLiveData<Event<LibaoEntity>>()
    val libaoDetailDestination: LiveData<Event<LibaoEntity>> = _libaoDetailDestination
    override fun navigateToLibaoDetailPage(libaoEntity: LibaoEntity) {
        _libaoDetailDestination.value = Event(libaoEntity)
    }

    private val _newDetailDestination = MutableLiveData<Event<String>>()
    val newDetailDestination: LiveData<Event<String>> = _newDetailDestination

    private val _updateOkhttpCacheAction = MutableLiveData<Event<String>>()
    val updateOkhttpCacheAction: LiveData<Event<String>> = _updateOkhttpCacheAction

    override fun navigateToNewsDetailPage(articleId: String) {
        _newDetailDestination.value = Event(articleId)
        // 统计文章阅读量
        repository.postArticleVisit(articleId)
            .compose(observableToMain())
            .subscribe(object : JSONObjectResponse() {

                override fun onResponse(response: JSONObject) {
                    super.onResponse(response)
                    if (response.length() != 0) {
                        try {
                            if ("success" == response.getString("status")) {
                                _updateOkhttpCacheAction.value = Event(articleId)
                            }
                        } catch (e: JSONException) {
                            e.printStackTrace();
                        }
                    }
                }
            });
    }

    private val _articleCommentDetailDestination = MutableLiveData<Event<String>>()
    val articleCommentDetailDestination: LiveData<Event<String>> = _articleCommentDetailDestination
    override fun navigateToArticleCommentDetailPage(articleId: String) {
        _articleCommentDetailDestination.value = Event(articleId)
    }

    private val _shareArticleDestination = MutableLiveData<Event<ConcernEntity>>()
    val shareArticleDestination: LiveData<Event<ConcernEntity>> = _shareArticleDestination
    override fun onShareArticle(concernEntity: ConcernEntity) {
        _shareArticleDestination.value = Event(concernEntity)
    }

    private val _copyExchangeCodeAction = MutableLiveData<Event<String>>()
    val copyExchangeCodeAction: LiveData<Event<String>> = _copyExchangeCodeAction
    override fun copyExchangeCode(code: String) {
        _copyExchangeCodeAction.value = Event(code)
    }

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


}