package com.gh.gamecenter.wrapper

import android.os.Bundle
import android.view.View
import androidx.lifecycle.Observer
import androidx.viewpager.widget.ViewPager
import com.gh.common.iinterface.ISmartRefresh
import com.gh.common.iinterface.ISmartRefreshContent
import com.gh.common.iinterface.ISuperiorChain
import com.gh.common.prioritychain.MultiTabGuideHandler
import com.gh.common.prioritychain.PriorityChain
import com.gh.common.prioritychain.PullDownPushHandler
import com.gh.gamecenter.R
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.tracker.IBusiness
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.common.view.TabIndicatorView
import com.gh.gamecenter.databinding.FragmentTabWrapperBinding
import com.gh.gamecenter.entity.BottomTab
import com.gh.gamecenter.entity.MultiTabNav
import com.gh.gamecenter.entity.PullDownPush
import com.gh.gamecenter.feature.utils.SentryHelper
import com.google.android.material.tabs.TabLayout
import com.scwang.smartrefresh.layout.api.RefreshLayout
import com.scwang.smartrefresh.layout.constant.RefreshState
import kotlin.math.roundToInt

/**
 * 二级页面-多tab导航页（带Tab的外层Fragment）
 */
class TabWrapperFragment: BaseTabWrapperFragment(), ISmartRefresh, ISmartRefreshContent, ISuperiorChain, IBusiness {
    private val binding by lazy { FragmentTabWrapperBinding.inflate(layoutInflater) }
    private val viewModel: TabWrapperViewModel by lazy { viewModelProvider(TabWrapperViewModel.Factory(multiTabNavId)) }
    private var inferiorChain: PriorityChain? = null
    private val priorityChain by lazy { PriorityChain { inferiorChain?.start() } }
    private val multiTabGuideHandler by lazy { MultiTabGuideHandler(24) }

    override fun getLayoutId(): Int = 0
    override fun getInflatedLayout(): View = binding.root
    override fun provideViewModel(): TabWrapperViewModel = viewModel
    override fun provideTabLayout(): TabLayout = binding.tabLayout
    override fun provideViewPager(): ViewPager = binding.viewPager
    override fun provideIndicatorView(): TabIndicatorView = binding.indicatorView
    override fun provideIndicatorWidth(): Int = 20
    override fun provideTabTextSize(): Float = 14F
    override fun provideTabDefaultColor(): Int = com.gh.gamecenter.common.R.color.text_secondary
    override fun provideTabSelectedColor(): Int = com.gh.gamecenter.common.R.color.text_theme
    override fun isTabScaleEnabled(): Boolean = false
    override fun addTabGuideHandlerIfExists(chain: PriorityChain) {
        if (isDefaultCustomPageFragment()) {
            chain.addHandler(multiTabGuideHandler)
        }
    }

    override fun getFirstTabLeftMargin(): Int = 4F.dip2px()
    override fun getLastTabRightMargin(): Int = 4F.dip2px()

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

    override fun onPageScrolled(
        position: Int,
        positionOffset: Float,
        tabEntityList: ArrayList<MultiTabNav.LinkMultiTabNav>
    ) {
        // 这里的 selectedPosition 指的是应该被高亮显示的 position
        val selectedPosition = try {
            (position + positionOffset).roundToInt()
        } catch (e: IllegalArgumentException) {
            // roundToInt() 方法有时候会报 Cannot round NaN value. 错误
            // https://sentry.shanqu.cc/organizations/lightgame/issues/301377/?project=22
            SentryHelper.onEvent(
                "HOME_NAN_POSITION",
                "value",
                "$position+$positionOffset=(${position + positionOffset})"
            )
            position
        }
        val positionOffsetOnRealSelectedPosition = if (positionOffset >= 0.5) {
            positionOffset - 1
        } else {
            positionOffset
        }

        updateTabStyle(selectedPosition, positionOffsetOnRealSelectedPosition, tabDefaultColor, tabSelectedColor)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setNavigationTitle(arguments?.getString(EntranceConsts.KEY_NAVIGATION_TITLE, "") ?: "")
    }

    override fun onFragmentFirstVisible() {
        super.onFragmentFirstVisible()
        initMenu(R.menu.menu_download)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel.title.observe(viewLifecycleOwner, Observer {
            setNavigationTitle(it)
        })
    }

    override fun hideTab() {
        binding.tabContainer.visibility = View.GONE
    }

    override fun showTabGuide(shouldShow: Boolean, guide: BottomTab.Guide?, guidePosition: Int) {
        if (!isDefaultCustomPageFragment()) {
            priorityChain.addHandler(multiTabGuideHandler)
            priorityChain.start()
        }

        if (shouldShow && guide != null && guidePosition != -1) {
            tabLayout?.post {
                if (activity == null) return@post

                val tabView = tabLayout?.getTabAt(guidePosition)?.view
                if (tabView != null) {
                    if (!isDefaultCustomPageFragment() && priorityChain.isHandlerQueueEmpty()) {
                        MultiTabGuideHandler.showMultiTabGuide(
                            true,
                            requireActivity(),
                            mBaseHandler as BaseHandler,
                            guide,
                            tabLayout!!,
                            tabView,
                            false
                        )
                    } else {
                        multiTabGuideHandler.doPreProcess(
                            true,
                            activity,
                            mBaseHandler,
                            guide,
                            tabLayout,
                            tabView,
                            false
                        )
                    }
                } else {
                    // 不显示
                    multiTabGuideHandler.doPreProcess(false)
                }
            }
        } else {
            multiTabGuideHandler.doPreProcess(false)
        }
    }

    override fun onRefresh() {
        getValidSmartRefreshContent()?.onRefresh()
    }

    override fun setSwipeRefreshEnabled(isSwipeRefreshEnabled: Boolean) {
        getValidSmartRefreshContent()?.setSwipeRefreshEnabled(isSwipeRefreshEnabled)
        getCurrentTabEntity()?.showPullDownPush = !isSwipeRefreshEnabled
    }

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

    override fun setSmartRefreshEnabled(isEnable: Boolean) {
        (parentFragment as? ISmartRefresh)?.setSmartRefreshEnabled(isEnable)
    }

    override fun finishTwoLevel(action: String) {
        (parentFragment as? ISmartRefresh)?.finishTwoLevel(action)
    }

    override fun finishRefresh() {
        (parentFragment as? ISmartRefresh)?.finishRefresh()
    }

    override fun popupPullDownPush(finishCallback: () -> Unit) {
        (parentFragment as? ISmartRefresh)?.popupPullDownPush(finishCallback)
    }

    override fun setPullDownPush(pullDownPush: PullDownPush?, pullDownPushHandler: PullDownPushHandler?) {
        (parentFragment as? ISmartRefresh)?.setPullDownPush(pullDownPush, pullDownPushHandler)
    }

    override fun onDarkModeChanged() {
        super.onDarkModeChanged()
        updateTabStyle(lastSelectedPosition, 0F, tabDefaultColor, tabSelectedColor)
    }

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

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

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