package com.gh.gamecenter.tag

import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
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.view.ConfigFilterView
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.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.observeNonNull
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.common.baselist.ListAdapter
import com.gh.gamecenter.common.baselist.ListFragment
import com.gh.gamecenter.common.baselist.LoadType
import com.gh.gamecenter.databinding.FragmentTagsBinding
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.entity.SubjectSettingEntity
import com.gh.gamecenter.entity.TagEntity
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.eventbus.EBPackage
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

class TagsListFragment : ListFragment<GameEntity, TagsListViewModel>() {

    private lateinit var mBinding: FragmentTagsBinding

    private var mTag: String = ""
    private var mAdapter: TagsListAdapter? = null
    private var mExposureListener: ExposureListener? = null

    private val mDataWatcher = 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 lateinit var mViewModel: TagsListViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mViewModel = viewModelProvider()
    }

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

        setNavigationTitle("标签详情")

        mCachedView?.setBackgroundColor(R.color.background_white.toColor(requireContext()))
        mSkeletonScreen = Skeleton.bind(mBinding.listSkeleton)
            .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_tags_skeleton)
            .show()

        mTag = arguments?.getString(TagsActivity.TAG) ?: ""
        val exposureSourceList =
            arguments?.getParcelableArrayList<ExposureSource>(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST)
        if (!exposureSourceList.isNullOrEmpty()) {
            mViewModel.basicExposureSourceList = exposureSourceList
        } else {
            val source = arguments?.getString(TagsActivity.SOURCE) ?: ""
            when (arguments?.getString(TagsActivity.FROM) ?: TagsActivity.From.OTHERS) {
                TagsActivity.From.GAME_DETAIL.value -> {
                    mViewModel.basicExposureSourceList = arrayListOf(ExposureSource("游戏详情", source))
                }
                TagsActivity.From.SEARCH.value -> {
                    mViewModel.basicExposureSourceList =
                        arrayListOf(ExposureSource("首页搜索", ""), ExposureSource("热门标签", source))
                }
            }
        }

        mViewModel.getTags(mTag)

        mViewModel.tags.observeNonNull(this) {
            mBinding.tagsRecyclerView.visibility = View.VISIBLE
            mBinding.configContainer.visibility = View.VISIBLE
            updateTagsView(it)
        }
        mViewModel.refresh.observeNonNull(this) { onRefresh() }
        mViewModel.requestTagsError.observeNonNull(this) {
            if (it) {
                mBinding.tagsRecyclerView.visibility = View.GONE
                mBinding.configContainer.visibility = View.GONE
                onLoadError()
            }
        }

        mBinding.configContainer.setOnConfigSetupListener(object : ConfigFilterView.OnConfigFilterSetupListener {
            override fun onShowSortSize() {}

            override fun onSetupSortSize(sortSize: SubjectSettingEntity.Size) {
                mViewModel.updateSortConfig(sortSize = sortSize)
            }

            override fun onSetupSortType(sortType: ConfigFilterView.SortType) {
                mViewModel.updateSortConfig(sortType = sortType)
            }
        })

        mListRv.addOnScrollListener(mExposureListener!!)
    }

    override fun onResume() {
        super.onResume()
        DownloadManager.getInstance().addObserver(mDataWatcher)
    }

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

    override fun getItemDecoration() = null

    override fun getLayoutId() = 0

    override fun getInflatedLayout() = FragmentTagsBinding.inflate(layoutInflater).apply { mBinding = this }.root

    override fun isAutomaticLoad(): Boolean {
        return false
    }

    override fun provideListViewModel(): TagsListViewModel {
        return viewModelProvider()
    }

    override fun provideListAdapter(): ListAdapter<GameEntity> {
        return mAdapter ?: TagsListAdapter(requireContext(), mViewModel, mEntrance).apply {
            mAdapter = this
            mExposureListener = ExposureListener(this@TagsListFragment, this)
        }
    }

    private fun updateTagsView(tags: ArrayList<TagEntity>) {
        mBinding.tagsRecyclerView.layoutManager =
            LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
        mBinding.tagsRecyclerView.adapter = TagsHorizontalAdapter(requireContext(), mViewModel, tags) {
            mBinding.tagsRecyclerView.smoothScrollToPosition(it)
        }
    }

    override fun onLoadRefresh() {
        if (mReuseNoConn?.visibility == View.VISIBLE
            && (mBinding.tagsRecyclerView.adapter == null || mBinding.tagsRecyclerView.adapter?.itemCount == 0)
        ) {
            mViewModel.getTags(mTag)
        } else {
            mBaseHandler.postDelayed({ mListViewModel.load(LoadType.REFRESH) }, 200)
        }

        mCachedView?.setBackgroundColor(R.color.background_white.toColor(requireContext()))
        mSkeletonScreen?.show()
        mReuseNoConn?.visibility = View.GONE
        mReuseNoData?.visibility = View.GONE
        mListLoading?.visibility = View.VISIBLE
        mListRv.visibility = View.GONE
    }

    override fun onRefresh() {
        mAdapter?.clearPositionAndPackageMap()
        super.onRefresh()
    }

    // 下载被删除事件
    @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.isInstalledOrUninstalled()) {
            mAdapter?.notifyDataSetChanged()
        }
    }

    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 onDarkModeChanged() {
        super.onDarkModeChanged()
        mSkeletonScreen = Skeleton.bind(mBinding.listSkeleton)
            .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_tags_skeleton)
            .show().apply { hide() }
        mCachedView?.setBackgroundColor(R.color.background_white.toColor(requireContext()))
        mBinding.tagsRecyclerView.setBackgroundColor(R.color.background_white.toColor(requireContext()))
        mBinding.tagsRecyclerView.adapter?.notifyDataSetChanged()
        mBinding.divider.setBackgroundColor(R.color.background.toColor(requireContext()))
        mBinding.configContainer.run {
            container.setBackgroundColor(R.color.background_white.toColor(requireContext()))
            updateAllTextView(mViewModel.mSortType)
            updatePopupWindow()
        }
    }
}