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.ExposureListener
import com.gh.common.util.DialogUtils
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.baselist.LazyListFragment
import com.gh.gamecenter.common.baselist.LoadType
import com.gh.gamecenter.common.constant.EntranceConsts
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.entity.GameEntity
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.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

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

    private lateinit var mExposureListener: ExposureListener

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

    private var mIsColumnCollection = false
    private var mScrollTop = false

    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
            )
        }
        return mAdapter as SubjectAdapter
    }

    override fun provideListViewModel(): SubjectListViewModel {
        val factory = SubjectListViewModel.Factory(
            HaloApp.getInstance().application,
            arguments?.getParcelable(EntranceConsts.KEY_SUBJECT_DATA)!!,
            arguments?.getParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST)
        )
        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
        super.onFragmentFirstVisible()
        (mListViewModel as SubjectListViewModel).lastPageDataMap =
            arguments?.get(SubjectFragment.LAST_PAGE_DATA) as? HashMap<String, String>

        mCachedView?.setBackgroundColor(R.color.background_white.toColor(requireContext()))
        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(R.color.skeleton_shimmer_color)
            .duration(Constants.SHIMMER_DURATION)
            .maskWidth(Constants.MASK_WIDTH)
            .gradientCenterColorWidth(Constants.GRADIENT_CENTER_COLOR_WIDTH)
            .load(skeletonLayoutId).show()
        mListViewModel.load(LoadType.REFRESH)
    }

    override fun getRealLayoutId() = R.layout.fragment_list_base_skeleton

    override fun initRealView() {
        super.initRealView()

        // 与外部Appbar交互
        mListRv.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
                }
            }
        })

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

    fun refreshPage(filter: String, sort: String, size: SubjectSettingEntity.Size) {
        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 onResume() {
        super.onResume()
    }

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