package com.gh.gamecenter.servers.gametest2

import android.os.Bundle
import android.view.View
import android.widget.FrameLayout
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.utils.goneIf
import com.gh.gamecenter.common.utils.safelyGetInRelease
import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.common.utils.viewModelProviderFromParent
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.exposure.ExposureSource
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
import com.halo.assistant.HaloApp
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

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 mTabFilterValue: String = ""
    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 {
        return viewModelProvider(
            GameServerTestV2ListViewModel.Factory(
                HaloApp.getInstance(),
                mGameServerTestV2ViewModel
            )
        )
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        mGameServerTestV2ViewModel = viewModelProviderFromParent()
        val filter = requireArguments().getString(EntranceConsts.KEY_FILTER, "")
        mTabFilterValue = if (filter == GameServerTestV2ViewModel.TestFilter.RECOMMEND.value) {
            "推荐"
        } else {
            "全部"
        }
        super.onCreate(savedInstanceState)
    }


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

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

    override fun initSkeletonScreen() {
        mSkeletonScreen = Skeleton.bind(mBinding?.skeleton)
            .shimmer(true)
            .angle(Constants.SHIMMER_ANGLE)
            .color(R.color.skeleton_shimmer_color)
            .duration(Constants.SHIMMER_DURATION)
            .maskWidth(Constants.MASK_WIDTH)
            .gradientCenterColorWidth(Constants.GRADIENT_CENTER_COLOR_WIDTH)
            .load(R.layout.fragment_game_server_test_v2_skeleton)
            .show()
    }

    override fun onFragmentFirstVisible() {
        super.onFragmentFirstVisible()
        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
                if (layoutManager is LinearLayoutManager && !mListViewModel.obsListData.value.isNullOrEmpty()) {
                    val firstVisiblePosition = layoutManager.findFirstVisibleItemPosition()
                    val readableDaysOffset = mListViewModel.getReadableDaysOffset(firstVisiblePosition)
                    val currentTimeFilter = mGameServerTestV2ViewModel?.getSelectedTimeFilterString(readableDaysOffset)
                    if (mSupremeSelectedTimeFilter == null && currentTimeFilter?.isNotEmpty() == true) {
                        if (mGameServerTestV2ViewModel?.selectedTimeFilterLiveData?.value != currentTimeFilter) {
                            NewFlatLogUtils.logGameTestDetailTimelineClick(
                                mTabFilterValue,
                                "自动定位",
                                currentTimeFilter
                            )
                        }
                        mGameServerTestV2ViewModel?.selectedTimeFilterLiveData?.value = currentTimeFilter
                    }
                    if (!mListViewModel.isLoadFirstPage) {
                        mBinding?.pullDownTipIv?.visibility = View.GONE
                    }

                    // 悬挂的文案
                    mBinding?.topDateContainer?.root?.visibility = View.VISIBLE
                    mBinding?.topDateContainer?.timeTv?.text =
                        mListViewModel?.getDayTextByPosition(firstVisiblePosition)

                    // 悬挂界面移动
                    val lp = mBinding?.topDateContainer?.root?.layoutParams as FrameLayout.LayoutParams
                    if (firstVisiblePosition != 0
                        && mListViewModel?.getItemAtPosition(firstVisiblePosition + 1)?.time != null
                    ) {
                        val bottom = layoutManager.findViewByPosition(firstVisiblePosition)?.bottom ?: 0
                        if (bottom <= (mBinding?.topDateContainer?.root?.height ?: 0)) {
                            lp.topMargin = bottom - (mBinding?.topDateContainer?.root?.height ?: 0)
                        } else {
                            lp.topMargin = 0
                        }
                    } else {
                        lp.topMargin = 0
                    }
                    mBinding?.topDateContainer?.root?.layoutParams = lp
                    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 {
                null
            }
        val position = requireArguments().getInt(EntranceConsts.KEY_POSITION)
        return mAdapter ?: GameServerTestV2ListAdapter(
            requireContext(),
            mEntrance,
            mGameServerTestV2ViewModel,
            exposureSource,
            position
        ).apply {
            mAdapter = this
        }
    }

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

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

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

    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(
                mTabFilterValue,
                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
        mLayoutManager.scrollToPositionWithOffset(positionToScroll, 0)
        mListRv.post {
            mLayoutManager.scrollToPositionWithOffset(positionToScroll, 0)
            if (mListViewModel.isLoadFirstPage) {
                mListRv.post {
                    val firstVisibleItemPosition = mLayoutManager.findFirstVisibleItemPosition()
                    mBinding?.pullDownTipIv?.goneIf(firstVisibleItemPosition <= 0)
                    mListViewModel.isLoadFirstPage = false
                }
            }
        }
    }

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

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

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