package com.gh.gamecenter.search

import android.app.Dialog
import android.os.Bundle
import android.text.SpannableString
import android.text.Spanned
import android.text.TextPaint
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.view.View
import android.view.animation.Animation
import android.view.animation.TranslateAnimation
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.exposure.DefaultExposureStateChangeListener
import com.gh.common.util.*
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.SearchActivity
import com.gh.gamecenter.SearchType
import com.gh.gamecenter.common.baselist.ListFragment
import com.gh.gamecenter.common.baselist.LoadType
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.entity.SuggestType
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.core.callback.AccelerateState
import com.gh.gamecenter.core.callback.OnAccelerateListener
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.MtaHelper
import com.gh.gamecenter.databinding.FragmentSearchResultBinding
import com.gh.gamecenter.db.SearchHistoryDao
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.eventbus.EBStartupAcceleration
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.addExposureHelper
import com.gh.gamecenter.feature.entity.VipEntity
import com.gh.gamecenter.help.HelpAndFeedbackBridge
import com.gh.gamecenter.livedata.EventObserver
import com.gh.gamecenter.minigame.MiniGameSearchResultFragment
import com.gh.gamecenter.search.viewmodel.SearchTabViewModel
import com.halo.assistant.HaloApp
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import com.lightgame.utils.Util_System_Keyboard
import com.therouter.TheRouter
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

open class SearchGameResultFragment : ListFragment<GameEntity, SearchGameResultViewModel>() {

    private val parentTabViewModel by viewModels<SearchTabViewModel>(
        ownerProducer = { parentFragment ?: this }
    )

    // 上一次搜索的关键字和时间
    private var previousSearchedPair: Pair<String, Long> = Pair("", 0)

    private var mAdapter: SearchGameResultAdapter? = null
    private lateinit var mShowAction: Animation
    private lateinit var mHideAction: Animation
    private var mIsFirstLoad = true
    private val mBinding by lazy { FragmentSearchResultBinding.inflate(layoutInflater) }

    protected var mKey: String = ""
    private var mType: String = ""
    private var mLoadingAnimation = false
    private var mScrollIng = false
    private var mIsAutoLoad = true

    private var iAcceleratorProvider = TheRouter.get(IAcceleratorProvider::class.java)

    private var refreshVipLoadingDialog: Dialog? = null
    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)
        }
    }

    private val onAccelerateListener = object : OnAccelerateListener {
        override fun onStateChanged(state: AccelerateState) {
            if (state is AccelerateState.Success || state is AccelerateState.Normal) {
                mAdapter?.notifyItemAccelerationState()
            }
        }

        override fun onProgress(progress: Int, curGamePkgName: String?, curGameZoneFlag: String?) = Unit
    }

    private val onDataHolderListener = object : AcceleratorDataHolder.OnDataHolderListener {
        override fun onVipStateChanged() {
            // vip 状态刷新完毕
            mListViewModel.showRefreshVipLoading(false)
            // 刷新页面内每个item的 vip状态
            mAdapter?.notifyDataSetChanged()

        }

    }

    override fun isAutomaticLoad(): Boolean {
        return mIsAutoLoad
    }

    override fun getLayoutId() = 0
    override fun getInflatedLayout() = mBinding.root

    override fun provideListViewModel() =
        viewModelProvider<SearchGameResultViewModel>(
            SearchGameResultViewModel.Factory(
                HaloApp.getInstance(),
                mKey,
                true,
                SearchGameResultRepository(),
                mType,
                activity?.intent?.getStringExtra(EntranceConsts.KEY_SOURCE_ENTRANCE) ?: "",
            )
        )

    override fun provideListAdapter(): SearchGameResultAdapter {
        if (mAdapter == null) {
            mAdapter =
                SearchGameResultAdapter(
                    requireContext(),
                    this,
                    (activity as? SearchActivity)?.mDao ?: SearchHistoryDao(requireContext()),
                    mListViewModel,
                    mEntrance,
                    mType,
                    mListViewModel.sourceEntrance
                ).apply { key = mKey }
        }
        return mAdapter!!
    }

    override fun getItemDecoration() = null

    override fun onCreate(savedInstanceState: Bundle?) {
        if (savedInstanceState != null) {
            mKey = savedInstanceState.getString(EntranceConsts.KEY_SEARCHKEY) ?: ""
            mType = savedInstanceState.getString(SearchActivity.KEY_SEARCH_TYPE) ?: ""
        }
        mIsAutoLoad = arguments?.getBoolean(EntranceConsts.KEY_IS_AUTO_LOAD, true) ?: true
        super.onCreate(savedInstanceState)
        mListRefresh?.isEnabled = false
        mBinding.reuseNoneData.reuseNoneDataDescTv.visibility = View.VISIBLE
        mBinding.reuseNoneData.reuseNoneDataTv.setText("没有找到你的游戏~")
        mBinding.reuseNoneData.reuseNoneData.setBackgroundColor(
            com.gh.gamecenter.common.R.color.ui_surface.toColor(
                requireContext()
            )
        )
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        mBinding.reuseNoneData.reuseNoDataSkipFunctionTv.visibility = View.VISIBLE
        mBinding.reuseNoneData.reuseNoDataSkipGameTv.visibility = View.VISIBLE
        arrayListOf(
            mBinding.reuseNoneData.reuseNoDataSkipFunctionTv,
            mBinding.reuseNoneData.reuseNoDataSkipGameTv,
            mBinding.containerMenuClose,
            mBinding.containerMenuOpen,
            mBinding.seekFunctionBtn,
            mBinding.seekGameBtn
        ).forEach {
            it.setOnClickListener(this)
        }

        mListRv.addExposureHelper(this, DefaultExposureStateChangeListener())
        mListRv!!.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    mScrollIng = false
                    mBinding.containerMenuClose.alpha = 1F
                } else {
                    mScrollIng = true
                    if (mBinding.containerMenuClose.visibility == View.VISIBLE) {
                        mBinding.containerMenuClose.alpha = 0.5F
                    } else {
                        mBinding.containerMenuClose.postDelayed({
                            mBinding.containerMenuClose.alpha = 0.5F
                        }, 300)
                    }
                }
            }

            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                if (mIsFirstLoad) {
                    mIsFirstLoad = false
                    val position = mLayoutManager?.findLastVisibleItemPosition()
                    if (position == (mAdapter?.itemCount ?: 0) - 1) {
                        val child = mLayoutManager?.findViewByPosition(position)
                        if (child != null && recyclerView.bottom - child.bottom > -DisplayUtils.dip2px(50F) && mAdapter?.isLoadOver() == true) {
                            return
                        }
                    }
                    mBinding.containerMenuOpen.visibility = View.VISIBLE
                    mBinding.seekGameBtn.visibility = View.VISIBLE
                    mBinding.seekFunctionBtn.visibility = View.VISIBLE
                    return
                }
                if (mBinding.containerMenuOpen.visibility == View.VISIBLE && !mLoadingAnimation) {
                    showCloseMenuView()
                }
                handleCloseMenuVisibility(recyclerView)
            }
        })

        initAnimation()

        parentTabViewModel.searchKeyAndType.observe(viewLifecycleOwner) { (key, type) ->
            setParams(key, type)
        }



        if (this !is MiniGameSearchResultFragment) {
            // 只有普通游戏搜索支持加速
            mListViewModel.refreshVipLoading.observe(viewLifecycleOwner, EventObserver {
                if (it) {
                    refreshVipLoadingDialog = DialogUtils.showWaitDialog(requireContext(), "数据刷新中...")
                } else {
                    refreshVipLoadingDialog?.dismiss()
                }
            })

            iAcceleratorProvider?.bindAccRelatedListener("", onAccelerateListener)

            AcceleratorDataHolder.instance.addListener(onDataHolderListener)
        }


    }

    private fun handleCloseMenuVisibility(recyclerView: RecyclerView) {
        val position = mLayoutManager!!.findLastVisibleItemPosition()
        if (position == mAdapter!!.itemCount - 1) {
            val child = mLayoutManager!!.findViewByPosition(position)
            if (child != null && recyclerView.bottom - child.bottom > -DisplayUtils.dip2px(50F) && mAdapter?.isLoadOver() == true) {
                mBinding.containerMenuClose.visibility = View.GONE
            } else {
                mBinding.containerMenuClose.visibility = View.VISIBLE
            }
        } else {
            if (!mLoadingAnimation) mBinding.containerMenuClose.visibility = View.VISIBLE
        }
    }

    private fun initAnimation() {
        mShowAction = TranslateAnimation(
            Animation.RELATIVE_TO_SELF,
            1.0F, Animation.RELATIVE_TO_SELF, 0.0F,
            Animation.RELATIVE_TO_SELF, 0.0F, Animation.RELATIVE_TO_SELF,
            0.0F
        )
        mShowAction.duration = 300
        mShowAction.setAnimationListener(object : Animation.AnimationListener {
            override fun onAnimationStart(animation: Animation?) {
                mLoadingAnimation = true
                mBinding.containerMenuClose.background = null
                mBinding.blank.visibility = View.VISIBLE
                mBinding.menuView.setImageResource(R.drawable.ic_search_menu_selected)
            }

            override fun onAnimationRepeat(animation: Animation?) {}

            override fun onAnimationEnd(animation: Animation?) {
                mLoadingAnimation = false
                mBinding.containerMenuClose.visibility = View.GONE
                mBinding.seekFunctionBtn.postDelayed({
                    mBinding.seekFunctionBtn.visibility = View.VISIBLE
                }, 100)
                mBinding.seekGameBtn.postDelayed({
                    mBinding.seekGameBtn.visibility = View.VISIBLE
                }, 130)
            }
        })

        mHideAction = TranslateAnimation(
            Animation.RELATIVE_TO_SELF,
            0.0F, Animation.RELATIVE_TO_SELF, 1.0F,
            Animation.RELATIVE_TO_SELF, 0.0F, Animation.RELATIVE_TO_SELF,
            0.0F
        )
        mHideAction.duration = 300
        mHideAction.setAnimationListener(object : Animation.AnimationListener {
            override fun onAnimationStart(animation: Animation?) {
                mLoadingAnimation = true

                mBinding.containerMenuClose.visibility = View.VISIBLE
                mBinding.seekGameBtn.visibility = View.INVISIBLE
                mBinding.seekFunctionBtn.visibility = View.INVISIBLE
                mBinding.containerMenuClose.postDelayed({
                    mBinding.blank.visibility = View.GONE
                    mBinding.containerMenuClose.setBackgroundResource(R.drawable.bg_search_menu)
                    mBinding.menuView.setImageResource(R.drawable.ic_search_menu_unselect)
                    mBinding.containerMenuOpen.visibility = View.GONE
                }, 200)
            }

            override fun onAnimationRepeat(animation: Animation?) {}

            override fun onAnimationEnd(animation: Animation?) {
                mLoadingAnimation = false
            }
        })
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)

        outState.putString(EntranceConsts.KEY_SEARCHKEY, mKey)
        outState.putString(SearchActivity.KEY_SEARCH_TYPE, mType)
        outState.putBoolean(EntranceConsts.KEY_IS_AUTO_LOAD, mIsAutoLoad)
    }

    private fun showOpenMenuView() {
        mBinding.containerMenuOpen.startAnimation(mShowAction)
        mBinding.containerMenuOpen.visibility = View.VISIBLE
    }

    private fun showCloseMenuView() {
        mBinding.containerMenuOpen.startAnimation(mHideAction)
    }

    override fun onClick(view: View) {
        when (view.id) {
            com.gh.gamecenter.common.R.id.reuseNoDataSkipFunctionTv -> {
                Util_System_Keyboard.hideSoftKeyboard(requireActivity())
                MtaHelper.onEvent("游戏搜索", "求功能", mKey)
                LogUtils.uploadSearchGame("ask_more_func", "搜索页", mKey, SearchType.fromString(mType).toChinese())
                HelpAndFeedbackBridge.startSuggestionActivity(context, SuggestType.FUNCTION, "", "求功能：$mKey")
            }

            com.gh.gamecenter.common.R.id.reuseNoDataSkipGameTv -> {
                Util_System_Keyboard.hideSoftKeyboard(requireActivity())
                MtaHelper.onEvent("游戏搜索", "求游戏", mKey)
                LogUtils.uploadSearchGame("ask_more_games", "搜索页", mKey, SearchType.fromString(mType).toChinese())
                HelpAndFeedbackBridge.startSuggestionActivity(context, SuggestType.UPDATE, "", "求游戏：$mKey")
            }

            R.id.container_menu_close -> {
                if (mScrollIng) return
                LogUtils.uploadSearchGame(
                    "open_floating_window",
                    "搜索页",
                    mKey,
                    SearchType.fromString(mType).toChinese()
                )
                showOpenMenuView()
            }

            R.id.container_menu_open -> {
                if (mScrollIng) return
                LogUtils.uploadSearchGame(
                    "close_floating_window",
                    "搜索页",
                    mKey,
                    SearchType.fromString(mType).toChinese()
                )
                showCloseMenuView()
            }

            R.id.seek_game_btn -> {
                Util_System_Keyboard.hideSoftKeyboard(requireActivity())
                MtaHelper.onEvent("游戏搜索", "求游戏", mKey)
                LogUtils.uploadSearchGame(
                    "ask_more_games",
                    " 搜索页-悬浮按钮",
                    mKey,
                    SearchType.fromString(mType).toChinese()
                )
                HelpAndFeedbackBridge.startSuggestionActivity(context, SuggestType.UPDATE, "", "求游戏：$mKey")
                showCloseMenuView()
            }

            R.id.seek_function_btn -> {
                Util_System_Keyboard.hideSoftKeyboard(requireActivity())
                MtaHelper.onEvent("游戏搜索", "求功能", mKey)
                LogUtils.uploadSearchGame(
                    "ask_more_func",
                    " 搜索页-悬浮按钮",
                    mKey,
                    SearchType.fromString(mType).toChinese()
                )
                HelpAndFeedbackBridge.startSuggestionActivity(context, SuggestType.FUNCTION, "", "求功能：$mKey")
                showCloseMenuView()
            }
        }
    }

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

        mListViewModel.refreshWrongInstallStatus()
    }

    override fun onPause() {
        super.onPause()
        DownloadManager.getInstance().removeObserver(dataWatcher)
        if (mBinding.containerMenuOpen.visibility == View.VISIBLE) {
            showCloseMenuView()
        }
    }

    override fun onLoadEmpty() {
        super.onLoadEmpty()
        showAd(mBinding.reuseNoneData.reuseNoneDataDescTv, false)

        NewLogUtils.logSearchEmpty(SearchType.fromString(mType).toChinese(), mKey)
    }

    fun setParams(key: String, type: String) {
        this.mType = type
        mAdapter?.type = type
        mListViewModel?.updateSearchKeyWithType(key, type)

        if (key == previousSearchedPair.first
            && System.currentTimeMillis() - previousSearchedPair.second < 300L
        ) {
            return
        }

        previousSearchedPair = Pair(key, System.currentTimeMillis())

        this.mKey = key
        mAdapter?.key = key
        mAdapter?.clearAdIdSet()
        mListViewModel?.clearSearchSubjects()
        mListViewModel?.load(LoadType.REFRESH)
    }

    fun showAd(view: TextView?, isSearchList: Boolean) {
        if (isSearchList) {
            view?.visibility = View.GONE
            return
        } else {
            view?.visibility = View.VISIBLE
        }

        val ad = AdHelper.getAd(AdHelper.LOCATION_SEARCH_EMPTY) ?: return
        val spannableString = SpannableString(ad.title)
        val clickableSpan = object : ClickableSpan() {
            override fun onClick(widget: View) {
                MtaHelper.onEvent("广告位统计", "搜索结果为空", ad.title)
                MtaHelper.onEvent("游戏搜索", ad.title, mKey)
                LogUtils.uploadSearchGame("click_ad", " 搜索页", mKey, SearchType.fromString(mType).toChinese())
                DirectUtils.directToLinkPage(requireContext(), ad.toLinkEntity(), "(搜索结果为空-广告位)", "")
            }

            override fun updateDrawState(paint: TextPaint) {
                paint.isUnderlineText = false
                paint.color = ContextCompat.getColor(requireContext(), com.gh.gamecenter.common.R.color.primary_theme)
            }
        }
        val tempString = spannableString.toString()
        val start = tempString.indexOf(ad.title!!)
        spannableString.setSpan(clickableSpan, start, spannableString.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        view?.movementMethod = LinkMovementMethod.getInstance()
        view?.text = spannableString
    }

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

    // 安装/卸载 事件
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(busFour: EBPackage) {
        if (!busFour.fromInit && busFour.isInstalledOrUninstalled()) {
            mAdapter?.notifyDataSetChanged()
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(startupAcceleration: EBStartupAcceleration) {
        mAdapter?.notifyItemAndStartupAcceleration(startupAcceleration)
    }

    fun showUnzipFailureDialog(downloadEntity: DownloadEntity) {
        val data = mAdapter?.positionAndPackageMap ?: return
        for (gameAndPosition in data) {
            if (gameAndPosition.key.contains(downloadEntity.packageName)) {
                val targetView = mLayoutManager.findViewByPosition(gameAndPosition.value)
                if (targetView != null) {
                    DialogUtils.showUnzipFailureDialog(requireContext(), downloadEntity)
                    return
                }
            }
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        iAcceleratorProvider?.unBindAccRelatedListener(onAccelerateListener)
        AcceleratorDataHolder.instance.removeListener(onDataHolderListener)
    }
}