package com.gh.gamecenter.subject

import android.view.View
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.RecyclerView
import com.ethanhua.skeleton.Skeleton
import com.gh.common.exposure.DefaultExposureStateChangeListener
import com.gh.common.util.DialogUtils
import com.gh.common.view.ConfigFilterView
import com.gh.common.view.ConfigFilterView.SortType
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.baselist.LazyListFragment
import com.gh.gamecenter.common.baselist.LoadType
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.pagelevel.IPageLevelProvider
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.utils.viewModelProviderFromParent
import com.gh.gamecenter.common.view.SpacingItemDecoration
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.UrlFilterUtils
import com.gh.gamecenter.entity.SubjectData
import com.gh.gamecenter.entity.SubjectSettingEntity
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.PageLocation
import com.gh.gamecenter.feature.exposure.addExposureHelper
import com.halo.assistant.HaloApp
import com.lightgame.OnTitleClickListener
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

open class SubjectListFragment : LazyListFragment<GameEntity, SubjectListViewModel>(), OnTitleClickListener {

    private var mAdapter: SubjectAdapter? = null
    private var mSubjectViewModel: SubjectViewModel? = null

    private var mIsColumnCollection = false
    private var mCollectionId = ""
    private var mCollectionName = ""
    private var mCollectionStyle = ""
    private var mScrollTop = false
    private var mMaxSize = ""
    private var mMinSize = ""

    var selectedLabelList = arrayListOf<String>()

    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 getStubLayoutId() = R.layout.fragment_list_base_skeleton_stub

    override fun getItemDecoration(): RecyclerView.ItemDecoration? {
        return if (arguments?.getBoolean(EntranceConsts.KEY_IS_HOME) == true) {
            null
        } else {
            SpacingItemDecoration(onlyDecorateTheFirstItem = true, top = DisplayUtils.dip2px(1F))
        }
    }

    override fun provideListAdapter(): SubjectAdapter {
        if (mAdapter == null) {
            mAdapter = SubjectAdapter(
                requireContext(),
                mListViewModel,
                mSubjectViewModel,
                arguments?.getString(EntranceConsts.KEY_ENTRANCE),
                mIsColumnCollection,
                arguments?.getInt(EntranceConsts.KEY_COLUMN_COLLECTION_CUSTOM_POSITION, -1) ?: -1,
                mCollectionId,
                mCollectionName,
                mCollectionStyle
            )
        }
        return mAdapter as SubjectAdapter
    }

    override fun provideListViewModel(): SubjectListViewModel {
        val bottomTabName = arguments?.getString(EntranceConsts.KEY_BOTTOM_TAB_NAME, "") ?: ""
        val bottomTabIndex = arguments?.getInt(EntranceConsts.KEY_BOTTOM_TAB_INDEX, -1) ?: -1
        val tabIndex = arguments?.getInt(EntranceConsts.KEY_TAB_INDEX, -1) ?: -1
        val tabName = arguments?.getString(EntranceConsts.KEY_TAB_NAME, "") ?: ""
        val multiTabNavId = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_ID, "") ?: ""
        val multiTabNavName = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_NAME, "") ?: ""

        val precisePageLevelString = (activity as? IPageLevelProvider)
            ?.getPageLevel()
            ?.getTempNewPageLevel(topTabPosition = tabIndex, bottomTabPosition = bottomTabIndex)
            ?.toFormattedString(ignoreBottomTabPositionMap = true)
            ?: ""
        val factory = SubjectListViewModel.Factory(
            HaloApp.getInstance().application,
            arguments?.getParcelable(EntranceConsts.KEY_SUBJECT_DATA)!!,
            PageLocation(
                bottomTab = bottomTabName,
                bottomTabIndex = bottomTabIndex,
                pageLevelString = precisePageLevelString,
                severalTabPageId = multiTabNavId,
                severalTabPageName = multiTabNavName,
                tabPosition = tabIndex,
                tabContent = tabName
            ),
            arguments?.getParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST),
            columnCollectionId = mCollectionId
        )
        if (requireContext() is SubjectActivity) {
            requireActivity().intent.getParcelableExtra<SubjectData>(EntranceConsts.KEY_SUBJECT_DATA)?.let {
                val f = SubjectViewModel.Factory(HaloApp.getInstance().application, it)
                mSubjectViewModel = viewModelProviderFromParent(f)
            }
        }
        return ViewModelProviders.of(this, factory).get(SubjectListViewModel::class.java)
    }

    override fun onFragmentFirstVisible() {
        mIsColumnCollection = arguments?.getBoolean(EntranceConsts.KEY_IS_COLUMN_COLLECTION, false) ?: false
        mCollectionId = arguments?.getString(EntranceConsts.KEY_COLUMN_COLLECTION_ID, "") ?: ""
        mCollectionName = arguments?.getString(EntranceConsts.KEY_COLUMN_COLLECTION_NAME, "") ?: ""
        mCollectionStyle = arguments?.getString(EntranceConsts.KEY_COLUMN_COLLECTION_STYLE, "") ?: ""
        super.onFragmentFirstVisible()
        (mListViewModel as SubjectListViewModel).run {
            lastPageDataMap =
                arguments?.get(SubjectFragment.LAST_PAGE_DATA) as? HashMap<String, String>
            arguments?.getString(EntranceConsts.KEY_SUBJECT_SORT_SIZE)?.let { selectedFilterSize = SubjectSettingEntity.Size(text = it) }
        }

        mCachedView?.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()))
        initFilterView()
        val skeletonLayoutId = when (arguments?.getString(EntranceConsts.KEY_SUBJECT_TYPE) ?: "") {
            "detail" -> R.layout.fragment_subject_detail_skeleton
            "tab" -> R.layout.fragment_subject_tab_skeleton
            else -> R.layout.fragment_subject_skeleton
        }
        mSkeletonScreen = Skeleton
            .bind(mCachedView.findViewById<View>(R.id.list_skeleton))
            .shimmer(true)
            .angle(Constants.SHIMMER_ANGLE)
            .color(com.gh.gamecenter.common.R.color.ui_skeleton_highlight)
            .duration(Constants.SHIMMER_DURATION)
            .maskWidth(Constants.MASK_WIDTH)
            .gradientCenterColorWidth(Constants.GRADIENT_CENTER_COLOR_WIDTH)
            .load(skeletonLayoutId).show()
        mListViewModel.load(LoadType.REFRESH)
    }

    private fun initFilterView() {
        val subjectSetting= arguments?.getParcelable<SubjectSettingEntity>(EntranceConsts.KEY_SUBJECT_SETTING_DATA) ?: return
        val originalFilter = mListViewModel.subjectData.filter
        mCachedView?.findViewById<ConfigFilterView>(R.id.filterView)?.run {
            goneIf(!subjectSetting.isFilterEnabled) {
                initSubjectFilterView(subjectSetting)
                when (updateTv.text) {
                    "更新" -> mListViewModel.subjectData.sort = UrlFilterUtils.getFilterQuery("update_time", "-1")
                    "最新" -> mListViewModel.subjectData.sort = UrlFilterUtils.getFilterQuery("publish", "-1")
                    "评分" -> mListViewModel.subjectData.sort = UrlFilterUtils.getFilterQuery("star", "-1")
                    else -> mListViewModel.subjectData.sort = UrlFilterUtils.getFilterQuery("position", "1")
                }
                setOnConfigSetupListener(object :
                    ConfigFilterView.OnConfigFilterSetupListener {
                    override fun onShowSortSize() {}

                    override fun onSetupSortSize(sortSize: SubjectSettingEntity.Size) {
                        mMinSize = sortSize.min.toString()
                        mMaxSize = sortSize.max.toString()

                        var filter = originalFilter.ifEmpty { "type:全部" }
                        if (mMinSize.isNotEmpty() && mMinSize != "-1") {
                            filter += ",${UrlFilterUtils.getFilterQuery("min_size", mMinSize)}"
                        }
                        if (mMaxSize.isNotEmpty() && mMaxSize != "-1") {
                            filter += ",${UrlFilterUtils.getFilterQuery("max_size", mMaxSize)}"
                        }

                        refreshPage(filter = filter, size = sortSize)
                    }

                    override fun onSetupSortType(sortType: SortType) {
                        val clickTv = when (sortType) {
                            SortType.RATING -> ratingTv
                            SortType.NEWEST -> newestTv
                            SortType.UPDATE -> updateTv
                            else -> recommendedTv
                        }

                        val sort = when (clickTv.text) {
                            "更新" -> UrlFilterUtils.getFilterQuery("update_time", "-1")
                            "最新" -> UrlFilterUtils.getFilterQuery("publish", "-1")
                            "评分" -> UrlFilterUtils.getFilterQuery("star", "-1")
                            else -> UrlFilterUtils.getFilterQuery("position", "1")
                        }

                        if (mListViewModel.subjectData.sort != sort) {
                            refreshPage(sort = sort)
                        }
                    }
                })
            }
        }
    }

    override fun getRealLayoutId() = R.layout.fragment_subject_list

    override fun initRealView() {
        super.initRealView()

        mListRv?.let {
            it.addExposureHelper(this, DefaultExposureStateChangeListener())
            // 与外部Appbar交互
            it.addOnScrollListener(object : RecyclerView.OnScrollListener() {
                override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                    super.onScrollStateChanged(recyclerView, newState)
                    val position = mLayoutManager.findFirstCompletelyVisibleItemPosition()
                    if (mScrollTop && position == 0 && newState == RecyclerView.SCROLL_STATE_IDLE) {
                        mScrollTop = false
                    }
                }
            })
        }
    }

    fun refreshPage(
        filter: String = mListViewModel.subjectData.filter,
        sort: String = mListViewModel.subjectData.sort,
        size: SubjectSettingEntity.Size = mListViewModel.selectedFilterSize
    ) {
        mListViewModel.selectedFilterSize = size
        mListViewModel.selectedLabelList = selectedLabelList
        mListViewModel.subjectData.filter = filter
        mListViewModel.subjectData.sort = sort
        mListViewModel.load(LoadType.REFRESH)
    }

    // 与外部Appbar交互
    override fun onTitleClick() {
        if (mLayoutManager == null
            || mLayoutManager.findFirstCompletelyVisibleItemPosition() == 0
            || provideListAdapter().itemCount == 0
        ) {
            // do nothing
        } else {
            mLayoutManager.scrollToPosition(0)
            mScrollTop = true
        }
    }

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

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

    // 下载被删除事件
    @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()
        }
    }

    override fun isAutomaticLoad() = false

    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()
        mAdapter?.let { it.notifyItemRangeChanged(0, it.itemCount) }
        mCachedView?.findViewById<ConfigFilterView>(R.id.filterView)?.run {
            if (isVisible) {
                updateAllTextView()
            }
        }
    }
}