package com.gh.gamecenter.servers.gametest2

import android.graphics.Typeface
import android.os.Bundle
import android.view.View
import android.view.ViewGroup.MarginLayoutParams
import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.ethanhua.skeleton.Skeleton
import com.gh.common.exposure.ExposureListener
import com.gh.common.util.DialogUtils
import com.gh.common.util.DownloadItemUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.xapk.XapkInstaller
import com.gh.common.xapk.XapkUnzipStatus
import com.gh.download.DownloadManager
import com.gh.gamecenter.R
import com.gh.gamecenter.common.baselist.LazyListFragment
import com.gh.gamecenter.common.baselist.ListAdapter
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.pagelevel.IPageLevelProvider
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.databinding.FragmentGameServerTestV2ListBinding
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.feature.entity.PageLocation
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import kotlin.math.abs

class GameServerTestV2ListFragment :
    LazyListFragment<GameServerTestV2ListViewModel.ItemData, GameServerTestV2ListViewModel>() {

    private var mBinding: FragmentGameServerTestV2ListBinding? = null
    private lateinit var mExposureListener: ExposureListener
    private lateinit var mScrollCalculatorHelper: ScrollCalculatorHelper
    private var mAdapter: GameServerTestV2ListAdapter? = null
    private var mGameServerTestV2ViewModel: GameServerTestV2ViewModel? = null
    private var mSupremeSelectedTimeFilter: String? = null // 手动选择的日期，优先级高，当它存在时忽略滚动的选中

    private val dataWatcher: DataWatcher = object : DataWatcher() {
        override fun onDataChanged(downloadEntity: DownloadEntity) {
            val locationList = mListViewModel?.locationMap?.get(downloadEntity.packageName)
            if (locationList != null) {
                for (location in locationList) {
                    mListViewModel.obsListData?.value?.safelyGetInRelease(location)?.game?.let { gameEntity ->
                        DownloadItemUtils.processDate(gameEntity, downloadEntity, mAdapter, location)
                    }
                }
                if (XapkUnzipStatus.FAILURE.name == downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS]) {
                    for (position in locationList) {
                        val targetView = mListRv?.layoutManager?.findViewByPosition(position)
                        if (targetView != null) {
                            DialogUtils.showUnzipFailureDialog(requireContext(), downloadEntity)
                            break
                        }
                    }
                }
            }
        }
    }

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

    override fun provideListViewModel(): GameServerTestV2ListViewModel {
        val linkId = arguments?.getString(EntranceConsts.KEY_ID, "none") ?: "none"
        return viewModelProvider(
            GameServerTestV2ListViewModel.Factory(mGameServerTestV2ViewModel, linkId)
        )
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        mGameServerTestV2ViewModel = viewModelProviderFromParent()
        super.onCreate(savedInstanceState)
    }


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

    override fun initRealView() {
        super.initRealView()
        mListRefresh?.isEnabled = false
        mListRv?.let {
            mScrollCalculatorHelper = ScrollCalculatorHelper(it, R.id.autoVideoView, 0)
        }
    }

    override fun initSkeletonScreen() {
        if (mBinding?.skeleton == null) return
        mSkeletonScreen = Skeleton.bind(mBinding?.skeleton)
            .shimmer(true)
            .angle(Constants.SHIMMER_ANGLE)
            .color(com.gh.gamecenter.common.R.color.ui_skeleton_highlight)
            .duration(Constants.SHIMMER_DURATION)
            .maskWidth(Constants.MASK_WIDTH)
            .gradientCenterColorWidth(Constants.GRADIENT_CENTER_COLOR_WIDTH)
            .load(R.layout.fragment_game_server_test_v2_skeleton)
            .show()
    }

    override fun onFragmentFirstVisible() {
        super.onFragmentFirstVisible()
        mBinding?.topDate?.run {
            root.setPadding(16F.dip2px(), 4F.dip2px(), 16F.dip2px(), 12F.dip2px())
            root.background = R.drawable.bg_game_server_test_v2_filter_gradient_bottom.toDrawable(requireContext())
            bigTimeTv.setTypeface(Typeface.createFromAsset(requireContext().assets, Constants.DIN_FONT_PATH))
        }
        mListRv?.clearOnScrollListeners()
        mExposureListener = ExposureListener(this, mAdapter!!)
        mListRv?.addOnScrollListener(mExposureListener)
        mListRv?.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
                val layoutManager = recyclerView.layoutManager
                val dataList = mListViewModel.obsListData.value
                if (layoutManager is LinearLayoutManager && !dataList.isNullOrEmpty()) {
                    val firstVisiblePosition = layoutManager.findFirstVisibleItemPosition()
                    val firstVisibleItemData = dataList.getOrNull(firstVisiblePosition)
                    val firstVisibleView = layoutManager.findViewByPosition(firstVisiblePosition) ?: return

                    if (firstVisibleItemData?.isTopGames == true) {
                        mBinding?.topDateContainer?.isVisible = false
                        firstVisibleView.findViewById<View>(R.id.gradientBgIv)?.isVisible = true
                    } else {
                        val lastPosition = firstVisiblePosition - 1
                        val nextPosition = firstVisiblePosition + 1
                        val lastItemData = if (lastPosition >= 0) dataList.getOrNull(lastPosition) else null
                        val nextItemData = if (nextPosition < dataList.size) dataList.getOrNull(nextPosition) else null
                        val topDataLayoutParams = mBinding?.topDateContainer?.layoutParams as? MarginLayoutParams ?: return
                        if (lastItemData?.isTopGames == true) {
                            topDataLayoutParams.topMargin = 0
                            mBinding?.topDateContainer?.isVisible = abs(firstVisibleView.top) >= 16F.dip2px()
                        } else if (nextItemData?.isTopGames == true) {
                            val bottom = firstVisibleView.bottom
                            val topDateHeight = mBinding?.topDateContainer?.height ?: 0
                            val topGameView = layoutManager.findViewByPosition(nextPosition) ?: return
                            topDataLayoutParams.topMargin = if (bottom <= topDateHeight) bottom - topDateHeight else 0
                            mBinding?.topDateContainer?.isVisible = true
                            topGameView.findViewById<View>(R.id.gradientBgIv)?.isVisible = false
                        } else if (mBinding?.topDateContainer?.isVisible == false) {
                            topDataLayoutParams.topMargin = 0
                            mBinding?.topDateContainer?.isVisible = true
                        }

                        // 悬挂的文案
                        mBinding?.topDate?.run {
                            root.visibility = View.VISIBLE
                            bigTimeTv.text = mListViewModel?.getBigDayTextByPosition(firstVisiblePosition)
                            timeTv.text = mListViewModel?.getDayTextByPosition(firstVisiblePosition)
                            gameCountTv.text = mListViewModel?.getGameCountTextByPosition(firstVisiblePosition)
                        }
                    }

                    val readableDaysOffset = mListViewModel.getReadableDaysOffset(firstVisiblePosition)
                    val currentTimeFilter = mGameServerTestV2ViewModel?.getSelectedTimeFilterString(readableDaysOffset)
                    if (mSupremeSelectedTimeFilter == null && currentTimeFilter?.isNotEmpty() == true) {
                        if (mGameServerTestV2ViewModel?.selectedTimeFilterLiveData?.value != currentTimeFilter) {
                            NewFlatLogUtils.logGameTestDetailTimelineClick(
                                "",
                                "自动定位",
                                currentTimeFilter
                            )
                            mGameServerTestV2ViewModel?.selectedTimeFilterLiveData?.value = currentTimeFilter
                        }
                    }
                    if (!mListViewModel.isLoadFirstPage) {
                        showPullDownTip(false)
                    }

                    scroll()
                }
            }

            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)
                if (newState == RecyclerView.SCROLL_STATE_IDLE && !mSupremeSelectedTimeFilter.isNullOrEmpty()) {
                    mSupremeSelectedTimeFilter = null
                }
                if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
                    mSupremeSelectedTimeFilter = null
                }
                mScrollCalculatorHelper.onScrollStateChanged(newState)
            }
        })
    }

    private fun scroll() {
        val firstVisibleItem = (mListRv?.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
        val lastVisibleItem = (mListRv?.layoutManager as LinearLayoutManager).findLastVisibleItemPosition()
        mScrollCalculatorHelper.onScroll(firstVisibleItem, lastVisibleItem)
    }

    override fun provideListAdapter(): ListAdapter<*> {
        val exposureSource =
            if (requireArguments().getParcelable<ExposureSource>(EntranceConsts.KEY_EXPOSURE_SOURCE) != null) {
                listOf<ExposureSource>(requireArguments().getParcelable(EntranceConsts.KEY_EXPOSURE_SOURCE)!!)
            } else if (requireArguments().getParcelableArrayList<ExposureSource>(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST) != null) {
                requireArguments().getParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST)
            } else {
                null
            }
        val position = requireArguments().getInt(EntranceConsts.KEY_POSITION)
        val linkText = requireArguments().getString(EntranceConsts.KEY_NAME, "")
        val topTabIndex = requireArguments().getInt(EntranceConsts.KEY_TAB_INDEX, -1)
        val bottomTabIndex = requireArguments().getInt(EntranceConsts.KEY_BOTTOM_TAB_INDEX, -1)
        val precisePageLevelString = (activity as? IPageLevelProvider)
            ?.getPageLevel()
            ?.getTempNewPageLevel(topTabPosition = topTabIndex, bottomTabPosition = bottomTabIndex)
            ?.toFormattedString(ignoreBottomTabPositionMap = true)
            ?: ""
        val pageLocation = PageLocation(
            requireArguments().getString(EntranceConsts.KEY_BOTTOM_TAB_NAME, ""),
            bottomTabIndex,
            precisePageLevelString,
            requireArguments().getString(EntranceConsts.KEY_MULTI_TAB_NAV_NAME, ""),
            requireArguments().getString(EntranceConsts.KEY_MULTI_TAB_NAV_ID, ""),
            topTabIndex,
            requireArguments().getString(EntranceConsts.KEY_TAB_NAME, "")
        )
        return mAdapter ?: GameServerTestV2ListAdapter(
            requireContext(),
            this,
            mGameServerTestV2ViewModel,
            exposureSource,
            position,
            linkText,
            pageLocation
        ).apply {
            mAdapter = this
        }
    }

    override fun getItemDecoration(): RecyclerView.ItemDecoration? = null

    fun changeTimeFilter() {
        if (::mScrollCalculatorHelper.isInitialized) {
            mScrollCalculatorHelper.currentPlayer?.release()
        }
        NewFlatLogUtils.logGameTestDetailTimelineClick(
            "",
            "手动点击",
            mGameServerTestV2ViewModel?.selectedTimeFilterLiveData?.value ?: ""
        )
        mSupremeSelectedTimeFilter = mGameServerTestV2ViewModel?.getCurrentSelectedTimeFilter() ?: ""
        scrollToTime(mSupremeSelectedTimeFilter!!)
    }

    fun changeCategoryFilter() {
        if (::mScrollCalculatorHelper.isInitialized) {
            mScrollCalculatorHelper.currentPlayer?.release()
        }
        onLoadRefresh()
        val selectedCategoryFilter = mGameServerTestV2ViewModel?.getCategoryFilterString() ?: ""
        NewFlatLogUtils.logGameTestDetailGameCategoryClick(
            "",
            selectedCategoryFilter,
            mGameServerTestV2ViewModel?.selectedTimeFilterLiveData?.value ?: "",
            true
        )
    }

    fun changeBigImageMode() {
        if (::mScrollCalculatorHelper.isInitialized) {
            mScrollCalculatorHelper.currentPlayer?.release()
        }
        onLoadRefresh()
    }

    override fun onFragmentResume() {
        resumeVideo()
        DownloadManager.getInstance().addObserver(dataWatcher)
        super.onFragmentResume()
    }

    override fun onFragmentPause() {
        pauseVideo()
        DownloadManager.getInstance().removeObserver(dataWatcher)
        super.onFragmentPause()
        val firstVisibleItemPosition = mLayoutManager?.findFirstVisibleItemPosition() ?: -1
        if (firstVisibleItemPosition >= 0) {
            val testTime = mListViewModel.obsListData.value?.safelyGetInRelease(firstVisibleItemPosition)?.testTime ?: 0
            val stayTime = (System.currentTimeMillis() - startPageTime) / 1000
            NewFlatLogUtils.logGameTestDetailView(
                "",
                stayTime,
                testTime,
                mGameServerTestV2ViewModel?.selectedTimeFilterLiveData?.value ?: ""
            )
        }
    }

    //下载被删除事件
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(status: EBDownloadStatus) {
        DownloadManager.getInstance().removePlatform(status.name, status.platform)
        if (status.status == "delete") {
            mListViewModel?.locationMap?.get(status.packageName)?.let {
                for (location in it) {
                    mListViewModel?.obsListData?.value?.safelyGetInRelease(location)?.game?.getEntryMap()
                        ?.remove(status.platform)
                    mAdapter?.notifyItemChanged(location)
                }
            }
        }
    }

    private fun pauseVideo() {
        val currentPlayer = mScrollCalculatorHelper.currentPlayer
        if (currentPlayer != null) {
            currentPlayer.resetDetailMask()
            currentPlayer.onVideoPause()
            val currentPosition = currentPlayer.getCurrentPosition()
            val videoUrl = currentPlayer.getUrl()
            if (videoUrl.isNotEmpty()) {
                ScrollCalculatorHelper.savePlaySchedule(MD5Utils.getContentMD5(videoUrl), currentPosition)
            }
        }
    }

    private fun resumeVideo() {
        val currentPlayer = mScrollCalculatorHelper.currentPlayer
        if (currentPlayer != null) {
            val videoUrl = currentPlayer.getUrl()
            if (videoUrl.isNotEmpty()) {
                val position = ScrollCalculatorHelper.getPlaySchedule(MD5Utils.getContentMD5(videoUrl))
                //这里必须要延迟操作，否则会白屏
                mBaseHandler.postDelayed({
                    if (position != 0L) {
                        mScrollCalculatorHelper.currentPlayer?.seekTo(position)
                        mScrollCalculatorHelper.currentPlayer?.onVideoResume(false)
                        val topVideoVoiceStatus = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
                        if (topVideoVoiceStatus) {
                            mScrollCalculatorHelper.currentPlayer?.mute()
                        } else {
                            mScrollCalculatorHelper.currentPlayer?.unMute()
                        }
                    } else {
                        mScrollCalculatorHelper.currentPlayer?.release()
                    }

                }, 50)
            }
        }
    }

    override fun onChanged(ts: MutableList<GameServerTestV2ListViewModel.ItemData>?) {
        super.onChanged(ts)
        if (!ts.isNullOrEmpty() && mListViewModel.isLoadFirstPage) {
            scrollToTime(GameServerTestV2ViewModel.TimeFilter.TODAY.value)
            mListRv?.postDelayed({
                scroll()
                mScrollCalculatorHelper.onScrollStateChanged(RecyclerView.SCROLL_STATE_IDLE)
            }, 200)
        }
    }

    private fun scrollToTime(timeFilter: String) {
        val positionToScroll = mListViewModel!!.getPositionByTimeFilter(timeFilter)
        if (positionToScroll < 0) return
        val itemData = mListViewModel.getItemAtPosition(positionToScroll)
        val offset = if (itemData?.isTopGames == true || positionToScroll == 0) 0 else TOP_DATE_CONTAINER_OFFSET.dip2px()
        mBinding?.topDateContainer?.isVisible = itemData?.isTopGames == false

        mLayoutManager.scrollToPositionWithOffset(positionToScroll, offset)
        mListRv?.post {
            mLayoutManager.scrollToPositionWithOffset(positionToScroll, offset)
            if (mListViewModel.isLoadFirstPage) {
                mListRv?.post {
                    val firstVisibleItemPosition = mLayoutManager.findFirstVisibleItemPosition()
                    showPullDownTip(firstVisibleItemPosition > 0)
                    mListViewModel.isLoadFirstPage = false
                }
            }
        }
    }

    override fun onLoadError() {
        super.onLoadError()
        mBinding?.topDateContainer?.visibility = View.GONE
        showPullDownTip(false)
    }

    override fun onLoadEmpty() {
        super.onLoadEmpty()
        mBinding?.topDateContainer?.visibility = View.GONE
        showPullDownTip(false)
    }

    private fun showPullDownTip(show: Boolean) {
        (parentFragment as? GameServerTestV2Fragment)?.showPullDownTip(show)
    }

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

    override fun onDarkModeChanged() {
        super.onDarkModeChanged()
        mBinding?.topDate?.root?.background = R.drawable.bg_game_server_test_v2_filter_gradient_bottom.toDrawable(requireContext())
    }

    companion object {
        private const val TOP_DATE_CONTAINER_OFFSET = -16F
    }
}