package com.gh.gamecenter.catalog

import android.os.Bundle
import android.view.View
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.CatalogFilterView
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.baselist.ListFragment
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.databinding.FragmentCatalogListBinding
import com.gh.gamecenter.entity.CatalogEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.entity.SubjectSettingEntity
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 NewCatalogListFragment : ListFragment<GameEntity, NewCatalogListViewModel>() {

    private var mPrimaryCatalogName: String = "" // 一级分类名
    private var mPrimaryCatalogId: String = "" // 一级分类 id
    private var mPrimeCatalog: CatalogEntity? = null
    private var mSubCatalogList = arrayListOf<CatalogEntity.SubCatalogEntity>()
    private var mInitCatalogName = ""
    private var mAdapter: NewCatalogListAdapter? = 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 var mBinding: FragmentCatalogListBinding? = null
    private lateinit var mExposureListener: ExposureListener
    private lateinit var mViewModel: NewCatalogListViewModel

    override fun getLayoutId() = 0

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

    override fun provideListViewModel() = viewModelProvider<NewCatalogListViewModel>()

    override fun provideListAdapter() = mAdapter
        ?: NewCatalogListAdapter(
            requireContext(),
            ExposureSource(mPrimaryCatalogName),
            mViewModel,
            mEntrance
        ).apply { mAdapter = this }

    override fun getItemDecoration() = null

    override fun onCreate(savedInstanceState: Bundle?) {
        mViewModel = provideListViewModel()

        mViewModel.title = arguments?.getString(EntranceConsts.KEY_NAME) ?: ""
        mViewModel.categoryTitle = arguments?.getString(EntranceConsts.KEY_CATALOG_TITLE) ?: ""
        mEntrance = arguments?.getString(EntranceConsts.KEY_ENTRANCE) ?: Constants.ENTRANCE_UNKNOWN
        mPrimeCatalog = arguments?.getParcelable(EntranceConsts.KEY_DATA)
        mSubCatalogList = mPrimeCatalog?.subCatalog as? ArrayList<CatalogEntity.SubCatalogEntity> ?: arrayListOf()

        mInitCatalogName = arguments?.getString(EntranceConsts.KEY_CATALOG_INIT_TITLE) ?: ""
        mPrimaryCatalogName = arguments?.getString(EntranceConsts.KEY_PRIMARY_CATALOG_NAME) ?: ""
        mPrimaryCatalogId = arguments?.getString(EntranceConsts.KEY_PRIMARY_CATALOG_ID) ?: ""

        mViewModel.selectedCatalog = mSubCatalogList.find { entity -> entity.name == mInitCatalogName }
            ?: CatalogEntity.SubCatalogEntity()
        mViewModel.primaryCatalogId = mPrimaryCatalogId
        initSortType()

        super.onCreate(savedInstanceState)
    }

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

        setNavigationTitle(mViewModel.title)

        initFilterView()

        mViewModel.refresh.observeNonNull(this) { onRefresh() }

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

        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()
    }

    private fun initSortType() {
        mPrimeCatalog?.switch?.run {
            if (hotSort == "on") {
                mViewModel.sortType = CatalogFilterView.SortType.RECOMMENDED
                return@run
            }
            if (newSort == "on") {
                mViewModel.sortType = CatalogFilterView.SortType.NEWEST
                return@run
            }
            if (starSort == "on") {
                mViewModel.sortType = CatalogFilterView.SortType.RATING
                return@run
            }
        }
    }

    private fun initFilterView() {
        mBinding?.filterContainer?.run {
            visibility = View.VISIBLE
            setTypeList(mPrimeCatalog?.switch ?: CatalogEntity.CatalogSwitch())
            setCatalogList(mSubCatalogList, mInitCatalogName)
            setOnConfigSetupListener(object : CatalogFilterView.OnCatalogFilterSetupListener {
                override fun onSetupSortSize(sortSize: SubjectSettingEntity.Size) {
                    mViewModel.updateSortConfig(sortSize = sortSize)
                }

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

                override fun onSetupSortCatalog(sortCatalog: CatalogEntity.SubCatalogEntity) {
                    mViewModel.updateSortConfig(sortCatalog = sortCatalog)
                }
            })
        }

    }

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

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

    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()
        mBinding?.filterContainer?.run {
            setRootBackgroundColor(R.color.background_white.toColor(requireContext()))
            setItemTextColor(R.color.text_subtitle.toColor(requireContext()))
            updatePopupWindow()
        }
    }
}