package com.gh.gamecenter.amway

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.recyclerview.widget.RecyclerView
import com.ethanhua.skeleton.Skeleton
import com.gh.common.exposure.ExposureListener
import com.gh.gamecenter.feature.exposure.ExposureSource
import com.gh.common.util.DialogUtils
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.amway.search.AmwaySearchActivity
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.eventbus.EBReuse
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.VerticalItemDecoration
import com.gh.gamecenter.core.utils.ClickUtils
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.MtaHelper
import com.gh.gamecenter.core.utils.TimeElapsedHelper
import com.gh.gamecenter.databinding.FragmentAmwayAlBinding
import com.gh.gamecenter.databinding.FragmentAmwayBinding
import com.gh.gamecenter.entity.RatingComment
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.fragment.HomeSearchToolWrapperFragment
import com.gh.gamecenter.gamedetail.rating.RatingFragment
import com.google.android.material.appbar.AppBarLayout
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 AmwayFragment : LazyListFragment<AmwayListItemData, AmwayViewModel>() {

    private lateinit var mViewModel: AmwayViewModel
    private val mElapsedHelper by lazy { TimeElapsedHelper() }
    private lateinit var mExposureListener: ExposureListener

    private var mDefaultBinding: FragmentAmwayBinding? = null
    private var mAlternativeBinding: FragmentAmwayAlBinding? = null

    private var mAdapter: AmwayAdapter? = null

    private var mUseAlternativeLayout = false
    private var mIsCollapsed = false

    private val dataWatcher = object : DataWatcher() {
        override fun onDataChanged(downloadEntity: DownloadEntity) {
            mAdapter?.notifyItemByDownload(downloadEntity)

            if (downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS] == XapkUnzipStatus.FAILURE.name) {
                showUnzipFailureDialog(downloadEntity)
            }
        }

        override fun onDataInit(downloadEntity: DownloadEntity) {
            mAdapter?.notifyItemByDownload(downloadEntity)
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        mUseAlternativeLayout = arguments?.getBoolean(EntranceConsts.KEY_IS_HOME, false) ?: false
        super.onCreate(savedInstanceState)
    }

    override fun getStubLayoutId() = R.layout.fragment_stub

    override fun getRealLayoutId(): Int {
        return if (mUseAlternativeLayout) R.layout.fragment_amway_al else R.layout.fragment_amway
    }

    override fun onFragmentFirstVisible() {
        super.onFragmentFirstVisible()

        mViewModel.fixedTopAmwayId = arguments?.getString(EntranceConsts.KEY_ID)
        mViewModel.initData()
        mViewModel.entrance = mEntrance
    }

    override fun onRealLayoutInflated(inflatedView: View) {
        super.onRealLayoutInflated(inflatedView)
        if (mUseAlternativeLayout) {
            mAlternativeBinding = FragmentAmwayAlBinding.bind(inflatedView)
        } else {
            mDefaultBinding = FragmentAmwayBinding.bind(inflatedView)
        }
    }

    override fun initRealView() {
        super.initRealView()

        mExposureListener = ExposureListener(this, mAdapter!!)
        mListRv.addOnScrollListener(mExposureListener)

        if (!mUseAlternativeLayout) {
            initDefaultLayout()
        } else {
            initAlternativeLayout()
        }

        mListRefresh?.setOnRefreshListener {
            MtaHelper.onEvent("安利墙", "刷新")
            onLoadRefresh()
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if ((requestCode == RatingFragment.RATING_REPLAY_REQUEST || requestCode == RatingFragment.RATING_PATCH_REQUEST)
            && resultCode == Activity.RESULT_OK
        ) {
            data?.getParcelableExtra<RatingComment>(RatingComment::class.java.simpleName)?.let {
                mViewModel.handleResultUpdate(it)
            }
        }
    }

    override fun provideListViewModel(): AmwayViewModel {
        mViewModel = viewModelProvider()
        return mViewModel
    }

    override fun getItemDecoration() = VerticalItemDecoration(context, 12F, false)
        .apply { mItemDecoration = this }

    override fun provideListAdapter(): ListAdapter<*> {
        if (mAdapter == null) {
            val basicExposureSource = arrayListOf<ExposureSource>().apply {
                arguments?.getParcelable<ExposureSource>(EntranceConsts.KEY_EXPOSURE_SOURCE)?.let {
                    add(it)
                }
                add(ExposureSource("安利墙", ""))
            }
            mAdapter = AmwayAdapter(requireContext(), mViewModel, basicExposureSource, mLayoutManager)
        }
        return mAdapter!!
    }

    override fun isAutomaticLoad() = false

    private fun initDefaultLayout() {
        mDefaultBinding?.run {
            nightMaskView.goneIf(!mIsDarkModeOn)

            // toolbar 消费 fitsSystemWindows 避免在 collapsingToolbar 下面出现多出来的 padding
            // [https://stackoverflow.com/questions/48137666/viewgroup-inside-collapsingtoolbarlayout-show-extra-bottom-padding-when-set-fits]
            ViewCompat.setOnApplyWindowInsetsListener(appbar) { _, insets ->
                (toolbar.layoutParams as ViewGroup.MarginLayoutParams).topMargin = insets.systemWindowInsetTop
                insets.consumeSystemWindowInsets()
            }

            val collapsingTrigger = 66F.dip2px() + DisplayUtils.getStatusBarHeight(context?.resources)

            toolbar.setNavigationOnClickListener { requireActivity().finish() }

            collapsingToolbar.scrimVisibleHeightTrigger = collapsingTrigger
            collapsingToolbar.scrimShownAction = {
                mIsCollapsed = it
                DisplayUtils.setLightStatusBar(requireActivity(), !mIsDarkModeOn && it)
                if (it) {
                    titleTv.alpha = 1F
                    titleTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_black))
                    toolbar.setNavigationIcon(R.drawable.ic_bar_back)
                } else {
                    titleTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.white))
                    toolbar.navigationIcon =
                        ContextCompat.getDrawable(requireContext(), R.drawable.ic_toolbar_back_white)
                }
            }

            titleTv.setOnClickListener {
                if (ClickUtils.isFastDoubleClick(titleTv.id, 300)) {
                    scrollToTop()
                }
            }

            appbar.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { _, verticalOffset ->
                val absOffset = abs(verticalOffset)
                val invisibleOffset = DisplayUtils.dip2px(30F)

                if (absOffset <= invisibleOffset) {
                    titleTv.alpha = 1 - (absOffset.toFloat() / invisibleOffset)
                } else {
                    titleTv.alpha = 0F
                }

                mListRefresh?.isEnabled = absOffset <= 2
            })

            fab.setOnClickListener {
                MtaHelper.onEvent("发表评论", "进入", "上墙")
                ifLogin("安利墙") {
                    startActivity(AmwaySearchActivity.getIntent(requireContext()))
                    NewFlatLogUtils.logAmwayPasteClick()
                }
            }
        }

        mListRefresh?.setProgressViewOffset(
            false,
            0,
            118F.dip2px() + DisplayUtils.getStatusBarHeight(requireContext().resources)
        )
        mSkeletonScreen =
            Skeleton.bind(mDefaultBinding?.skeletonPlaceholder).shimmer(false).load(R.layout.fragment_amway_skeleton)
                .show()
    }

    private fun initAlternativeLayout() {
        mAlternativeBinding?.firstBackground?.goneIf(mIsDarkModeOn)
        mAlternativeBinding?.secondBackground?.goneIf(mIsDarkModeOn)
        mAlternativeBinding?.topBackgroundView?.goneIf(mIsDarkModeOn)
        mAlternativeBinding?.fab?.setOnClickListener {
            MtaHelper.onEvent("发表评论", "进入", "上墙")
            ifLogin("安利墙") {
                startActivity(AmwaySearchActivity.getIntent(requireContext()))
            }
        }
        mAlternativeBinding?.listRv?.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
                val scrollY = recyclerView.computeVerticalScrollOffset()
                mAlternativeBinding?.headerContainer?.translationY = -scrollY.toFloat()
                if (parentFragment is HomeSearchToolWrapperFragment && isSupportVisible) {
                    (parentFragment as HomeSearchToolWrapperFragment).onScrollChanged(
                        mAlternativeBinding?.headerContainer?.measuredHeight ?: 0,
                        scrollY
                    )
                }
            }
        })

        mSkeletonScreen = Skeleton.bind(mAlternativeBinding?.skeletonPlaceholder).shimmer(false)
            .load(R.layout.fragment_amway_skeleton_al).show()
    }

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

        mElapsedHelper.pauseCounting()
        MtaHelper.onEventWithTime("安利墙", mElapsedHelper.elapsedTime, "浏览")
    }

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

        mElapsedHelper.resetCounting()
        mElapsedHelper.resumeCounting()
    }

    private fun scrollToTop() {
        val firstItemPosition = mLayoutManager.findFirstVisibleItemPosition()
        if (firstItemPosition >= 10) {
            mListRv.scrollToPosition(6)
        }
        mListRv.smoothScrollToPosition(0)
        mDefaultBinding?.appbar?.setExpanded(true)
    }

    //下载被删除事件
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(status: EBDownloadStatus) {
        if ("delete" == status.status) {
            mAdapter?.notifyItemAndRemoveDownload(status)
        }
    }

    //安装、卸载事件
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(busFour: EBPackage) {
        val data = mAdapter?.getGameEntityByPackage(busFour.packageName) ?: arrayListOf()
        for (gameAndPosition in data) {
            mAdapter?.notifyChildItem(gameAndPosition.position)
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(reuse: EBReuse) {
        if ("Refresh" == reuse.type) {
            mAdapter?.notifyDataSetChanged()
        } else if (reuse.type == Constants.LOGIN_TAG) { // 登入
            scrollToTop()
            mViewModel.initData(false)
        }
    }

    fun showUnzipFailureDialog(downloadEntity: DownloadEntity) {
        val data = mAdapter?.getGameEntityByPackage(downloadEntity.packageName) ?: return
        for (gameAndPosition in data) {
            val targetView = mLayoutManager.findViewByPosition(gameAndPosition.position)
            if (targetView != null) {
                if (targetView is RecyclerView) {
                    // todo 如果时竖向专题该怎么判断?
                } else {
                    DialogUtils.showUnzipFailureDialog(requireContext(), downloadEntity)
                    return
                }
            }
        }
    }

    fun onScrollChanged() {
        if (parentFragment is HomeSearchToolWrapperFragment) {
            val scrollY = mAlternativeBinding?.listRv?.computeVerticalScrollOffset()
            if (scrollY != null) {
                mAlternativeBinding?.headerContainer?.translationY = -scrollY.toFloat()
                if (parentFragment is HomeSearchToolWrapperFragment && isSupportVisible) {
                    (parentFragment as HomeSearchToolWrapperFragment).onScrollChanged(
                        mAlternativeBinding?.headerContainer?.measuredHeight ?: 0,
                        scrollY
                    )
                }
            }
        }
    }

    override fun onDarkModeChanged() {
        super.onDarkModeChanged()
        mItemDecoration?.let { mListRv?.removeItemDecoration(it) }
        mListRv?.addItemDecoration(itemDecoration)
        mAdapter?.itemCount?.let { mAdapter?.notifyItemRangeChanged(0, it) }
        if (mUseAlternativeLayout) {
            mAlternativeBinding?.firstBackground?.goneIf(mIsDarkModeOn)
            mAlternativeBinding?.secondBackground?.goneIf(mIsDarkModeOn)
            mAlternativeBinding?.topBackgroundView?.goneIf(mIsDarkModeOn)
            mAlternativeBinding?.listRefresh?.setBackgroundColor(R.color.background.toColor(requireContext()))
            onScrollChanged()
        } else {
            mDefaultBinding?.nightMaskView?.goneIf(!mIsDarkModeOn)
            mDefaultBinding?.appbar?.setBackgroundColor(R.color.background_white.toColor(requireContext()))
            mDefaultBinding?.collapsingToolbar?.setContentScrimColor(R.color.background_white.toColor(requireContext()))
            mDefaultBinding?.listRefresh?.setBackgroundColor(R.color.background.toColor(requireContext()))
        }
    }
}