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

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.View
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContract
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.children
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
import com.therouter.TheRouter
import com.gh.common.util.CheckLoginUtils
import com.gh.common.util.DirectUtils
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.LazyFragment
import com.gh.gamecenter.common.baselist.LoadStatus
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.iinterface.IScrollable
import com.gh.gamecenter.core.provider.IVisitManagerProvider
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.databinding.FragmentFollowHomeBinding
import com.gh.gamecenter.entity.FollowUserEntity
import com.gh.gamecenter.eventbus.EBUserFollow
import com.gh.gamecenter.feature.provider.IMessageDetailProvider
import com.gh.gamecenter.forum.home.CommunityHomeFragment
import com.gh.gamecenter.forum.home.CommunityHomeViewModel
import com.gh.gamecenter.forum.home.ForumScrollCalculatorHelper
import com.gh.gamecenter.forum.home.follow.*
import com.gh.gamecenter.forum.home.follow.adapter.FollowHomeAdapter
import com.gh.gamecenter.forum.home.follow.fragment.AllFollowedFragment.Companion.KEY_HAS_READ_ID
import com.gh.gamecenter.forum.home.follow.model.FollowRepository.Companion.FOLLOW_UPDATE_TYPE_GAME
import com.gh.gamecenter.forum.home.follow.model.FollowRepository.Companion.FOLLOW_UPDATE_TYPE_USER
import com.gh.gamecenter.forum.home.follow.viewholder.FollowHomeHeaderViewHolder
import com.gh.gamecenter.forum.home.follow.viewmodel.FollowHomeViewModel
import com.gh.gamecenter.game.commoncollection.detail.CustomCommonCollectionDetailActivity
import com.gh.gamecenter.libao.LibaoDetailActivity
import com.gh.gamecenter.livedata.EventObserver
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.login.user.UserViewModel
import com.gh.gamecenter.newsdetail.NewsShareDialog
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

class FollowHomeFragment : LazyFragment(), IScrollable {

    override fun addSyncPageObserver(): Boolean {
        return true
    }

    private val viewModel by viewModels<FollowHomeViewModel>()

    private val communityHomeViewModel by viewModels<CommunityHomeViewModel>(
        ownerProducer = { requireParentFragment() }
    )

    private lateinit var userViewModel: UserViewModel

    private var userId: String? = null

    private var dynamicType: String? = null

    private var binding: FragmentFollowHomeBinding? = null

    private var hasLoaded = false

    private lateinit var pageConfiguration: FollowPageConfiguration

    private var isFirstTimeEnter = true

    private val handler = Handler(Looper.getMainLooper())

    private val dividerPaint by lazy {
        Paint().apply {
            color = com.gh.gamecenter.common.R.color.ui_divider.toColor(requireContext())
            strokeWidth = 0.5F.dip2px().toFloat()
        }
    }

    private val rvBackgroundPaint by lazy {
        Paint().apply {
            color = com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext())
        }
    }

    private val layoutManager by lazy {
        LinearLayoutManager(context)
    }

    private val adapter: FollowHomeAdapter by lazy {
        FollowHomeAdapter(viewLifecycleOwner, viewModel, pageConfiguration)
    }

    // 3s 以后才开始计算
    private var enterStartTime = 0L

    private lateinit var allFollowLauncher: ActivityResultLauncher<Unit>

    private var mScrollCalculatorHelper: ForumScrollCalculatorHelper? = null

    private val headerViewHolder by lazy(LazyThreadSafetyMode.NONE) {
        binding?.let {
            FollowHomeHeaderViewHolder(it.layoutHeader, object : FollowHomeHeaderViewHolder.OnEventListener {
                override fun onItemClick(position: Int, data: List<FollowUserEntity>) {
                    viewModel.viewItemFollowed(position, data)
                }

                override fun onAllClick() {
                    viewModel.viewAllFollowed()
                }

                override fun onLoginClick() {
                    viewModel.login()
                }

            })
        }

    }

    override fun provideSyncAdapter(): RecyclerView.Adapter<*> {
        return adapter
    }

    override fun getRealLayoutId(): Int = R.layout.fragment_follow_home

    override fun onRealLayoutInflated(inflatedView: View) {
        binding = FragmentFollowHomeBinding.bind(inflatedView)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        pageConfiguration = FollowPageConfiguration("社区-关注", "")
        allFollowLauncher = requireActivity().activityResultRegistry.register(
            KEY_LAUNCH_ALL_FOLLOW,
            this,
            object : ActivityResultContract<Unit, List<String>?>() {
                override fun createIntent(context: Context, input: Unit): Intent {
                    return AllFollowedActivity.getIntent(context)
                }

                override fun parseResult(resultCode: Int, intent: Intent?): List<String>? {
                    if (resultCode == Activity.RESULT_OK) {
                        val hasReadIds = intent?.getStringArrayListExtra(KEY_HAS_READ_ID)
                        return hasReadIds ?: listOf()
                    }
                    return null
                }

            }
        ) { value ->
            value?.let {
                if (it.isEmpty()) {
                    viewModel.loadFollowedUsers()
                } else {
                    adapter.notifyFollowUserReadStatus(it)
                }
            }
        }

        viewModel.hasFollowedUser.observe(this, Observer {
            communityHomeViewModel.updateHasFollowUser(it)
        })
    }

    override fun initRealView() {
        super.initRealView()

        mScrollCalculatorHelper = ForumScrollCalculatorHelper(R.id.horizontalVideoView, R.id.verticalVideoView, 0)
        binding?.recyclerView?.itemAnimator = null

        userViewModel = viewModelProvider(UserViewModel.Factory(requireActivity().application))

        userViewModel.loginObsUserinfo.observe(viewLifecycleOwner) {
            /* 由于其它页面每次初始化 userViewModel时，loginObsUserInfo都会被赋值一次，为避免重复加载，这里需要过滤重复的用户信息 */
            if (hasLoaded && userId == it?.data?.userId) {
                // 已经加载过数据，并且userId不变，不需要重复加载
                return@observe
            }
            hasLoaded = true
            if (it?.data == null) {
                // 未登录，加载推荐关注列表
                userId = null
                viewModel.loadFirst(userId != null, isPullToRefresh = false)
            } else {
                // 已登录，加载已关注列表
                userId = it.data.userId
                if (userId != null) {
                    viewModel.loadFirst(userId != null, isPullToRefresh = false)
                }
            }

        }

        communityHomeViewModel.filterFollowedAction.observe(viewLifecycleOwner, EventObserver {
            val newDynamicType = when (it) {
                0 -> ""
                1 -> FOLLOW_UPDATE_TYPE_USER
                else -> FOLLOW_UPDATE_TYPE_GAME
            }
            if (dynamicType != newDynamicType) {
                dynamicType = newDynamicType
                viewModel.loadFirst(userId != null, dynamicType ?: "", false)
            }

        })

        with(viewModel) {

            loadStatus.observe(viewLifecycleOwner) { (loadStatus, isPullRefresh) ->
                if (isPullRefresh) {
                    if (loadStatus != LoadStatus.INIT_LOADING) {
                        binding?.srlRefresh?.isRefreshing = false
                    }
                } else {
                    binding?.layoutLoading?.root?.goneIf(loadStatus != LoadStatus.INIT_LOADING)
                }
                adapter.setLoadStatus(loadStatus)

                if (loadStatus == LoadStatus.INIT_LOADED) {
                    AppExecutor.uiExecutor.executeWithDelay(Runnable {
                        tryCatchInRelease {
                            scroll()
                            mScrollCalculatorHelper?.onScrollStateChanged(
                                binding?.recyclerView!!,
                                RecyclerView.SCROLL_STATE_IDLE
                            )
                        }
                    }, 100)
                }
            }

            dataList.observe(viewLifecycleOwner) {
                if (it.size == 1) {
                    // 由于第一个是头部，如果list长度为1，则说明后面没有数据
                    binding?.llEmptyContainer?.goneIf(false)
                    binding?.recyclerView?.goneIf(true)
                    val headerItem = it.firstOrNull() as? FollowUserItem
                    if (headerItem != null) {
                        headerViewHolder?.bind(headerItem.isLogin, headerItem.data)
                        setEmptyLayout(headerItem)
                    }
                } else {
                    binding?.llEmptyContainer?.goneIf(true)
                    binding?.recyclerView?.goneIf(false)
                    setDataList(it)
                }
            }

            followedDetailDestination.observe(viewLifecycleOwner, EventObserver { (position, data) ->
                FollowDynamicActivity.start(requireContext(), position, data)
                activity?.overridePendingTransition(0, 0) // 取消进入和退出动画
            })

            myFollowedListDestination.observe(viewLifecycleOwner, EventObserver {
                allFollowLauncher.launch(Unit)
            })

            loginDestination.observe(viewLifecycleOwner, EventObserver {
                CheckLoginUtils.checkLogin(context, "关注", null)
            })

            gameDetailDestination.observe(viewLifecycleOwner, EventObserver {
                GameDetailActivity.startGameDetailActivity(
                    requireContext(),
                    it.id,
                    "",
                    traceEvent = it.exposureEvent
                )
            })

            linkDestination.observe(viewLifecycleOwner, EventObserver { (link, exposureEvent) ->
                DirectUtils.directToLinkPage(requireContext(), link, "关注页面", "", exposureEvent)
            })

            commonCollectionDestination.observe(viewLifecycleOwner, EventObserver {
                val intent = CustomCommonCollectionDetailActivity.getIntent(
                    requireContext(),
                    it.id,
                    it.layout,
                    "自定义页面",
                )
                startActivity(intent)
            })

            userHomeDestination.observe(viewLifecycleOwner, EventObserver {
                DirectUtils.directToHomeActivity(requireContext(), it, 1, "", "")
            })

            libaoDetailDestination.observe(viewLifecycleOwner, EventObserver {
                val intent = LibaoDetailActivity.getIntent(requireContext(), it, false, "$mEntrance+关注列表")
                startActivity(intent)
            })

            newDetailDestination.observe(viewLifecycleOwner, EventObserver {
                TheRouter.build(RouteConsts.activity.newsDetailActivity)
                    .withString(EntranceConsts.KEY_NEWSID, it)
                    .withString(EntranceConsts.KEY_ENTRANCE, "")
                    .navigation(requireActivity())
            })

            articleCommentDetailDestination.observe(viewLifecycleOwner, EventObserver {
                val messageDetailProvider = TheRouter.get(IMessageDetailProvider::class.java)
                if (messageDetailProvider != null) {
                    val intent = messageDetailProvider.getIntentById(requireContext(), it, -1, false, "")
                    startActivity(intent)
                }
            })

            shareArticleDestination.observe(viewLifecycleOwner, EventObserver { concernEntity ->
                NewsShareDialog.show(
                    requireActivity() as AppCompatActivity,
                    concernEntity.shortId,
                    concernEntity.id,
                    concernEntity.gameIcon,
                    concernEntity.title
                )
            })

            copyExchangeCodeAction.observe(viewLifecycleOwner, EventObserver {
                it.copyTextAndToast()
            })

            updateOkhttpCacheAction.observe(viewLifecycleOwner, EventObserver {
                // 更新okhttp缓存数据
                val visitManagerProvider = TheRouter.get(IVisitManagerProvider::class.java)
                visitManagerProvider?.updateOkhttpCache(requireContext(), it)
            })
        }

        binding?.srlRefresh?.setOnRefreshListener {
            mScrollCalculatorHelper?.currentPlayer?.release()
            mScrollCalculatorHelper?.reset()
            val isLogin = userId != null
            viewModel.loadFirst(isLogin, dynamicType ?: "", true)
        }

        binding?.recyclerView?.addOnScrollListener(object : OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)
                binding?.recyclerView?.let {
                    mScrollCalculatorHelper?.onScrollStateChanged(it, newState)
                }
            }

            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
                if (dy != 0) scroll()
            }
        })

    }

    private fun setEmptyLayout(headerItem: FollowUserItem) {
        binding?.layoutEmpty?.run {
            root.goneIf(false)
            if (headerItem.isLogin) {
                reuseNoneDataDescTv.goneIf(true)
            } else {
                reuseNoneDataDescTv.goneIf(false)
                reuseNoneDataDescTv.setText(R.string.follow_home_no_login_tips)
            }
        }

    }

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

    override fun onFragmentResume() {
        resumeVideo()
        super.onFragmentResume()
        handler.postDelayed({
            enterStartTime = System.currentTimeMillis()
            SensorsBridge.trackFollowTabBrowse(isFirstTimeEnter)
        }, TRACK_ENTER_TIME)
    }

    override fun onFragmentPause() {
        super.onFragmentPause()
        pauseVideo()
        isFirstTimeEnter = false
        handler.removeCallbacksAndMessages(null)
        if (enterStartTime != 0L) {
            val endTime = System.currentTimeMillis()
            val stayLength = "${(endTime - enterStartTime) / MS_UNIT}"
            SensorsBridge.trackFollowTabBrowseDuration(stayLength)
        }
        enterStartTime = 0L
    }

    private fun resumeVideo() {
        mScrollCalculatorHelper?.run {
            if (currentPlayer != null
                && currentPosition >= 0
                && currentPosition < viewModel.videoList.size
            ) {
                val video = viewModel.videoList.safelyGetInRelease(currentPosition)
                if (video != null) {
                    val position = ForumScrollCalculatorHelper.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 < viewModel.videoList.size
            ) {
                currentPlayer?.onVideoPause()
                val position = currentPlayer?.getCurrentPosition() ?: 0L
                val video = viewModel.videoList.safelyGetInRelease(currentPosition)
                if (video != null) {
                    ForumScrollCalculatorHelper.savePlaySchedule(MD5Utils.getContentMD5(video.url), position)
                }
            }
        }
    }

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

    private fun setDataList(dataList: List<FollowItem>) {
        binding?.run {
            if (recyclerView.adapter == null) {
                recyclerView.layoutManager = layoutManager
                recyclerView.addItemDecoration(FollowItemDecoration(dividerPaint, rvBackgroundPaint))
                recyclerView.adapter = adapter
            }
            adapter.submitList(dataList)
        }

    }

    override fun scrollToTop() {
        binding?.recyclerView?.scrollToPosition(0)
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onUserFollow(change: EBUserFollow) {
        adapter.notifyFollowUserChanged(change)
    }

    override fun onDarkModeChanged() {
        super.onDarkModeChanged()
        val rvFollows = binding?.recyclerView
        if (rvFollows != null) {
            if (parentFragment is CommunityHomeFragment) {
                (parentFragment as CommunityHomeFragment).translateTopBg(rvFollows.computeVerticalScrollOffset() - 8F.dip2px())
            }
            rvFollows.tryToClearRecycler()
            rvFollows.recycledViewPool.clear()
            adapter.notifyItemRangeChanged(0, adapter.itemCount)
        }
        dividerPaint.color = com.gh.gamecenter.common.R.color.ui_divider.toColor(requireContext())
        rvBackgroundPaint.color = com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext())
    }

    private class FollowItemDecoration(
        private val dividerPaint: Paint,
        private val backgroundPaint: Paint
    ) : RecyclerView.ItemDecoration() {
        override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
            super.onDrawOver(c, parent, state)
            parent.children.forEach { child ->
                val position = parent.getChildAdapterPosition(child)
                // 1.第一个itemView为头部关注人列表，不需要分割线
                // 2.默认推荐数据不需要分割线
                val isLoggedIn = UserManager.getInstance().isLoggedIn
                if (isLoggedIn && position > 0) {
                    val bottom = child.bottom
                    c.drawLine(
                        16F.dip2px().toFloat(),
                        bottom.toFloat(),
                        (child.width - 16F.dip2px()).toFloat(),
                        bottom.toFloat(),
                        dividerPaint
                    )
                }

            }
        }

        /**
         * 由于 关注用户/论坛 列表需要和顶部 tab连在一起组成渐变色，所以RecyclerView不能直接设置背景颜色
         * 在这里绘制除了 关注用户/论坛 列表其它位置的背景颜色
         * + 12 是为了预留出圆角的高度
         */
        override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
            super.onDraw(c, parent, state)
            val firstChild = parent.children.firstOrNull()
            if (firstChild != null) {
                c.drawRect(Rect(0, firstChild.bottom + 12F.dip2px(), parent.width, parent.bottom), backgroundPaint)
            }
        }

    }

    companion object {
        private const val KEY_LAUNCH_ALL_FOLLOW = "key_launch_all_follow"

        const val LOCATION_FOLLOW_PAGE = "关注页面"
        private const val TRACK_ENTER_TIME = 3000L
        private const val MS_UNIT = 1000.0
    }
}