package com.gh.gamecenter.download

import android.graphics.Color
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView
import com.gh.ad.AdDelegateHelper
import com.gh.common.util.HomePluggableHelper
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.PackageHelper
import com.gh.common.util.PackageInstaller
import com.gh.download.DownloadManager
import com.gh.gamecenter.DownloadManagerActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.BaseFragment_TabLayout
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.eventbus.EBMiPush
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.databinding.FragmentDownloadBinding
import com.gh.gamecenter.databinding.TabItemDownloadNumberBinding
import com.gh.gamecenter.entity.AdConfig
import com.gh.gamecenter.entity.HomePluggableFilterEntity
import com.gh.gamecenter.eventbus.EBDownloadChanged
import com.gh.gamecenter.eventbus.EBSkip
import com.gh.gamecenter.eventbus.EBUISwitch
import com.gh.gamecenter.feature.entity.PluginLocation
import com.gh.gamecenter.manager.PackagesManager
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.lang.ref.WeakReference

class DownloadFragment : BaseFragment_TabLayout() {

    // 下载 tab 是否被手动选中过
    private var mIsDownloadTabHasBeenSelected: Boolean = false
    private var mIsUpdateTabHasBeenSelected: Boolean = false

    private lateinit var mDownloadNumberTv: TextView
    private lateinit var mUpdateNumberTv: TextView
    private val mDownloadManager: DownloadManager by lazy { DownloadManager.getInstance() }

    private var mPermanentInactivePluggableApkList: List<HomePluggableFilterEntity>? = null

    private val mBinding by lazy { FragmentDownloadBinding.inflate(layoutInflater) }

    private val mAdGameBannerLayoutManager by lazy {
        LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false)
    }
    private val mAdGameBannerSnapHelper by lazy {
        PagerSnapHelper()
    }
    private var mAdGameBannerAdapter: AdGameBannerAdapter? = null
    private var mAdGameViewModel: AdGameViewModel? = null
    private val mAdLooperHandler = LooperHandler(this)
    private val mSlideLooperKey = 200
    private var mSlideInterval = -1

    private val mDataWatcher = object : DataWatcher() {
        override fun onDataChanged(downloadEntity: DownloadEntity) {
            mAdGameBannerAdapter?.notifyItemByDownload(downloadEntity)
        }

        override fun onDataInit(downloadEntity: DownloadEntity) {
            onDataChanged(downloadEntity)
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        SensorsBridge.trackDownloadManagerEnter(
            mEntrance,
            arguments?.getString(EntranceConsts.KEY_BOTTOM_TAB_NAME, "") ?: "",
            arguments?.getString(EntranceConsts.KEY_GAME_COLUMN_ID, "") ?: "",
            arguments?.getString(EntranceConsts.KEY_GAME_COLUMN_NAME, "") ?: "",
            arguments?.getString(EntranceConsts.KEY_CUSTOM_PAGE_ID, "") ?: "",
            arguments?.getString(EntranceConsts.KEY_CUSTOM_PAGE_NAME, "") ?: "",
            arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_ID, "") ?: "",
            arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_NAME, "") ?: ""
        )

        mPermanentInactivePluggableApkList = HomePluggableHelper.getPermanentInactivePluggablePackage()
    }

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

    override fun initFragmentList(fragments: MutableList<Fragment>) {
        fragments.add(GameDownloadFragment())
        fragments.add(UpdatableGameFragment())
        fragments.add(NewInstalledGameFragment())
    }

    override fun initTabTitleList(tabTitleList: MutableList<String>) {
        tabTitleList.add(getString(R.string.download_game))
        tabTitleList.add(getString(R.string.download_tab_update))
        tabTitleList.add(getString(R.string.download_tab_installed))
    }

    override fun provideTabView(position: Int, tabTitle: String): View? {
        val viewBinding = TabItemDownloadNumberBinding.inflate(LayoutInflater.from(context))
        var view: View? = viewBinding.root
        viewBinding.tabTitle.text = tabTitle

        when (position) {
            INDEX_DOWNLOAD -> mDownloadNumberTv = viewBinding.tabDownloadNumber
            INDEX_UPDATE -> mUpdateNumberTv = viewBinding.tabDownloadNumber
            else -> view = null
        }
        return view
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        setNavigationTitle(getString(R.string.title_downloadmanager))
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        updateUpdateHint()
        updateDownloadHint()

        if (mDownloadNumberTv.visibility != View.VISIBLE && mUpdateNumberTv.visibility == View.VISIBLE) {
            mViewPager.currentItem = INDEX_UPDATE
        } else {
            // 进入并选中下载管理时立马标记已下载待安装为已读
            mIsDownloadTabHasBeenSelected = true
            updateDownloadHint()
            mDownloadManager.markDownloadingTaskAsRead()
            mDownloadManager.markDownloadedTaskAsRead()
        }

        if (AdDelegateHelper.shouldShowDownloadManagerAd()) {
            val downloadManagerAd = AdDelegateHelper.getDownloadManagerAd()
            val showThirdPartyAd = downloadManagerAd?.displayRule?.adSource == AdDelegateHelper.AD_TYPE_SDK
            val showOwnerAd = downloadManagerAd?.displayRule?.adSource == AdDelegateHelper.AD_TYPE_OWNER
            val thirdPartyAd = downloadManagerAd?.thirdPartyAd
            val ownerAd = downloadManagerAd?.ownerAd
            val showOnFailed = downloadManagerAd?.displayRule?.onFailedAction == "show"
            if ((showThirdPartyAd && thirdPartyAd != null) || (!showThirdPartyAd && thirdPartyAd != null && ownerAd == null)) {
                initThirdPartyAd(downloadManagerAd, thirdPartyAd) { isSuccess ->
                    if (!isAdded) return@initThirdPartyAd
                    mBinding.maskView.goneIf(!isSuccess)
                    if (!isSuccess && ownerAd != null && showOnFailed) {
                        mSlideInterval = ownerAd.adSource?.sliderInterval ?: -1
                        initOwnerAd(downloadManagerAd)
                    }
                    if (isSuccess) {
                        SPUtils.setLong(Constants.SP_LAST_DOWNLOAD_MANAGER_AD_SHOW_TIME, System.currentTimeMillis())
                    }
                }
            } else if ((showOwnerAd && ownerAd != null) || (showThirdPartyAd && ownerAd != null && showOnFailed)) {
                mSlideInterval = ownerAd.adSource?.sliderInterval ?: -1
                initOwnerAd(downloadManagerAd)
            }
        }

        val pathOfPackageToInstall = activity?.intent?.getStringExtra(KEY_PATH_OF_PACKAGE_TO_INSTALL)
        if (!TextUtils.isEmpty(pathOfPackageToInstall)) {
            PackageInstaller.install(requireContext(), false, pathOfPackageToInstall)
        }
    }

    private fun initThirdPartyAd(adConfig: AdConfig?, thirdPartyAd: AdConfig.ThirdPartyAd, callback: (isSuccess: Boolean) -> Unit) {
        val onAdShowAction = {
            SensorsBridge.trackEvent("ThirdPartyAdShow",
                "ad_source", thirdPartyAd.sourceName,
                "ad_id", thirdPartyAd.slotId,
                "ad_format", adConfig?.typeChinese ?: "",
                "ad_placement", "下载管理",
                "ad_space_id", adConfig?.id ?: "",
                "ad_space_name", adConfig?.name ?: ""
            )
        }
        val onAdClickAction = {
            SensorsBridge.trackEvent("ThirdPartyAdClick",
                "ad_source", thirdPartyAd.sourceName,
                "ad_id", thirdPartyAd.slotId,
                "ad_format", adConfig?.typeChinese ?: "",
                "ad_placement", "下载管理",
                "ad_space_id", adConfig?.id ?: "",
                "ad_space_name", adConfig?.name ?: ""
            )
        }
        AdDelegateHelper.requestThirdPartyBannerAd(
            this,
            mBinding.adContainer,
            thirdPartyAd,
            DisplayUtils.getScreenWidthInDp(requireActivity()),
            onAdShowAction,
            onAdClickAction,
            callback
        )
    }

    private fun initOwnerAd(adConfig: AdConfig) {
        if (!isAdded || adConfig.id.isEmpty()) return
        mAdGameViewModel = viewModelProvider(AdGameViewModel.Factory(adConfig))
        initAdGameBanner(adConfig)
        mBinding.closeAdIv.setOnClickListener {
            NewFlatLogUtils.logCloseGameAd(
                adConfig.id,
                adConfig.name,
                "下载管理",
                adConfig.typeChinese,
                adConfig.ownerAd?.id ?: "",
                adConfig.ownerAd?.sourceName ?: ""
            )
            mBinding.adGameItemContainer.visibility = View.GONE
            mBinding.maskView.visibility = View.GONE
            DownloadManager.getInstance().removeObserver(mDataWatcher)
        }

        mAdGameViewModel?.gameListLiveData?.observe(viewLifecycleOwner) {
            mBinding.maskView.goneIf(it.isNullOrEmpty())
            mBinding.adGameItemContainer.goneIf(it.isNullOrEmpty()) {
                DownloadManager.getInstance().addObserver(mDataWatcher)
                mAdGameBannerAdapter?.run {
                    submitList(it)
                    if (it.size > 1) {
                        mBinding.adGameBannerRv.scrollToPosition(getActualFirstPositionInCenter())
                    }
                }
                startAdBannerAutoPlay()
                SPUtils.setLong(Constants.SP_LAST_DOWNLOAD_MANAGER_AD_SHOW_TIME, System.currentTimeMillis())
            }
            if (it.isNullOrEmpty() && adConfig.displayRule.adSource == AdDelegateHelper.AD_TYPE_OWNER &&
                adConfig.displayRule.onFailedAction == "show" && adConfig.thirdPartyAd != null) {
                // 自有广告游戏为空时，显示第三方广告
                initThirdPartyAd(adConfig, adConfig.thirdPartyAd) { isSuccess ->
                    if (!isAdded) return@initThirdPartyAd
                    mBinding.maskView.goneIf(!isSuccess)
                    if (isSuccess) {
                        SPUtils.setLong(Constants.SP_LAST_DOWNLOAD_MANAGER_AD_SHOW_TIME, System.currentTimeMillis())
                    }
                }
            }
        }
    }

    private fun initAdGameBanner(adConfig: AdConfig) {
        mBinding.adGameBannerRv.run {
            mAdGameBannerAdapter = AdGameBannerAdapter(
                requireContext(),
                adConfig,
                mAdGameBannerSnapHelper,
                mAdGameBannerLayoutManager,
                "下载管理"
            )
            adapter = mAdGameBannerAdapter
            layoutManager = mAdGameBannerLayoutManager
            isNestedScrollingEnabled = false
            (itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
            mAdGameBannerSnapHelper.attachToRecyclerView(this)
            addOnItemTouchListener(object : RecyclerView.SimpleOnItemTouchListener() {
                override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
                    val isStop = e.action == MotionEvent.ACTION_DOWN || e.action == MotionEvent.ACTION_MOVE
                    if (isStop) stopAdBannerAutoPlay() else startAdBannerAutoPlay()
                    return false
                }
            })
        }
    }

    override fun onPause() {
        super.onPause()
        DownloadManager.getInstance().removeObserver(mDataWatcher)
    }

    override fun onResume() {
        super.onResume()

        if (mViewPager.currentItem == INDEX_DOWNLOAD) {
            mDownloadManager.markDownloadingTaskAsRead()
            mDownloadManager.markDownloadedTaskAsRead()
            updateDownloadHint()
        }
        DownloadManager.getInstance().checkAndRetryDownload(false)
        if (mBinding.adGameItemContainer.isVisible) {
            DownloadManager.getInstance().addObserver(mDataWatcher)
        }

        refreshInstallStatus()
    }

    private fun refreshInstallStatus() {
        PackageHelper.refreshWrongInstallStatus(PackagesManager.getInstalledSet())
    }

    override fun onParentActivityFinish() {
        super.onParentActivityFinish()

        // onDestroy 的回调有点晚，不能及时更新外部红点
        if (mIsDownloadTabHasBeenSelected || mViewPager.currentItem == INDEX_DOWNLOAD) {
            mDownloadManager.markDownloadingTaskAsRead()
            mDownloadManager.markDownloadedTaskAsRead()
        }
    }

    override fun onPageSelected(index: Int) {
        EventBus.getDefault().post(EBUISwitch(DownloadManagerActivity.TAG, index))

        SensorsBridge.trackDownloadManagerTabSelect(mTabTitleList[index])

        if (index == INDEX_UPDATE) {
            mIsUpdateTabHasBeenSelected = true
            updateUpdateHint()
            mDownloadManager.markUpdatableTaskAsRead()
        } else if (index == INDEX_DOWNLOAD) {
            mIsDownloadTabHasBeenSelected = true
            updateDownloadHint()
            mDownloadManager.markDownloadingTaskAsRead()
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(mipush: EBMiPush) {
        if ("plugin_install" == mipush.from) {
            mViewPager.currentItem = DownloadManagerActivity.INDEX_DOWNLOAD
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(changed: EBDownloadChanged) {
        if ("download" == changed.type) {
            // 因为数据库已安装的数据是是比这个回调晚的，所以这里延时500ms
            postDelayedRunnable({ updateDownloadHint() }, 500L)
        } else if ("update" == changed.type) {
            updateUpdateHint()
        }
    }

    private fun updateDownloadHint() {
        if (!::mDownloadNumberTv.isInitialized || !isAdded) return

        val downloadData = DownloadManager.getInstance().allDownloadEntityExcludeSilentTask
        if (downloadData.size > 0) {
            mDownloadNumberTv.visibility = View.VISIBLE
        } else {
            mDownloadNumberTv.visibility = View.INVISIBLE
            return
        }

        var downloadingCount = 0
        for (download in downloadData) {
            if (DownloadStatus.done != download.status) {
                downloadingCount++
            }
        }

        val layoutParams = mDownloadNumberTv.layoutParams as LinearLayout.LayoutParams
        when {
            downloadingCount > 0 -> {
                layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT
                layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT
                layoutParams.setMargins(4F.dip2px(), 0, 0, 0F.dip2px())
                mDownloadNumberTv.setBackgroundColor(Color.TRANSPARENT)
                mDownloadNumberTv.text = downloadingCount.toString()
            }

            mDownloadManager.isContainsUnreadDownloadedTask -> {
                layoutParams.width = 6F.dip2px()
                layoutParams.height = 6F.dip2px()
                layoutParams.setMargins(2F.dip2px(), 0, 0, 3F.dip2px())
                mDownloadNumberTv.setBackgroundResource(R.drawable.oval_hint_red_bg)
                mDownloadNumberTv.text = ""
            }

            else -> mDownloadNumberTv.visibility = View.GONE
        }
        mDownloadNumberTv.layoutParams = layoutParams
    }

    private fun updateUpdateHint() {
        if (!::mUpdateNumberTv.isInitialized) return

        if (mIsUpdateTabHasBeenSelected) {
            mUpdateNumberTv.visibility = View.INVISIBLE
            return
        }

        val updateCount = mDownloadManager.getUnreadUpdateCount(PackagesManager.getUpdateList()
            .filter { gameUpdateEntity ->
                gameUpdateEntity.isShowPlugin(PluginLocation.only_index)
                        && mPermanentInactivePluggableApkList?.filter { it.pkgName == gameUpdateEntity.packageName }?.size == 0
            })

        mUpdateNumberTv.visibleIf(updateCount != 0)
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(skip: EBSkip) {
        if (DownloadManagerActivity.TAG == skip.type) {
            if (view != null) {
                requireView().postDelayed({
                    mViewPager.currentItem = skip.currentItem
                    if (isAdded && skip.currentItem == DownloadManagerActivity.INDEX_DOWNLOAD) {
                        val fragments = childFragmentManager.fragments
                        if (fragments != null) {
                            for (fragment in fragments) {
                                if (fragment.isAdded
                                    && fragment is GameDownloadFragment
                                ) {
                                    fragment.onResume() // auto refresh list
                                }
                            }
                        }
                    }
                }, 300)
            }
        }
    }

    private fun startAdBannerAutoPlay() {
        if ((mAdGameBannerAdapter != null && mAdGameBannerAdapter!!.getActualSize() < 2) || mSlideInterval == -1) return
        stopAdBannerAutoPlay()
        mAdLooperHandler.sendEmptyMessageDelayed(mSlideLooperKey, mSlideInterval * 1000L)
    }

    private fun stopAdBannerAutoPlay() {
        mAdLooperHandler.removeMessages(mSlideLooperKey)
    }

    private fun scrollToNextPage() {
        val snapView = mAdGameBannerSnapHelper.findSnapView(mAdGameBannerLayoutManager)
        if (snapView != null) {
            mAdGameBannerLayoutManager.smoothScrollToPosition(
                mBinding.adGameBannerRv,
                null,
                mAdGameBannerLayoutManager.getPosition(snapView) + 1
            )
        }
    }

    companion object {
        const val INDEX_DOWNLOAD = 0
        const val INDEX_UPDATE = 1

        const val KEY_PATH_OF_PACKAGE_TO_INSTALL = "key_path_of_package_to_install"
        const val KEY_URL_OF_PACKAGE_TO_INSTALL = "key_url_of_package_to_install"
    }

    class LooperHandler(fragment: DownloadFragment) : Handler(Looper.getMainLooper()) {
        private val mWeakReference: WeakReference<DownloadFragment> = WeakReference(fragment)

        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            val fragment = mWeakReference.get()
            if (fragment != null && msg.what == fragment.mSlideLooperKey) {
                fragment.scrollToNextPage()
                fragment.startAdBannerAutoPlay()
            }
        }
    }
}