package com.gh.gamecenter.forum.home

import android.view.View
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.ethanhua.skeleton.Skeleton
import com.gh.common.util.CheckLoginUtils
import com.gh.common.util.NewLogUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.baselist.LazyListFragment
import com.gh.gamecenter.common.baselist.LoadStatus
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.iinterface.IScrollable
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.databinding.FragmentForumListBinding
import com.gh.gamecenter.entity.ForumEntity
import com.gh.gamecenter.eventbus.EBDeleteDetail
import com.gh.gamecenter.eventbus.EBForumRecordChange
import com.gh.gamecenter.eventbus.EBTypeChange
import com.gh.gamecenter.eventbus.EBUserFollow
import com.gh.gamecenter.forum.home.ForumScrollCalculatorHelper.Companion.getPlaySchedule
import com.gh.gamecenter.forum.home.ForumScrollCalculatorHelper.Companion.savePlaySchedule
import com.gh.gamecenter.qa.entity.ArticleEntity
import com.gh.gamecenter.login.user.UserViewModel
import com.gh.gamecenter.video.detail.CustomManager
import com.google.android.material.appbar.AppBarLayout
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import kotlin.math.abs

class ForumArticleListFragment : LazyListFragment<ArticleEntity, ForumArticleListViewModel>(), IScrollable {

    private var mViewModel: ForumArticleListViewModel? = null
    private var mUserViewModel: UserViewModel? = null
    private var mBinding: FragmentForumListBinding? = null
    private var mAdapter: ForumArticleListAdapter? = null
    private var mScrollCalculatorHelper: ForumScrollCalculatorHelper? = null
    private var mRecordForums = listOf<ForumEntity>()
    private var mPath = ""
    private var mIsFirst = true
    private var mHaveLoadLoginData = false
    private var mIsFirstAndIsLogin = false
    private var mRefreshEnable = true
    private var mRecordRvScrolling = false

    override fun getRealLayoutId() = R.layout.fragment_forum_list

    override fun onFragmentFirstVisible() {
        mPath = arguments?.getString(EntranceConsts.KEY_PATH) ?: ""
        val factory = UserViewModel.Factory(requireActivity().application)
        mUserViewModel = ViewModelProviders.of(this, factory)[UserViewModel::class.java]
        mUserViewModel?.loginObsUserinfo?.observe(this, Observer {
            if ((it?.data != null && !mHaveLoadLoginData && !mIsFirstAndIsLogin)
                || (it?.data == null && mHaveLoadLoginData)
            ) {
                onRefresh()
            }
        })

        super.onFragmentFirstVisible()
        mScrollCalculatorHelper = ForumScrollCalculatorHelper(R.id.horizontalVideoView, R.id.verticalVideoView, 0)
    }

    override fun initRealView() {
        super.initRealView()

        initSkeleton()

        mViewModel?.recordForumsLiveData?.observeNonNull(viewLifecycleOwner) {
            mRecordForums = it.first
            if (!it.second) initRecordForums(it.first)
        }

        mBinding?.run {
            appbar.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { _, verticalOffset ->
                mRefreshEnable = abs(verticalOffset) <= 2 && !mRecordRvScrolling
                mListRefresh?.isEnabled = mRefreshEnable
            })

            mListRv.addOnScrollListener(object : RecyclerView.OnScrollListener() {
                override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                    super.onScrollStateChanged(recyclerView, newState)
                    mScrollCalculatorHelper?.onScrollStateChanged(mListRv, newState)
                    if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                        var position = mLayoutManager.findLastCompletelyVisibleItemPosition()
                        if (position == -1) position = mLayoutManager.findLastVisibleItemPosition() - 1
                        NewLogUtils.logRecommendFeedSlide(position + 1)
                    }
                }

                override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                    if (dy > Constants.FOLLOW_HINT_TRIGGER_HEIGHT) {
                        EventBus.getDefault().post(EBTypeChange(CommunityHomeFragment.EB_HIDE_QUESTION_BUTTON, 0))
                    } else if (dy < -Constants.FOLLOW_HINT_TRIGGER_HEIGHT) {
                        EventBus.getDefault().post(EBTypeChange(CommunityHomeFragment.EB_SHOW_QUESTION_BUTTON, 0))
                    }
                    if (dy != 0) scroll()
                    if (parentFragment is CommunityHomeFragment) {
                        (parentFragment as CommunityHomeFragment).translateTopBg(recyclerView.computeVerticalScrollOffset() - 8F.dip2px())
                    }
                }
            })
        }

    }

    private fun initSkeleton() {
        mSkeletonScreen = Skeleton.bind(mBinding?.listSkeleton)
            .shimmer(true)
            .angle(Constants.SHIMMER_ANGLE)
            .color(R.color.skeleton_shimmer_color)
            .duration(Constants.SHIMMER_DURATION)
            .maskWidth(Constants.MASK_WIDTH)
            .gradientCenterColorWidth(Constants.GRADIENT_CENTER_COLOR_WIDTH)
            .load(R.layout.fragment_forum_list_skeleton)
            .show()
    }

    override fun onRealLayoutInflated(inflatedView: View) {
        super.onRealLayoutInflated(inflatedView)
        mBinding = FragmentForumListBinding.bind(inflatedView)
    }

    override fun onFragmentResume() {
        resumeVideo()
        super.onFragmentResume()
        if (mIsFirst) {
            mIsFirstAndIsLogin = CheckLoginUtils.isLogin()
            mIsFirst = false
        } else {
            mIsFirstAndIsLogin = false
            mViewModel?.getForumUnreadStatus(false)
        }
        NewLogUtils.logRecommendFeedEvent("view_for_you_feed")
    }

    override fun onFragmentPause() {
        super.onFragmentPause()
        pauseVideo()
    }

    override fun onDestroy() {
        super.onDestroy()
        mScrollCalculatorHelper?.currentPlayer?.release()
    }

    override fun provideListViewModel(): ForumArticleListViewModel {
        mViewModel = viewModelProvider()
        return mViewModel!!
    }

    override fun getItemDecoration() = null

    override fun provideListAdapter() = mAdapter ?: ForumArticleListAdapter(
        requireContext(),
        mEntrance,
        mPath,
        mViewModel ?: provideListViewModel()
    ).apply { mAdapter = this }

    override fun onRefresh() {
        mScrollCalculatorHelper?.currentPlayer?.release()
        mScrollCalculatorHelper?.reset()
        super.onRefresh()
        mBinding?.recordForumsContainer?.visibility = View.GONE
        mViewModel?.getRecordForums()
    }

    override fun onLoadDone() {
        super.onLoadDone()
        initRecordForums(mRecordForums)
        mHaveLoadLoginData = CheckLoginUtils.isLogin()
        AppExecutor.uiExecutor.executeWithDelay(Runnable {
            tryCatchInRelease {
                scroll()
                mScrollCalculatorHelper?.onScrollStateChanged(mListRv, RecyclerView.SCROLL_STATE_IDLE)
            }
        }, 100)
    }

    private fun initRecordForums(list: List<ForumEntity>) {
        if (list.isEmpty()) return
        mBinding?.run {
            recordForumsContainer.visibility = View.VISIBLE
            recordForumsMore.setOnClickListener {
                NewLogUtils.logRecommendFeedEvent("click_recent_more")
                (parentFragment as? CommunityHomeFragment)?.run {
                    setCurrentItem(CommunityHomeFragment.TAB_FORUM_INDEX)
                }
            }
            if (recordForumsRv.adapter != null) {
                (recordForumsRv.adapter as? ForumRecordsAdapter)?.checkResetData(list)
            } else {
                recordForumsRv.layoutManager = LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false)
                recordForumsRv.adapter = ForumRecordsAdapter(requireContext(), "社区-推荐-最近浏览", list)
                recordForumsRv.addOnScrollListener(object : RecyclerView.OnScrollListener() {
                    override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                        super.onScrollStateChanged(recyclerView, newState)

                        mRecordRvScrolling = newState != RecyclerView.SCROLL_STATE_IDLE
                        if (newState != RecyclerView.SCROLL_STATE_IDLE) {
                            listRefresh.isEnabled = false
                        } else {
                            listRefresh.isEnabled = mRefreshEnable
                        }
                    }
                })
            }
        }
    }

    fun onRefresh(filter: String) {
        mViewModel?.sort = if (filter == "最新发布") "time.edit" else "time.comment"
        onRefresh()
    }

    override fun scrollToTop() {
        mBinding?.run {
            mListRv.scrollToPosition(0)
            appbar.setExpanded(true)
        }
    }

    // 插入一条数据到首位
    fun insertDataToFirstIndex(entity: ArticleEntity) {
        mAdapter?.run {
            if (entityList == null) return

            if (entityList.size == 0) {
                mListRv?.visibility = View.VISIBLE
                mReuseNoData?.visibility = View.GONE
                mReuseNoConn?.visibility = View.GONE
            }

            entityList.add(0, entity)
            notifyDataSetChanged()
            mViewModel?.videoList?.add(0, entity.transformForumVideoEntity())
            scrollToTop()
        }
    }

    private fun scroll() {
        val firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition()
        val lastVisibleItem = mLayoutManager.findLastVisibleItemPosition()
        mScrollCalculatorHelper?.onScroll(mViewModel?.videoList, firstVisibleItem, lastVisibleItem)
    }

    private fun resumeVideo() {
        mScrollCalculatorHelper?.run {
            if (currentPlayer != null
                && currentPosition >= 0
                && currentPosition < mViewModel?.videoList?.size ?: 0
            ) {
                val video = mViewModel?.videoList?.safelyGetInRelease(currentPosition)
                if (video != null) {
                    val position = getPlaySchedule(MD5Utils.getContentMD5(video.url))
                    //这里必须要延迟操作，否则会白屏
                    mBaseHandler.postDelayed({
                        tryCatchInRelease {
                            if (position != 0L) {
                                if (currentPlayer?.currentState == GSYVideoView.CURRENT_STATE_PAUSE) {
                                    currentPlayer?.startPlayLogic(true)
                                }
                            } else {
                                currentPlayer?.release()
                            }
                        }
                    }, 50)
                }
            }
        }
    }

    private fun pauseVideo() {
        mScrollCalculatorHelper?.run {
            if (currentPlayer != null
                && currentPosition >= 0
                && currentPosition < mViewModel?.videoList?.size ?: 0
            ) {
                currentPlayer?.onVideoPause()
                val position = currentPlayer?.getCurrentPosition() ?: 0L
                val video = mViewModel?.videoList?.safelyGetInRelease(currentPosition)
                if (video != null) {
                    savePlaySchedule(MD5Utils.getContentMD5(video.url), position)
                }
            }
        }
    }

    override fun addSyncPageObserver(): Boolean = true

    override fun provideSyncAdapter() = mAdapter

    override fun onBackPressed(): Boolean {
        mScrollCalculatorHelper?.currentPlayer?.run {
            return (isIfCurrentIsFullscreen
                    && CustomManager.backFromWindowFull(requireActivity(), getKey()))
        }
        return super.onBackPressed()
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEvent(detail: EBDeleteDetail) {
        mAdapter?.run {
            val currentEntity = entityList?.find { it.id == detail.id }
            val indexOf = entityList?.indexOf(currentEntity) ?: 0
            entityList?.remove(currentEntity)
            notifyItemRemoved(indexOf)
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onForumRecordChange(change: EBForumRecordChange) {
        mBinding?.run {
            if (recordForumsContainer.visibility == View.VISIBLE) {
                mViewModel?.run {
                    val firstEntity = recordForums.safelyGetInRelease(0)
                    if (firstEntity?.id == change.forumEntity.id) {
                        if (firstEntity.unread) {
                            firstEntity.unread = false
                        }
                        return
                    }

                    val findEntity = recordForums.find { it.id == change.forumEntity.id }
                    if (findEntity != null) {
                        recordForums.remove(findEntity)
                    }
                    recordForums.add(0, change.forumEntity)
                }
            } else {
                mViewModel?.recordForums = arrayListOf(change.forumEntity)
            }
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onUserFollow(change: EBUserFollow) {
        mAdapter?.run {
            var count = 0
            entityList.forEach {
                if (it.user.id == change.userId) {
                    count++
                    it.me.isFollower = change.isFollow
                }
            }
            if (count > 1) notifyDataSetChanged()
        }
    }

    override fun onDarkModeChanged() {
        super.onDarkModeChanged()
        if (parentFragment is CommunityHomeFragment) {
            (parentFragment as CommunityHomeFragment).translateTopBg(mListRv.computeVerticalScrollOffset() - 8F.dip2px())
        }
        mBinding?.run {
            initSkeleton()
            showSkeleton(mListViewModel.loadStatusLiveData.value == LoadStatus.INIT_LOADING)
            recordForumsRv.adapter?.let { it.notifyItemRangeChanged(0, it.itemCount) }
            mListRv?.adapter?.let { it.notifyItemRangeChanged(0, it.itemCount) }
        }
    }
}