package com.gh.gamecenter.wrapper

import android.graphics.Color
import android.graphics.Typeface
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.MarginLayoutParams
import android.widget.ImageView
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.core.graphics.ColorUtils
import androidx.core.view.doOnLayout
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import com.gh.common.constant.Config
import com.gh.common.databind.BindingAdapters
import com.gh.common.exposure.ExposureManager
import com.gh.common.iinterface.ISearchToolbarTab
import com.gh.common.iinterface.ISmartRefresh
import com.gh.common.iinterface.ISmartRefreshContent
import com.gh.common.iinterface.ISuperiorChain
import com.gh.common.prioritychain.AccelerateNotificationHandler
import com.gh.common.prioritychain.MultiTabGuideHandler
import com.gh.common.prioritychain.PriorityChain
import com.gh.common.prioritychain.PullDownPushHandler
import com.gh.common.util.*
import com.gh.common.util.LogUtils
import com.gh.common.util.NewLogUtils
import com.gh.download.DownloadManager
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
import com.gh.gamecenter.amway.AmwayFragment
import com.gh.gamecenter.common.base.adapter.FragmentAdapter
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.eventbus.EBReuse
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.json.json
import com.gh.gamecenter.common.observer.MuteCallback
import com.gh.gamecenter.common.observer.VolumeObserver
import com.gh.gamecenter.common.tracker.IBusiness
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.TabIndicatorView
import com.gh.gamecenter.core.iinterface.IScrollable
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.TimeElapsedHelper
import com.gh.gamecenter.databinding.FragmentSearchToolbarTabWrapperBinding
import com.gh.gamecenter.databinding.LayoutAutoVideoViewBinding
import com.gh.gamecenter.entity.BottomTab
import com.gh.gamecenter.entity.GameUpdateEntity
import com.gh.gamecenter.entity.MultiTabNav
import com.gh.gamecenter.entity.PullDownPush
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.exposure.time.TimeUtil
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.feature.utils.SentryHelper
import com.gh.gamecenter.gamecollection.square.GameCollectionSquareFragment
import com.gh.gamecenter.home.custom.CustomPageFragment
import com.gh.gamecenter.home.video.AutomaticVideoView
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
import com.gh.gamecenter.message.MessageUnreadViewModel
import com.gh.gamecenter.packagehelper.PackageViewModel
import com.gh.gamecenter.teenagermode.TeenagerModeActivity
import com.gh.gamecenter.wrapper.SearchToolbarTabWrapperFragment.Style
import com.gh.vspace.VHelper
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.tabs.TabLayout
import com.halo.assistant.HaloApp
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import com.scwang.smartrefresh.layout.api.RefreshHeader
import com.scwang.smartrefresh.layout.api.RefreshLayout
import com.scwang.smartrefresh.layout.constant.RefreshState
import com.scwang.smartrefresh.layout.listener.SimpleMultiPurposeListener
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import kotlin.math.abs
import kotlin.math.roundToInt

/**
 * 一级页面，带搜索栏的多tab导航页，支持下拉推送，
 * 支持三种样式：搜索栏+无Tab、单行搜索栏+Tab、双行搜索栏+Tab
 * @see Style
 */
class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbarTab, ISmartRefresh, ISuperiorChain, IBusiness {

    private lateinit var binding: FragmentSearchToolbarTabWrapperBinding

    private val viewModel: SearchToolbarTabWrapperViewModel by lazy {
        viewModelProviderFromParent(
            SearchToolbarTabWrapperViewModel.Factory(multiTabNavId, noTabLinkEntity?.link ?: ""),
            multiTabNavId + (noTabLinkEntity?.link ?: "")
        )
    }

    private var downloadHintTv: TextView? = null
    private var searchHintTv: TextView? = null
    private var searchContainerView: View? = null
    private var downloadView: View? = null
    private var messageUnread: TextView? = null
    private var searchRightView: ImageView? = null
    private var teenagerModelView: View? = null

    private var currentAppBarColor: Int = 0
    private var currentTabSelectedColor: Int = 0
    private var currentTabDefaultColor: Int = 0
    private var currentIndicatorDrawable: Int = 0

    private var mainWrapperViewModel: MainWrapperViewModel? = null
    private val unreadViewModel: MessageUnreadViewModel by lazy {
        viewModelProvider(
            MessageUnreadViewModel.Factory(
                HaloApp.getInstance().application
            )
        )
    }
    private val packageViewModel: PackageViewModel by lazy { viewModelProvider(PackageViewModel.Factory()) }
    private lateinit var elapsedHelper: TimeElapsedHelper

    private var style = Style.TWO_LINES_TAB

    private val statusBarHeight by lazy { DisplayUtils.getStatusBarHeight(requireContext().resources) }
    private var isDisplayingLightContent = false
    private var offsetCritical = 0.7F
    private var pullDownPushAction = "" // 触发行为（主动展开/自动展开）
    private var showTwoLevel = false
    private var isDragging = false
    private var pullDownPushClick = false
    private var finishingTwoLevel = false
    private var headerOffset = 0
    private var clipChildren = true
    private var twoLevelOpenOffset = 0
    private var twoLevelOpenCount = 0
    private var showTwoLevelStartOffset = 0
    private var pullDownPush: PullDownPush? = null
    private var pullDownPushExposureEvent: ExposureEvent? = null
    private var gameViewHolder: GameViewHolder? = null

    private var noTabLinkEntity: LinkEntity? = null
    private var lightStatusBar: Boolean? = null
    private var lightSearchToolbarStyle: Boolean? = null
    private var lightRefreshHeaderStyle: Boolean? = null

    private var inferiorChain: PriorityChain? = null
    private val priorityChain by lazy { PriorityChain { inferiorChain?.start() } }
    private var superiorChain: ISuperiorChain? = null
    private var autoFinishTwoLevelHandler: Handler? = null
    private var autoFinishTwoLevelCallback: (() -> Unit)? = null
    private val multiTabGuideHandler by lazy { MultiTabGuideHandler(24) }

    private val singleLineTabToolbarHeight = 56F.dip2px()
    private val twoLinesTabToolbarHeight = 48F.dip2px()

    private var autoVideoView: AutomaticVideoView? = null
    private val volumeObserver by lazy {
        VolumeObserver(object : MuteCallback {
            override fun onMute(isMute: Boolean) {
                if (::binding.isInitialized) {
                    binding.muteIv.setImageResource(if (isMute) R.drawable.ic_basic_offsound else R.drawable.ic_basic_onsound)
                }
                if (isMute) {
                    autoVideoView?.mute()
                } else {
                    autoVideoView?.unMute()
                }
            }
        })
    }

    private var searchStyle: BottomTab.SearchStyle? = null
        set(value) {
            field = value
            setSearchHint()
        }

    private val dataWatcher = object : DataWatcher() {
        override fun onDataChanged(downloadEntity: DownloadEntity) {
            if (downloadEntity.gameId == pullDownPush?.game?.id) {
                updatePullDownPushDownloadBtn()
            }
        }

        override fun onDataInit(downloadEntity: DownloadEntity) {
            onDataChanged(downloadEntity)
        }
    }

    override fun getLayoutId(): Int = 0
    override fun provideViewModel(): TabWrapperViewModel = viewModel

    override fun provideTabLayout(): TabLayout? {
        return if (style == Style.SINGLE_LINE_TAB) {
            binding.tabSearchToolbar.tabLayout
        } else {
            super.provideTabLayout()
        }
    }

    override fun provideIndicatorView(): TabIndicatorView? {
        return if (style == Style.SINGLE_LINE_TAB) {
            binding.tabSearchToolbar.indicatorView
        } else {
            super.provideIndicatorView()
        }
    }

    private fun getToolbarHeight() = if (style == Style.SINGLE_LINE_TAB) singleLineTabToolbarHeight else twoLinesTabToolbarHeight

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        noTabLinkEntity = arguments?.getParcelable(LinkEntity::class.java.simpleName)
        searchStyle = arguments?.getParcelable(BottomTab.SearchStyle::class.java.simpleName) ?: BottomTab.SearchStyle()
        if (searchStyle?.styleType == BottomTab.SearchStyle.STYLE_APPOSITION) {
            style = Style.SINGLE_LINE_TAB
        } else if (multiTabNavId.isEmpty() && noTabLinkEntity != null) {
            style = Style.NO_TAB
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        binding = try {
            FragmentSearchToolbarTabWrapperBinding.inflate(layoutInflater)
        } catch (e: Exception) {
            SentryHelper.onEvent("VIEW_BINDING_BIND_ERROR",
                "digest", e.localizedMessage,
                "gid", HaloApp.getInstance().gid
            )
            // 玄学，重试一次，该闪退闪退
            FragmentSearchToolbarTabWrapperBinding.inflate(layoutInflater)
        }
        mCachedView = binding.root
        return mCachedView
    }

    private fun initSearchToolbar() {
        binding.contentBgView.isVisible = style != Style.TWO_LINES_TAB
        binding.tabContainer.isVisible = style == Style.TWO_LINES_TAB
        val showDownload = Config.isShow()
        if (style == Style.SINGLE_LINE_TAB) {
            binding.tabSearchToolbar.root.visibility = View.VISIBLE
            downloadHintTv = binding.tabSearchToolbar.menuDownloadCountHint
            searchHintTv = binding.tabSearchToolbar.searchTv
            searchContainerView = binding.tabSearchToolbar.searchContainer
            downloadView = binding.tabSearchToolbar.downloadContainer

            binding.collapsingToolbar.updateLayoutParams<AppBarLayout.LayoutParams> {
                scrollFlags = AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL
            }
            binding.tabSearchToolbar.searchContainer.setOnClickListener(this)
            binding.tabSearchToolbar.downloadContainer.setOnClickListener(this)
        } else {
            binding.searchToolbar.root.visibility = View.VISIBLE
            downloadHintTv = binding.searchToolbar.actionTip
            searchHintTv = binding.searchToolbar.actionbarSearchInput
            searchContainerView = binding.searchToolbar.actionbarSearchRl
            downloadView = binding.searchToolbar.actionbarRlDownload
            messageUnread = binding.searchToolbar.messageUnreadHint
            searchRightView = binding.searchToolbar.actionbarSearchRight
            teenagerModelView = binding.searchToolbar.actionbarTeenagerModel

            teenagerModelView?.isVisible = !showDownload
            searchContainerView?.isVisible = showDownload
            searchRightView?.isVisible = !showDownload

            downloadView?.setOnClickListener(this)
            binding.searchToolbar.actionbarNotification.setOnClickListener(this)
            binding.searchToolbar.actionbarSearchRl.setOnClickListener(this)
            teenagerModelView?.setOnClickListener(this)
            searchHintTv?.setOnClickListener(this)
            searchRightView?.setOnClickListener(this)
        }
        downloadView?.isVisible = showDownload
        downloadHintTv?.typeface = Typeface.createFromAsset(requireContext().assets, Constants.DIN_FONT_PATH)
        messageUnread?.typeface = Typeface.createFromAsset(requireContext().assets, Constants.DIN_FONT_PATH)
        packageViewModel.filterSameUpdateLiveData.observe(this) { updateList: List<GameUpdateEntity> ->
            setDownloadHint(updateList)
        }
        unreadViewModel.messageCenterUnreadCountLiveData.observe(this) { unreadCount: Int ->
            setMessageUnread(unreadCount)
        }

        setSearchHint()
    }

    private fun setDownloadHint(updateList: List<GameUpdateEntity>) {
        downloadHintTv?.also {
            val count = DownloadManager.getInstance().getDownloadOrUpdateCount(updateList)
            it.goneIf(count == null) {
                it.text = count!!
                setHintLayoutParams(it, count.isEmpty())
            }
        }
    }

    private fun setMessageUnread(unreadCount: Int) {
        messageUnread?.isVisible = unreadCount != 0
        if (unreadCount == -1) {
            messageUnread?.text = ""
            messageUnread?.also { setHintLayoutParams(it, true) }
        } else {
            messageUnread?.also { BindingAdapters.setMessageUnread(it, unreadCount) }
            messageUnread?.also { setHintLayoutParams(it, false) }
        }
    }

    private fun setHintLayoutParams(textView: TextView, isRedDot: Boolean) {
        val params = textView.layoutParams
        if (isRedDot) {
            params.width = 6F.dip2px()
            params.height = 6F.dip2px()
            (params as MarginLayoutParams).rightMargin = (-4F).dip2px()
            params.topMargin = 0
            textView.setPadding(0, 0, 0, 0)
            textView.minWidth = 0
        } else {
            params.width = RelativeLayout.LayoutParams.WRAP_CONTENT
            params.height = 14F.dip2px()
            (params as MarginLayoutParams).rightMargin = (-8F).dip2px()
            params.topMargin = (-4F).dip2px()
            textView.setPadding(4F.dip2px(), 0, 4F.dip2px(), 0)
            textView.minWidth = 14F.dip2px()
        }
        textView.layoutParams = params
    }

    private fun setSearchHint() {
        if (isSupportVisible) {
            when (searchStyle?.searchType) {
                BottomTab.SearchStyle.TYPE_HALO_GAME -> {
                    searchHintTv?.let { DefaultSearchHintHelper.setSearchHint(it) }
                }
                BottomTab.SearchStyle.TYPE_MINI_GAME -> {
                    searchHintTv?.hint = if (searchStyle?.styleType == BottomTab.SearchStyle.STYLE_APPOSITION) "搜索" else "请输入小游戏关键词"
                }
                BottomTab.SearchStyle.TYPE_BBS -> {
                    searchHintTv?.hint = if (searchStyle?.styleType == BottomTab.SearchStyle.STYLE_APPOSITION) "搜索" else "搜索论坛内容、用户"
                }
            }
        }
    }

    override fun onClick(v: View) {
        when (v.id) {
            R.id.downloadContainer,
            R.id.actionbar_rl_download -> {
                DataCollectionUtils.uploadClick(activity, "下载图标", "主页")
                DirectUtils.directToDownloadManager(
                    requireContext(),
                    "底部tab",
                    bottomTabName,
                    multiTabName = multiTabNavName,
                    multiTabId = multiTabNavId
                )
            }

            R.id.searchIv,
            R.id.searchContainer,
            R.id.actionbar_search_input,
            R.id.actionbar_search_rl,
            R.id.actionbar_search_right -> {
                val searchBoxPattern = if (v.id == R.id.searchIv) "靠右" else "置顶且展开"
                DirectUtils.directToSearch(
                    requireContext(),
                    searchStyle?.searchType ?: "halo_game",
                    searchHintTv?.hint.toString(),
                    "搜索栏",
                    "多tab导航页",
                    bottomTabName,
                    multiTabId = multiTabNavId,
                    multiTabName = multiTabNavName,
                    searchBoxPattern = searchBoxPattern
                )
            }

            R.id.actionbar_notification -> {
                DataCollectionUtils.uploadClick(activity, "消息图标", "主页")
                NewLogUtils.logMessageInformBellClick(messageUnread?.visibility == View.VISIBLE, "首页")
                SensorsBridge.trackMessageCenterClick()
                // 优先进入有数字提醒的消息tab，其次是有红点提醒的游戏动态，最后是没有提醒的消息tab
                var defaultTabIndex = 1
                val messageUnreadCount = unreadViewModel.messageUnreadCountLiveData.value
                val isConcernUnread = unreadViewModel.zixunConcernLiveData.value
                if ((messageUnreadCount == null || messageUnreadCount.message < 1) && isConcernUnread == true) {
                    defaultTabIndex = 0
                }
                DirectUtils.directToMessageCenter(defaultTabIndex, "(工具栏)")
            }

            R.id.actionbar_teenager_model -> {
                startActivity(TeenagerModeActivity.getIntent(requireContext()))
            }
        }
    }

    override fun onFragmentFirstVisible() {
        super.onFragmentFirstVisible()
        mainWrapperViewModel = viewModelProviderFromParent(MainWrapperViewModel.Factory(HaloApp.getInstance()))
        elapsedHelper = TimeElapsedHelper()

        initSearchToolbar()
        buildPriorityChain()

        // 记录 appBarOffset 供其它子页面使用
        binding.appbar.addOnOffsetChangedListener { _, verticalOffset ->
            viewModel.appBarOffset = abs(verticalOffset)
        }

        binding.searchIv.setOnClickListener(this)
        binding.collapsingToolbar.scrimShownAction = {
            if (binding.searchIv.isVisible != it) {
                binding.searchIv.isVisible = it
                binding.indicatorView.post {
                    binding.indicatorView.generatePath(binding.viewPager.currentItem, 0F)
                }
            }
        }

        initSmartRefresh()

        if (style == Style.NO_TAB) {
            (binding.collapsingToolbar.layoutParams as? AppBarLayout.LayoutParams)?.let { lp ->
                lp.scrollFlags = AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL
            }
            initNoTabViewPager()
        }

        viewModel.tabSelectLiveData.observe(viewLifecycleOwner) {
            val selectTab = it.getContentWithHandled()
            if (selectTab is MainSelectedEvent.SelectedTab) {
                if (selectTab.topTabIndex != -1) {
                    viewPager?.doOnLayout {
                        viewPager?.setCurrentItem(selectTab.topTabIndex, false)
                    }
                }
            }
        }
    }

    override fun hideTab() {
        binding.tabContainer.visibility = View.GONE
        (binding.collapsingToolbar.layoutParams as? AppBarLayout.LayoutParams)?.let { lp ->
            lp.scrollFlags = AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL
        }
    }

    fun setSuperiorChain(superiorChain: ISuperiorChain?): SearchToolbarTabWrapperFragment {
        this.superiorChain = superiorChain
        return this
    }

    /**
     * 构建 PriorityChain，使用优先队列来决定当前需要显示哪一个弹窗
     * 插件化通知 popup (4)
     * 首页自动下拉二楼 (5)
     */
    private fun buildPriorityChain() {
        val accelerateNotificationHandler = AccelerateNotificationHandler(21)
        priorityChain.addHandler(accelerateNotificationHandler)

        mainWrapperViewModel?.accelerateNotificationPopup?.observe(this) {

            if (priorityChain.isHandlerQueueEmpty()) {
                if (it == null) return@observe

                val accelerateSet = HashSet(SPUtils.getStringSet(Constants.SP_ACCELERATE_NOTIFICATION_POP_UP_SET))
                if (it.isNotEmpty() && !accelerateSet.contains(it[0].messageId)) {
                    AccelerateNotificationHandler.showAccelerateNotificationPopupWindow(
                        requireActivity(),
                        mainWrapperViewModel,
                        mBaseHandler as BaseHandler,
                        it[0],
                        null
                    )
                    accelerateSet.add(it[0].messageId)
                    SPUtils.setStringSet(Constants.SP_ACCELERATE_NOTIFICATION_POP_UP_SET, accelerateSet)
                }
            } else {
                accelerateNotificationHandler.doPreProcess(
                    requireActivity(),
                    mBaseHandler,
                    it,
                    mainWrapperViewModel!!
                )
            }
        }

        if (superiorChain != null) {
            superiorChain?.registerInferiorChain(priorityChain)
        } else {
            priorityChain.start()
        }
    }

    private fun initNoTabViewPager() {
        fragmentList.clear()
        viewPager = provideViewPager()
        loadingStub?.visibility = View.GONE
        noTabLinkEntity?.let {
            if (it.type == ViewPagerFragmentHelper.TYPE_CUSTOM_PAGE) {
                val bundle = Bundle()
                bundle.putAll(arguments)
                bundle.putString(EntranceConsts.KEY_CUSTOM_PAGE_ID, it.link)
                bundle.putString(EntranceConsts.KEY_CUSTOM_PAGE_NAME, it.text)
                fragmentList.add(CustomPageFragment().setSuperiorChain(this).with(bundle))
            }
        }
        viewPager?.run {
            offscreenPageLimit = fragmentList.size
            defaultSelectedTab = 0
            setRestoredCurItem(this)
            adapter = FragmentAdapter(childFragmentManager, fragmentList)
        }
    }

    private fun initSmartRefresh() {
        binding.run {
            gameViewHolder = GameViewHolder(headerContainer).also {
                it.gameDownloadBtn = downloadBtn
                it.multiVersionDownloadTv = multiVersionDownloadTv
                it.gameDownloadTips = downloadTipsLottie
            }
            topMaskView.updateLayoutParams<ViewGroup.LayoutParams> {
                height = statusBarHeight + getToolbarHeight()
            }
            twoLevelOpenOffset = DisplayUtils.getScreenWidth() - getToolbarHeight() - statusBarHeight
            showTwoLevelStartOffset = 139F.dip2px() - statusBarHeight
            classicsHeader.setArrowResource(R.drawable.icon_arrow)
            statusBar.post {
                twoLevelHeader.updateLayoutParams<MarginLayoutParams> {
                    topMargin = -(statusBarHeight + getToolbarHeight())
                }
            }
            refreshLayout.setFloorHeight(DisplayUtils.getScreenWidth() - getToolbarHeight() - statusBarHeight)
            refreshLayout.setOnMultiPurposeListener(object : SimpleMultiPurposeListener() {
                override fun onRefresh(refreshLayout: RefreshLayout) {
                    val currentTabEntity = getCurrentTabEntity()
                    SensorsBridge.trackEvent("CustomPageFlush", json {
                        "bottom_tab" to bottomTabName
                        "several_tab_page_name" to multiTabNavName
                        "several_tab_page_id" to multiTabNavId
                        "position" to lastSelectedPosition
                        "tab_content" to currentTabEntity?.name
                        "custom_page_name" to currentTabEntity?.link?.text
                        "custom_page_id" to currentTabEntity?.link?.link
                    })
                    getValidSmartRefreshContent()?.onRefresh()
                }

                override fun onHeaderMoving(
                    header: RefreshHeader?,
                    isDragging: Boolean,
                    percent: Float,
                    offset: Int,
                    headerHeight: Int,
                    maxDragHeight: Int
                ) {
                    this@SearchToolbarTabWrapperFragment.isDragging = isDragging
                    headerOffset = offset
                    updateStyleOnHeaderMoving(offset)
                    headerContainer.translationY = -(twoLevelOpenOffset - offset).toFloat()
                }

                override fun onStateChanged(
                    refreshLayout: RefreshLayout,
                    oldState: RefreshState,
                    newState: RefreshState
                ) {
                    getValidSmartRefreshContent()?.onStateChanged(refreshLayout, oldState, newState)

                    val isAutoScrollToTwoLevel = oldState == RefreshState.None && newState == RefreshState.TwoLevel
                    val isDragToTwoLevel =
                        oldState == RefreshState.ReleaseToRefresh && newState == RefreshState.ReleaseToTwoLevel
                    val isScrollToTwoLevel = isDragToTwoLevel || isAutoScrollToTwoLevel
                    val isShowTwoLevelByDrag =
                        oldState == RefreshState.TwoLevelReleased && newState == RefreshState.TwoLevel
                    val isFinishTwoLevel = oldState == RefreshState.TwoLevel && newState == RefreshState.TwoLevelFinish

                    val currentTabEntity = getCurrentTabEntity()
                    pullDownPush?.run {
                        if (isAutoScrollToTwoLevel) {
                            pullDownPushAction = "自动展开"
                            twoLevelOpenCount++
                            SensorsBridge.trackEvent(
                                "DropDownPushShow",
                                json {
                                    "action" to "自动展开"
                                    "drop_down_push_id" to id
                                    "game_name" to game?.name
                                    "game_id" to game?.id
                                    "bottom_tab" to bottomTabName
                                    "several_tab_page_name" to multiTabNavName
                                    "several_tab_page_id" to multiTabNavId
                                    "position" to lastSelectedPosition
                                    "tab_content" to currentTabEntity?.name
                                    "custom_page_name" to currentTabEntity?.link?.text
                                    "custom_page_id" to currentTabEntity?.link?.link
                                }
                            )
                            com.gh.common.util.NewFlatLogUtils.logHomePushShow(
                                id,
                                "自动展开",
                                twoLevelOpenCount,
                                game?.id ?: "",
                                game?.name ?: ""
                            )
                        }
                        if (isShowTwoLevelByDrag) {
                            pullDownPushAction = "主动展开"
                            SensorsBridge.trackEvent(
                                "DropDownPushShow",
                                json {
                                    "action" to "主动展开"
                                    "drop_down_push_id" to id
                                    "game_name" to game?.name
                                    "game_id" to game?.id
                                    "bottom_tab" to bottomTabName
                                    "several_tab_page_name" to multiTabNavName
                                    "several_tab_page_id" to multiTabNavId
                                    "position" to lastSelectedPosition
                                    "tab_content" to currentTabEntity?.name
                                    "custom_page_name" to currentTabEntity?.link?.text
                                    "custom_page_id" to currentTabEntity?.link?.link
                                }
                            )
                            com.gh.common.util.NewFlatLogUtils.logHomePushShow(
                                id,
                                "主动展开",
                                twoLevelOpenCount,
                                game?.id ?: "",
                                game?.name ?: ""
                            )
                        }
                        if (isDragToTwoLevel) {
                            twoLevelOpenCount++

                            SensorsBridge.trackEvent(
                                "DropDownPushTrigger",
                                json {
                                    "drop_down_push_id" to id
                                    "game_name" to game?.name
                                    "game_id" to game?.id
                                    "bottom_tab" to bottomTabName
                                    "several_tab_page_name" to multiTabNavName
                                    "several_tab_page_id" to multiTabNavId
                                    "position" to lastSelectedPosition
                                    "tab_content" to currentTabEntity?.name
                                    "custom_page_name" to currentTabEntity?.link?.text
                                    "custom_page_id" to currentTabEntity?.link?.link
                                }
                            )
                            com.gh.common.util.NewFlatLogUtils.logHomePushTrigger(
                                id,
                                twoLevelOpenCount,
                                game?.id ?: "",
                                game?.name ?: ""
                            )
                        }
                    }

                    if (isScrollToTwoLevel) {
                        showTwoLevel = true
                        refreshStatusBarStyle()
                    }

                    if (isFinishTwoLevel) {
                        pausePullDownPushVideo()
                        if (isDragging) {
                            finishTwoLevel("主动收起")
                        }
                        showTwoLevel = false
                    }

                    when (newState) {
                        RefreshState.TwoLevel -> {
                            binding.refreshLayout.isDisableContent = false
                        }
                        RefreshState.None -> {
                            showTwoLevel = false
                            isDragging = false
                            twoLevelHeader.setFloorDuration(1000)
                            binding.refreshLayout.setFloorDuration(1000)
                            classicsHeader.visibility = View.VISIBLE
                        }

                        RefreshState.PullDownToRefresh -> {
                            showTwoLevel = false
                            binding.classicsHeader.updateLayoutParams<MarginLayoutParams> {
                                topMargin = getToolbarHeight() + statusBarHeight - 59F.dip2px()
                            }
                        }

                        RefreshState.PullDownCanceled,
                        RefreshState.ReleaseToRefresh -> showTwoLevel = false

                        else -> {
                            // do nothing
                        }
                    }

                    val clipChildrenTemp: Boolean
                    when (newState) {
                        RefreshState.TwoLevel,
                        RefreshState.TwoLevelFinish -> {
                            clipChildrenTemp = false
                            toolbarBackground.alpha = 0F
                            statusBarBackground.alpha = 0F
                            contentContainer.radius = 8F.dip2px().toFloat()
                        }

                        RefreshState.ReleaseToTwoLevel,
                        RefreshState.TwoLevelReleased -> {
                            clipChildrenTemp = false
                            toolbarBackground.alpha = 0F
                            statusBarBackground.alpha = 0F
                            headerBackground.alpha = 0F
                            contentContainer.radius = 8F.dip2px().toFloat()
                        }

                        else -> {
                            clipChildrenTemp = true
                            toolbarBackground.alpha = 1F
                            statusBarBackground.alpha = 1F
                            headerBackground.alpha = 1F
                            contentContainer.radius = 0F
                        }
                    }

                    if (clipChildren != clipChildrenTemp) {
                        clipChildren = clipChildrenTemp
                        wrapperLl.clipChildren = clipChildren
                        binding.refreshLayout.clipChildren = clipChildren
                    }
                }
            })

            twoLevelHeader.setOnTwoLevelListener {
                pullDownPushExposureEvent?.timeInMillisecond = System.currentTimeMillis()
                pullDownPushExposureEvent?.time = TimeUtil.currentTime()
                pullDownPushExposureEvent?.payload?.sequence = twoLevelOpenCount
                pullDownPushExposureEvent?.let {
                    ExposureManager.log(it)
                }
                elapsedHelper.resetCounting()
                elapsedHelper.resumeCounting()
                playPullDownPushVideo()
                true
            }
        }
    }

    private fun updatePullDownPushDownloadBtn() {
        binding.run {
            pullDownPush?.game?.run {
                gameViewHolder?.let {
                    DownloadItemUtils.updateItem(requireContext(), this, it)
                }
                DownloadItemUtils.setOnClickListener(
                    requireContext(),
                    downloadBtn,
                    this,
                    0,
                    null,
                    "自定义页面-下拉推送",
                    location = "",
                    traceEvent = pullDownPushExposureEvent,
                    clickCallback = {
                        updatePullDownPushDownloadBtn()
                        val currentTabEntity = getCurrentTabEntity()
                        SensorsBridge.trackEvent(
                            "DropDownPushClick",
                            json {
                                "action" to pullDownPushAction
                                "button_name" to "下载按钮"
                                "drop_down_push_id" to id
                                "game_name" to name
                                "game_id" to id
                                "bottom_tab" to bottomTabName
                                "several_tab_page_name" to multiTabNavName
                                "several_tab_page_id" to multiTabNavId
                                "position" to lastSelectedPosition
                                "tab_content" to currentTabEntity?.name
                                "custom_page_name" to currentTabEntity?.link?.text
                                "custom_page_id" to currentTabEntity?.link?.link
                            }
                        )
                    },
                    refreshCallback = { updatePullDownPushDownloadBtn() },
                    allStateClickCallback = null
                )
            }
        }
    }

    // 下拉进入/退出下拉推送时更新背景透明度
    private fun updateStyleOnHeaderMoving(offset: Int) {
        if (context == null) return
        binding.run {
            if (offset >= showTwoLevelStartOffset) {
                val oneLevelAlpha =
                    1 - (offset - showTwoLevelStartOffset) / (twoLevelOpenOffset - showTwoLevelStartOffset).toFloat()
                tabBgView.alpha = oneLevelAlpha
                contentBgView.alpha = oneLevelAlpha
                viewModel.updateBackgroundAlpha(oneLevelAlpha)

                if (viewModel.isTabCustomPage(lastSelectedPosition)) {
                    refreshStatusBarStyle()
                    updateSearchToolbarStyle(true)
                    updateRefreshHeaderStyle()
                    if (getCurrentTabStyle()?.isSlideBackgroundColorEnable == false) {
                        if (style == Style.SINGLE_LINE_TAB) {
                            updateTabStyleOnHeaderMoving(
                                TAB_DEFAULT_COLOR_LIGHT.toColor(requireContext()),
                                TAB_DEFAULT_COLOR_LIGHT.toColor(requireContext()),
                                R.drawable.ic_home_tab_indicator_white
                            )
                        }
                    } else {
                        val lightStyle =
                            (isDisplayingLightContent && oneLevelAlpha >= PULL_TAB_TEXT_STYLE_UPDATE_PERCENT) || style == Style.SINGLE_LINE_TAB
                        val tabSelectedColor = if (lightStyle) {
                            TAB_DEFAULT_COLOR_LIGHT.toColor(requireContext())
                        } else {
                            TAB_SELECTED_COLOR.toColor(requireContext())
                        }
                        val tabDefaultColor = if (lightStyle) {
                            TAB_DEFAULT_COLOR_LIGHT.toColor(requireContext())
                        } else {
                            TAB_DEFAULT_COLOR.toColor(requireContext())
                        }
                        val indicatorDrawable = if (lightStyle) {
                            R.drawable.ic_home_tab_indicator_white
                        } else {
                            R.drawable.ic_commodity_selected
                        }
                        updateTabStyleOnHeaderMoving(tabSelectedColor, tabDefaultColor, indicatorDrawable)
                    }
                }
            } else {
                tabBgView.alpha = 1F
                contentBgView.alpha = 1F
                viewModel.updateBackgroundAlpha(1F)

                if (viewModel.isTabCustomPage(lastSelectedPosition)) {
                    refreshStatusBarStyle()
                    updateSearchToolbarStyle(mIsDarkModeOn || isDisplayingLightContent)
                    updateRefreshHeaderStyle()
                    if (getCurrentTabStyle()?.isSlideBackgroundColorEnable == false && style == Style.SINGLE_LINE_TAB) {
                        updateTabStyleOnHeaderMoving(
                            TAB_SELECTED_COLOR.toColor(requireContext()),
                            TAB_DEFAULT_COLOR.toColor(requireContext()),
                            R.drawable.ic_commodity_selected
                        )
                    }
                }
            }

            if (refreshLayout.state == RefreshState.TwoLevelFinish || refreshLayout.state == RefreshState.TwoLevel) {
                headerBackground.alpha = 1 - offset / twoLevelOpenOffset.toFloat()
            }
        }
    }

    private fun updateTabStyleOnHeaderMoving(tabSelectedColor: Int, tabDefaultColor: Int, indicatorDrawable: Int) {
        if (currentTabSelectedColor != tabSelectedColor || currentTabDefaultColor != tabDefaultColor) {
            currentTabSelectedColor = tabSelectedColor
            currentTabDefaultColor = tabDefaultColor
            updateTabStyle(lastSelectedPosition, 0F, currentTabDefaultColor, currentTabSelectedColor)
        }
        if (currentIndicatorDrawable != indicatorDrawable) {
            currentIndicatorDrawable = indicatorDrawable
            indicatorView?.updateIndicatorDrawable(indicatorDrawable.toDrawable(requireContext()))
        }
    }

    override fun popupPullDownPush(finishCallback: () -> Unit) {
        if (!isSupportVisible) {
            setResumeAndPauseListener {
                if (it) {
                    popupPullDownPush(finishCallback)
                    setResumeAndPauseListener(null)
                }
            }
            return
        }
        binding.run {
            // 搜索栏隐藏时滚动到顶部
            if (viewModel.appBarOffset != 0) {
                appbar.setExpanded(true)
            }
            (getFragment(viewPager.currentItem) as? IScrollable)?.scrollToTop()

            if (multiTabNavId == MainWrapperRepository.getInstance().defaultNavId) {
                pullDownPush =
                    pullDownPush ?: MainWrapperRepository.getInstance().customPageLiveData.value?.linkPullDownPush
            }

            if ((pullDownPush == null)
                || fragmentList.isEmpty()
                || fragmentList.safelyGetInRelease(viewPager.currentItem) !is ISmartRefreshContent
            ) {
                finishCallback.invoke()
                return
            }

            // 自动弹出时禁止一切手势操作，避免动画冲突造成界面混乱
            refreshLayout.isDisableContent = true

            // 自动弹出
            mBaseHandler.post {
                pullDownPush?.run {
                    val pullDownPushSet = HashSet(SPUtils.getStringSet(Constants.SP_PULL_DOWN_PUSH_POP_UP_SET))
                    twoLevelHeader.openTwoLevel(true)
                    wrapperLl.clipChildren = false
                    refreshLayout.clipChildren = false
                    headerBackground.animate().alpha(0F).duration = AUTO_OPEN_TWO_LEVEL_DURATION
                    statusBarBackground.animate().alpha(0F).duration = AUTO_OPEN_TWO_LEVEL_DURATION
                    toolbarBackground.animate().alpha(0F).duration = AUTO_OPEN_TWO_LEVEL_DURATION
                    classicsHeader.visibility = View.INVISIBLE
                    pullDownPushSet.add(id)
                    SPUtils.setStringSet(Constants.SP_PULL_DOWN_PUSH_POP_UP_SET, pullDownPushSet)
                    autoFinishTwoLevelCallback = finishCallback
                    autoFinishTwoLevelHandler = object : Handler(Looper.getMainLooper()) {
                        override fun handleMessage(msg: Message) {
                            super.handleMessage(msg)
                            finishTwoLevel("自动收起")
                            finishCallback.invoke()
                        }
                    }
                    when {
                        putAwaySwitch == "video_finished" && video != null -> {
                            autoVideoView?.setVideoAllCallBack(object : GSYSampleCallBack() {
                                override fun onAutoComplete(url: String?, vararg objects: Any?) {
                                    super.onAutoComplete(url, *objects)
                                    autoFinishTwoLevelHandler?.sendEmptyMessage(KEY_AUTO_FINISH_TWO_LEVEL)
                                    autoVideoView?.setVideoAllCallBack(null)
                                }
                            })
                        }
                        putAwaySwitch.toIntOrNull() != null -> {
                            val autoFinishDelayTime = putAwaySwitch.toInt() * 1000L
                            autoFinishTwoLevelHandler?.sendEmptyMessageDelayed(KEY_AUTO_FINISH_TWO_LEVEL, autoFinishDelayTime)
                        }
                    }
                }
            }
        }
    }

    override fun setPullDownPush(pullDownPush: PullDownPush?, pullDownPushHandler: PullDownPushHandler?) {
        if (!isAdded) return

        if (autoVideoView == null) {
            binding.autoVideoViewStub.setOnInflateListener { _, inflated ->
                autoVideoView = LayoutAutoVideoViewBinding.bind(inflated).root
                setPullDownPushInternal(pullDownPush, pullDownPushHandler)
            }
            try {
                binding.autoVideoViewStub.inflateOrShow()
            } catch (e: Exception) {
                SentryHelper.onEvent("VIEW_STUB_INFLATE_ERROR", "digest", e.localizedMessage)
            }
        } else {
            setPullDownPushInternal(pullDownPush, pullDownPushHandler)
        }
    }

    private fun setPullDownPushInternal(push: PullDownPush?, pullDownPushHandler: PullDownPushHandler?) {
        if (push != null) {
            setSmartRefreshEnabled(true)
            if ((pullDownPush?.id ?: "") == push.id) return

            pullDownPush = push
            pullDownPush?.run {
                if (game != null) {
                    game.sequence = 1
                    pullDownPushExposureEvent = ExposureEvent.createEventWithSourceConcat(
                        game,
                        basicSource = listOf(ExposureSource("自定义页面", "$customPageName+$customPageId")),
                        source = listOf(ExposureSource("下拉推送", id))
                    )
                }

                binding.run {
                    if (game != null) {
                        gameNameTv.text = game.name
                        GameItemViewHolder.initGameSubtitleAndAdLabel(game, gameSubtitleTv)
                        updatePullDownPushDownloadBtn()
                        headerContainer.setOnClickListener {
                            if (showTwoLevel) {
                                pullDownPushClick = true
                                val currentTabEntity = getCurrentTabEntity()
                                SensorsBridge.trackEvent(
                                    "DropDownPushClick",
                                    json {
                                        "action" to pullDownPushAction
                                        "button_name" to "游戏详情"
                                        "drop_down_push_id" to id
                                        "game_name" to game.name
                                        "game_id" to game.id
                                        "bottom_tab" to bottomTabName
                                        "several_tab_page_name" to multiTabNavName
                                        "several_tab_page_id" to multiTabNavId
                                        "position" to lastSelectedPosition
                                        "tab_content" to currentTabEntity?.name
                                        "custom_page_name" to currentTabEntity?.link?.text
                                        "custom_page_id" to currentTabEntity?.link?.link
                                    }
                                )
                                GameDetailActivity.startGameDetailActivity(
                                    requireContext(),
                                    game.id,
                                    "(自定义页面-下拉推送)",
                                    pullDownPushExposureEvent
                                )
                            }
                        }
                    }
                    descTv.text = description
                    gameImageIv.goneIf(video != null) {
                        ImageUtils.display(gameImageIv, imgUrl)
                    }
                    autoVideoView?.onVideoReset()
                    muteIv.isVisible = video != null
                    autoVideoView?.goneIf(video == null) {
                        if (autoVideoView?.isInPlayingState == false) {
                            GSYVideoOptionBuilder()
                                .setIsTouchWiget(false)
                                .setUrl(video?.url ?: "")
                                .setRotateViewAuto(false)
                                .setCacheWithPlay(true)
                                .setRotateWithSystem(false)
                                .setReleaseWhenLossAudio(true)
                                .setLooping(false)
                                .setShowFullAnimation(false)
                                .build(autoVideoView)
                            autoVideoView?.updateThumb(imgUrl)
                            autoVideoView?.setParamsData(game, null)
                            autoVideoView?.setOnVideoClickListener {
                                headerContainer.performClick()
                            }
                        }
                        var videoVoiceStatus = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
                        muteIv.setImageResource(if (videoVoiceStatus) R.drawable.ic_basic_offsound else R.drawable.ic_basic_onsound)
                        muteIv.setDebouncedClickListener {
                            videoVoiceStatus = !videoVoiceStatus
                            muteIv.setImageResource(if (videoVoiceStatus) R.drawable.ic_basic_offsound else R.drawable.ic_basic_onsound)
                            if (videoVoiceStatus) {
                                autoVideoView?.mute()
                            } else {
                                autoVideoView?.unMute()
                            }
                        }
                    }
                }
            }
        }

        val pullDownPushSet =
            SPUtils.getStringSet(Constants.SP_PULL_DOWN_PUSH_POP_UP_SET)
        val popupPush = pullDownPush != null
                && "on" == pullDownPush!!.popSwitch
                && !pullDownPushSet.contains(pullDownPush!!.id)

        pullDownPushHandler?.doPreProcess(this as? ISmartRefresh, popupPush)
    }

    private fun observeVolume() {
        context?.applicationContext?.contentResolver?.registerContentObserver(
            android.provider.Settings.System.CONTENT_URI,
            true,
            volumeObserver
        )
    }

    private fun unObserveVolume() {
        context?.applicationContext?.contentResolver?.unregisterContentObserver(volumeObserver)
    }


    private fun updateRefreshHeaderStyle(force: Boolean = false) {
        if (lightRefreshHeaderStyle == isDisplayingLightContent && !force) return
        lightRefreshHeaderStyle = isDisplayingLightContent
        binding.classicsHeader.run {
            val arrowColorFilterColor = if (isDisplayingLightContent) com.gh.gamecenter.common.R.color.text_aw_primary else com.gh.gamecenter.common.R.color.text_tertiary
            val primaryColor = if (isDisplayingLightContent) com.gh.gamecenter.common.R.color.white else com.gh.gamecenter.common.R.color.ui_surface
            val accentColor = if (isDisplayingLightContent) com.gh.gamecenter.common.R.color.white else com.gh.gamecenter.common.R.color.text_tertiary
            setArrowColorFilter(arrowColorFilterColor.toColor(requireContext()))
            setPrimaryColor(primaryColor.toColor(requireContext()))
            setAccentColor(accentColor.toColor(requireContext()))
        }
    }

    // 播放下拉推送视频
    private fun playPullDownPushVideo() {
        binding.run {
            if (!pullDownPush?.video?.url.isNullOrEmpty()) {
                if (autoVideoView?.currentState != GSYVideoView.CURRENT_STATE_PAUSE) {
                    mBaseHandler.postDelayed({
                        val videoOption =
                            SPUtils.getString(Constants.SP_HOME_OR_DETAIL_VIDEO_OPTION, Constants.VIDEO_OPTION_WIFI)
                                ?: Constants.VIDEO_OPTION_WIFI

                        when (videoOption) {
                            Constants.VIDEO_OPTION_ALL -> {
                                autoVideoView?.onVideoReset()
                                autoVideoView?.startPlayLogic(false)
                            }

                            Constants.VIDEO_OPTION_WIFI -> {
                                if (NetworkUtils.isWifiConnected(HaloApp.getInstance().application)) {
                                    autoVideoView?.onVideoReset()
                                    autoVideoView?.startPlayLogic(false)
                                }
                            }

                            else -> {
                                //do nothing
                            }
                        }
                    }, PULL_DOWN_PUSH_VIDEO_PLAY_DELAY)
                } else {
                    resumePullDownPushVideo()
                }
                observeVolume()
            }
        }
    }

    private fun pausePullDownPushVideo() {
        binding.run {
            if (showTwoLevel && !pullDownPush?.video?.url.isNullOrEmpty()) {
                autoVideoView?.onVideoPause()
                val currentPosition = autoVideoView?.getCurrentPosition() ?: 0L
                val videoUrl = autoVideoView?.getUrl()
                if (!videoUrl.isNullOrEmpty()) {
                    ScrollCalculatorHelper.savePlaySchedule(MD5Utils.getContentMD5(videoUrl), currentPosition)
                }
                unObserveVolume()
            }
        }
    }

    private fun resumePullDownPushVideo() {
        binding.run {
            if (!finishingTwoLevel && showTwoLevel && !pullDownPush?.video?.url.isNullOrEmpty()) {
                val videoUrl = autoVideoView?.getUrl()
                if (!videoUrl.isNullOrEmpty()) {
                    val position = ScrollCalculatorHelper.getPlaySchedule(MD5Utils.getContentMD5(videoUrl))
                    //这里必须要延迟操作，否则会白屏
                    mBaseHandler.postDelayed({
                        if (position != 0L) {
                            autoVideoView?.seekTo(position)
                            autoVideoView?.onVideoResume(false)
                            if (autoVideoView?.isMute == true) {
                                autoVideoView?.mute()
                            } else {
                                autoVideoView?.unMute()
                            }
                        } else {
                            autoVideoView?.release()
                        }
                    }, PULL_DOWN_PUSH_VIDEO_PLAY_DELAY)
                }
            }
        }
    }

    override fun onFragmentPause() {
        super.onFragmentPause()
        pausePullDownPushVideo()
        DownloadManager.getInstance().removeObserver(dataWatcher)

        superiorChain?.unregisterInferiorChain(priorityChain)
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(status: EBDownloadStatus) {
        packageViewModel.filterSameUpdateLiveData.value?.let {
            setDownloadHint(it)
        }
        // 下载被删除事件
        if ("delete" == status.status) {
            if (status.gameId == pullDownPush?.game?.id) {
                updatePullDownPushDownloadBtn()
            }
        }
    }

    // 安装/卸载 事件
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(busFour: EBPackage) {
        if (busFour.isInstalledOrUninstalled()) {
            updatePullDownPushDownloadBtn()
        }
    }

    override fun finishRefresh() {
        binding.refreshLayout.finishRefresh(true)
    }

    override fun setSmartRefreshEnabled(isEnable: Boolean) {
        binding.refreshLayout.setEnableRefresh(isEnable)
        getValidSmartRefreshContent()?.setSwipeRefreshEnabled(!isEnable)
        getCurrentTabEntity()?.showPullDownPush = isEnable
    }

    override fun finishTwoLevel(action: String) {
        if (showTwoLevel) {
            autoFinishTwoLevelHandler?.removeMessages(KEY_AUTO_FINISH_TWO_LEVEL)
            binding.twoLevelHeader.finishTwoLevel()
            autoFinishTwoLevelCallback?.invoke()
            autoFinishTwoLevelCallback = null
            elapsedHelper.pauseCounting()
            pullDownPush?.run {
                val currentTabEntity = getCurrentTabEntity()
                SensorsBridge.trackEvent(
                    "DropDownPushClick",
                    json {
                        "action" to pullDownPushAction
                        "button_name" to "关闭推送"
                        "drop_down_push_id" to id
                        "game_name" to game?.name
                        "game_id" to game?.id
                        "bottom_tab" to bottomTabName
                        "several_tab_page_name" to multiTabNavName
                        "several_tab_page_id" to multiTabNavId
                        "position" to lastSelectedPosition
                        "tab_content" to currentTabEntity?.name
                        "custom_page_name" to currentTabEntity?.link?.text
                        "custom_page_id" to currentTabEntity?.link?.link
                    }
                )
                com.gh.common.util.NewFlatLogUtils.logHomePushClose(
                    id,
                    action,
                    twoLevelOpenCount,
                    game?.id ?: "",
                    game?.name ?: "",
                    elapsedHelper.elapsedTime
                )
            }
        }
    }

    override fun onFragmentResume() {
        super.onFragmentResume()
        refreshStatusBarStyle(true)
        resumePullDownPushVideo()
        DownloadManager.getInstance().addObserver(dataWatcher)
        updatePullDownPushDownloadBtn()
        mainWrapperViewModel?.requestAccelerateNotificationPopup()
        updateSearchToolbarStyle(mIsDarkModeOn || isDisplayingLightContent || showTwoLevel, true)
        if (CheckLoginUtils.isLogin()) {
            unreadViewModel.retry()
        }

        mBaseHandler.post {
            superiorChain?.registerInferiorChain(priorityChain)
        }
    }

    override fun onPageSelected(position: Int) {
        super.onPageSelected(position)
        getCurrentTabEntity()?.showPullDownPush?.let { setSmartRefreshEnabled(it) }
        if (showTwoLevel) finishTwoLevel("跳转收起")
    }

    private fun updateIndicatorDrawable(indicatorView: TabIndicatorView?) {
        if (isDisplayingLightContent) {
            indicatorView?.updateIndicatorDrawable(R.drawable.ic_home_tab_indicator_white.toDrawable(requireContext()))
        } else {
            indicatorView?.updateIndicatorDrawable(R.drawable.ic_commodity_selected.toDrawable(requireContext()))
        }
    }

    override fun onPageScrolled(
        position: Int,
        positionOffset: Float,
        tabEntityList: ArrayList<MultiTabNav.LinkMultiTabNav>
    ) {
        val nextPosition = position + 1
        val tabStyle = tabEntityList.safelyGetInRelease(position)?.style

        // 处理当前 tab 和下一个 tab
        if (nextPosition != tabBindingList.size) {
            val nextTabStyle = tabEntityList.safelyGetInRelease(nextPosition)?.style
            var currentAppBarColor = tabStyle?.primaryColor ?: backgroundWhiteColor
            var nextAppBarColor = nextTabStyle?.primaryColor ?: backgroundWhiteColor

            if (currentAppBarColor == Color.WHITE) currentAppBarColor = backgroundWhiteColor
            if (nextAppBarColor == Color.WHITE) nextAppBarColor = backgroundWhiteColor

            if (getFragment(position) is AmwayFragment) {
                currentAppBarColor = if (mIsDarkModeOn) backgroundColor else amwayPrimaryColor
                tabStyle?.currentSelectColor = currentAppBarColor
            }
            if (getFragment(nextPosition) is AmwayFragment) {
                nextAppBarColor = if (mIsDarkModeOn) backgroundColor else amwayPrimaryColor
            }

            val proximatelySelectedTabStyle = if (positionOffset < 0.5) tabStyle else nextTabStyle

            val appBarColorInBetween = if (currentAppBarColor == nextAppBarColor) {
                currentAppBarColor
            } else {
                ColorUtils.blendARGB(currentAppBarColor, nextAppBarColor, positionOffset)
            }

            // 颜色显示是否变更
            val isDisplayingLightContentTemp = proximatelySelectedTabStyle?.useLightStyle ?: false || showTwoLevel
            val isContentStyleChanged = isDisplayingLightContentTemp != isDisplayingLightContent
            isDisplayingLightContent = isDisplayingLightContentTemp

            if (!showTwoLevel) {
                currentTabSelectedColor =
                    if (isDisplayingLightContent) tabDefaultLightColor else tabSelectedColor
                currentTabDefaultColor = if (isDisplayingLightContent) tabDefaultLightColor else tabDefaultColor
            }

            if (isContentStyleChanged) {
                binding.searchIv.setImageResource(if (isDisplayingLightContent) R.drawable.toolbar_search_light else R.drawable.toolbar_search)
                if (!showTwoLevel) updateIndicatorDrawable(indicatorView)
                refreshStatusBarStyle()
            }

            this.currentAppBarColor = appBarColorInBetween
            updateAppBarStyle(appBarColorInBetween, isDisplayingLightContent)
        } else {
            var currentAppBarColor = tabStyle?.primaryColor ?: backgroundWhiteColor
            if (mIsDarkModeOn && currentAppBarColor == Color.WHITE) {
                currentAppBarColor = backgroundWhiteColor
            }
            if (getFragment(position) is AmwayFragment) {
                currentAppBarColor = if (mIsDarkModeOn) backgroundColor else amwayPrimaryColor
                tabStyle?.currentSelectColor = currentAppBarColor
            }
            isDisplayingLightContent = tabStyle?.useLightStyle == true || showTwoLevel
            if (!showTwoLevel) {
                currentTabSelectedColor =
                    if (isDisplayingLightContent) tabDefaultLightColor else tabSelectedColor
                currentTabDefaultColor = if (isDisplayingLightContent) tabDefaultLightColor else tabDefaultColor
            }

            updateAppBarStyle(currentAppBarColor, isDisplayingLightContent)
            binding.searchIv.setImageResource(if (isDisplayingLightContent) R.drawable.toolbar_search_light else R.drawable.toolbar_search)
            if (!showTwoLevel) updateIndicatorDrawable(indicatorView)
            refreshStatusBarStyle()
        }

        // 这里的 selectedPosition 指的是应该被高亮显示的 position
        val selectedPosition = try {
            (position + positionOffset).roundToInt()
        } catch (e: IllegalArgumentException) {
            // roundToInt() 方法有时候会报 Cannot round NaN value. 错误 positionOffset 的值为 NAN
            // https://sentry.shanqu.cc/organizations/lightgame/issues/301377/?project=22
            position
        }
        val positionOffsetOnRealSelectedPosition = if (positionOffset >= 0.5) {
            positionOffset - 1
        } else {
            positionOffset
        }

        updateTabStyle(
            selectedPosition,
            positionOffsetOnRealSelectedPosition,
            currentTabDefaultColor,
            currentTabSelectedColor
        )
    }

    override fun onScrollChanged(totalHeight: Int, offset: Int, isDarkModeChanged: Boolean) {
        val currentTabStyle = getCurrentTabStyle()
        currentTabStyle?.offsetRatio = offset / totalHeight.toFloat()
        if (((currentTabStyle?.isSlideBackgroundColorShow == true || (currentTabStyle != null && isDarkModeChanged)) && offset >= totalHeight)
            || (currentTabStyle?.isSlideBackgroundColorEnable == false && viewModel.isTabCustomPage(lastSelectedPosition))
        ) {
            currentTabStyle.isSlideBackgroundColorShow = false
            currentTabStyle.primaryColor = backgroundWhiteColor
            currentTabStyle.useLightStyle = false
            isDisplayingLightContent = showTwoLevel && !currentTabStyle.isSlideBackgroundColorEnable
            updateAppBarColorWhenScrollChanged(backgroundWhiteColor)
            mBaseHandler.post { refreshStatusBarStyle() }
            if (!showTwoLevel || !currentTabStyle.isSlideBackgroundColorEnable) {
                currentTabSelectedColor = TAB_SELECTED_COLOR.toColor(requireContext())
                currentTabDefaultColor = TAB_DEFAULT_COLOR.toColor(requireContext())
                indicatorView?.updateIndicatorDrawable(R.drawable.ic_commodity_selected.toDrawable())
                binding.searchIv.setImageResource(R.drawable.toolbar_search)
                updateTabStyle(lastSelectedPosition, 0F, currentTabDefaultColor, currentTabSelectedColor)
            }
        } else if (offset < totalHeight) {
            var currentSelectColor = currentTabStyle?.currentSelectColor ?: 0
            val offsetMeetsCriticalPoint = (currentTabStyle?.offsetRatio ?: 0F) < offsetCritical
            currentTabStyle?.isSlideBackgroundColorShow = true
            if (getFragment(binding.viewPager.currentItem) is AmwayFragment) {
                currentSelectColor = if (mIsDarkModeOn) backgroundColor else amwayPrimaryColor
            }
            val colorInBetween =
                ColorUtils.blendARGB(currentSelectColor, backgroundWhiteColor, currentTabStyle?.offsetRatio ?: 0F)
            updateAppBarColorWhenScrollChanged(colorInBetween)
            currentTabStyle?.primaryColor = colorInBetween
            currentTabStyle?.useLightStyle = offsetMeetsCriticalPoint
            if (isDisplayingLightContent != currentTabStyle?.useLightStyle) {
                isDisplayingLightContent = offsetMeetsCriticalPoint
            }
            mBaseHandler.post { refreshStatusBarStyle() }
            if (!showTwoLevel) {
                currentTabSelectedColor = if (offsetMeetsCriticalPoint) tabDefaultLightColor else tabSelectedColor
                currentTabDefaultColor = if (offsetMeetsCriticalPoint) tabDefaultLightColor else tabDefaultColor
                indicatorView?.updateIndicatorDrawable(
                    if (offsetMeetsCriticalPoint) {
                        R.drawable.ic_home_tab_indicator_white.toDrawable()
                    } else {
                        R.drawable.ic_commodity_selected.toDrawable()
                    }
                )
                binding.searchIv.setImageResource(if (offsetMeetsCriticalPoint) R.drawable.toolbar_search_light else R.drawable.toolbar_search)
                updateTabStyle(lastSelectedPosition, 0F, currentTabDefaultColor, currentTabSelectedColor)
            }
        }
    }

    private fun updateAppBarColorWhenScrollChanged(color: Int) {
        val currentTabStyle = getCurrentTabStyle()
        if ((currentTabStyle?.offsetRatio ?: 0F) >= 1F && color != com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext())) {
            currentTabStyle?.currentSelectColor = color
            currentTabStyle?.primaryColor = color
        }

        val useLightStyle = color != com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()) ||
                (showTwoLevel && currentTabStyle?.isSlideBackgroundColorEnable == false)
        updateAppBarStyle(color, useLightStyle)
    }

    override fun changeAppBarColor(color: Int, pageId: String) {
        val currentTab = getCurrentTabEntity()
        val currentTabStyle = getCurrentTabStyle()
        //此处的判断是防止banner在滑动过程中切换tab会导致背景设置错误
        if (style != Style.NO_TAB && (currentTab?.link?.type != ViewPagerFragmentHelper.TYPE_CUSTOM_PAGE || currentTab.link.link != pageId)) {
            val customPageTabStyle = viewModel.getCustomPageTabEntity(pageId)?.style
            customPageTabStyle?.currentSelectColor = color
            if (customPageTabStyle?.isSlideBackgroundColorShow == true) {
                val colorInBetween =
                    ColorUtils.blendARGB(
                        color,
                        com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()),
                        customPageTabStyle.offsetRatio
                    )
                customPageTabStyle.primaryColor = colorInBetween
            }
        } else {
            currentTabStyle?.currentSelectColor = color
            if (currentTabStyle?.isSlideBackgroundColorShow == true) {
                val colorInBetween =
                    ColorUtils.blendARGB(
                        color,
                        com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()),
                        currentTabStyle.offsetRatio
                    )
                currentTabStyle.primaryColor = colorInBetween
                updateAppBarStyle(colorInBetween, colorInBetween != com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()))
            }
        }
    }

    override fun updateSearchStyle(searchStyle: BottomTab.SearchStyle) { this.searchStyle = searchStyle }

    override fun getCurrentTabIndex(): Int? = provideViewPager()?.currentItem
    override fun addTabGuideHandlerIfExists(chain: PriorityChain) {
        if (isDefaultCustomPageFragment()) {
            chain.addHandler(multiTabGuideHandler)
        }
    }

    private fun getCurrentTabStyle(): MultiTabNav.LinkMultiTabNav.TabStyle? =
        if (style == Style.NO_TAB) viewModel.noTabStyle else getCurrentTabEntity()?.style

    /**
     * 更新 AppBar 的控件 style
     */
    private fun updateAppBarStyle(color: Int, useLightStyle: Boolean) {
        binding.toolbarBgView.setBackgroundColor(color)
        binding.statusBar.setBackgroundColor(color)
        binding.headerBgView.setBackgroundColor(color)
        binding.tabBgView.setBackgroundColor(color)
        binding.contentBgView.setBackgroundColor(color)

        updateSearchToolbarStyle(mIsDarkModeOn || useLightStyle)
    }

    private fun updateSearchToolbarStyle(useLightStyle: Boolean, force: Boolean = false) {
        if (lightSearchToolbarStyle == useLightStyle && !force) return
        lightSearchToolbarStyle = useLightStyle

        binding.searchToolbar.actionbarIvSearch.setImageResource(if (useLightStyle) R.drawable.toolbar_search_icon_light else com.gh.gamecenter.common.R.drawable.toolbar_search_icon)
        binding.searchToolbar.actionbarDownload.setImageResource(if (useLightStyle) R.drawable.toolbar_download_light else R.drawable.toolbar_download)
        binding.searchToolbar.actionbarMessage.setImageResource(if (useLightStyle) R.drawable.toolbar_message_light else R.drawable.toolbar_message)
        binding.searchToolbar.actionbarTeenagerModelIv.setImageResource(if (useLightStyle) R.drawable.toolbar_teenager_light else R.drawable.toolbar_teenager)
        binding.searchToolbar.actionbarTeenagerModelTv.setTextColor(
            if (useLightStyle) Color.WHITE else com.gh.gamecenter.common.R.color.text_secondary.toColor(
                requireContext()
            )
        )

        binding.tabSearchToolbar.searchIv.setImageResource(if (useLightStyle) R.drawable.toolbar_search_icon_light else com.gh.gamecenter.common.R.drawable.toolbar_search_icon)
        binding.tabSearchToolbar.menuDownloadIv.setImageResource(if (useLightStyle) R.drawable.toolbar_download_light else R.drawable.toolbar_download)

        searchRightView?.setImageResource(if (useLightStyle) R.drawable.toolbar_search_light else R.drawable.toolbar_search)
        teenagerModelView?.setBackgroundResource(if (useLightStyle) R.drawable.button_round_black_alpha_10 else R.drawable.button_round_f2f4f7)
        searchHintTv?.setHintTextColor(
            if (useLightStyle) com.gh.gamecenter.common.R.color.search_text_color_light.toColor(requireContext()) else com.gh.gamecenter.common.R.color.search_text_color_default.toColor(
                requireContext()
            )
        )
        searchContainerView?.background =
            if (useLightStyle) R.drawable.home_search_bg_light.toDrawable(requireContext()) else R.drawable.home_search_bg.toDrawable(
                requireContext()
            )
    }

    override fun onBackPressed(): Boolean {
        if (showTwoLevel) {
            finishTwoLevel("主动收起")
            return true
        }
        return super.onBackPressed()
    }

    override fun showTabGuide(shouldShow: Boolean, guide: BottomTab.Guide?, guidePosition: Int) {
        if (style == Style.NO_TAB) return

        if (!isDefaultCustomPageFragment()) {
            priorityChain.addHandler(multiTabGuideHandler)
        }

        if (shouldShow && guide != null && guidePosition != -1) {
            tabLayout?.post {
                val tabView = tabLayout?.getTabAt(guidePosition)?.view
                if (tabView != null) {
                    val isSingleLineTab = style == Style.SINGLE_LINE_TAB
                    multiTabGuideHandler.doPreProcess(
                        true,
                        requireActivity(),
                        mBaseHandler,
                        guide,
                        tabLayout,
                        tabView,
                        isSingleLineTab,
                        parentFragment as? MainWrapperFragment,
                        this
                    )
                } else {
                    // 不显示
                    multiTabGuideHandler.doPreProcess(false)
                }
            }
        } else {
            multiTabGuideHandler.doPreProcess(false)
        }
    }

    private fun updateTabAndToolbarStyleOnDarkModeChanged() {
        viewModel.tabListLiveData.value?.forEach {
            if (it.link?.type != ViewPagerFragmentHelper.TYPE_AMWAY) {
                it.style.primaryColor = com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext())
            }
        }
        val currentTabEntity = getCurrentTabEntity()
        if (currentTabEntity?.link?.type != ViewPagerFragmentHelper.TYPE_AMWAY && currentTabEntity?.link?.type != ViewPagerFragmentHelper.TYPE_CUSTOM_PAGE) {
            onScrollChanged(0, 0, true)
        }
        binding.run {
            contentContainer.setCardBackgroundColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()))
            toolbarBackground.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()))
            if (showTwoLevel) {
                updateStyleOnHeaderMoving(headerOffset)
            }
            if (getCurrentTabStyle()?.isSlideBackgroundColorEnable == false) {
                toolbarBgView.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()))
            }
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(reuse: EBReuse) {
        if ("Refresh" == reuse.type) {
            setSearchHint()

            // 打开下载按钮事件
            downloadView?.isVisible = Config.isShow()
        }
        if (reuse.type == EntranceConsts.HOST_HOME_GAME_COLLECTION_SQUARE) {
            fragmentList.forEachIndexed { index, fragment ->
                if (fragment is GameCollectionSquareFragment) {
                    binding.viewPager.currentItem = index
                }
            }
        }
        if (reuse.type == Constants.FINISH_PULL_DOWN_PUSH) {
            if (!pullDownPushClick) {
                finishingTwoLevel = true
                mBaseHandler.postDelayed({
                    finishTwoLevel("跳转收起")
                    finishingTwoLevel = false
                }, FINISH_TWO_LEVEL_DELAY)
            }
            pullDownPushClick = false
        }
    }

    override fun onTabViewClick() {
        if (showTwoLevel) {
            binding.twoLevelHeader.setFloorDuration(100)
            binding.refreshLayout.setFloorDuration(100)
            finishTwoLevel("跳转收起")
        }
    }

    /**
     * 刷新状态栏风格 （亮色或暗色）
     * 因为调用此方法损耗较大，所以需要在状态变更时才调用
     * @param force 是否强制刷新
     */
    private fun refreshStatusBarStyle(force: Boolean = false) {
        val lightStatusBarTemp = !showTwoLevel && !isDisplayingLightContent && !mIsDarkModeOn
        if ((lightStatusBarTemp != lightStatusBar || force) && isSupportVisible) {
            lightStatusBar = lightStatusBarTemp
            DisplayUtils.transparentStatusBar(requireActivity())
            DisplayUtils.setLightStatusBar(requireActivity(), lightStatusBarTemp)
        }
    }

    /**
     * 记录 tab 被选中的日志
     */
    override fun logTabSelected(tabEntity: MultiTabNav.LinkMultiTabNav, position: Int) {
        super.logTabSelected(tabEntity, position)
        VHelper.mainEntranceMap[bottomTabName] = tabEntity.name
        LogUtils.logHomeTopTabClick(
            tabEntity.name,
            tabEntity.link?.type,
            tabEntity.link?.text,
            tabEntity.link?.link,
            position,
            "首页"
        )

        if (tabEntity.link?.type == "common_collection") {
            NewLogUtils.logAccessToCommonCollectionDetail(
                tabEntity.link.link ?: "",
                tabEntity.link.text ?: "",
                "首页顶部Tab栏"
            )
        }
    }

    override fun onDarkModeChanged() {
        super.onDarkModeChanged()
        updateSearchToolbarStyle(mIsDarkModeOn || isDisplayingLightContent, true)
        updateRefreshHeaderStyle(true)
        updateTabAndToolbarStyleOnDarkModeChanged()
        updatePullDownPushDownloadBtn()
    }

    override fun registerInferiorChain(chain: PriorityChain) {
        inferiorChain = chain
        if (priorityChain.isHandlerQueueEmpty()) {
            inferiorChain?.resume()
        }
    }

    override fun unregisterInferiorChain(chain: PriorityChain) {
        if (inferiorChain == chain) {
            inferiorChain = null
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        autoFinishTwoLevelHandler?.removeCallbacksAndMessages(null)
        autoVideoView?.release()
    }

    override fun getBusinessId(): Pair<String, String> = (currentFragment as? IBusiness)?.getBusinessId() ?: Pair("", "")

    enum class Style {
        /**
         * 搜索栏+无Tab
         */
        NO_TAB,

        /**
         * 单行搜索栏+Tab
         * TAB栏与搜索栏在同一行展示，对应 search_style.style_type=apposition
         */
        SINGLE_LINE_TAB,

        /**
         * 两行搜索栏+Tab
         * TAB栏与搜索栏分开两行展示，对应 search_style.style_type=two_lines
         */
        TWO_LINES_TAB,
    }

    companion object {
        const val PULL_DOWN_PUSH_VIDEO_PLAY_DELAY = 100L
        const val FINISH_TWO_LEVEL_DELAY = 1000L
        const val AUTO_OPEN_TWO_LEVEL_DURATION = 1000L
        const val PULL_TAB_TEXT_STYLE_UPDATE_PERCENT = 0.5F
        const val KEY_AUTO_FINISH_TWO_LEVEL = 123
    }

}