package com.gh.gamecenter.servers

import android.graphics.Color
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.RelativeLayout
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager.widget.ViewPager
import com.ethanhua.skeleton.Skeleton
import com.ethanhua.skeleton.ViewSkeletonScreen
import com.gh.common.exposure.ExposureListener
import com.gh.common.util.*
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.baselist.LoadStatus
import com.gh.gamecenter.common.base.fragment.BaseFragment
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.core.utils.MtaHelper.onEvent
import com.gh.gamecenter.databinding.FragmentKaifuContentBinding
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.text.SimpleDateFormat
import java.util.*

/**
 * 开服表内容 fragment
 */
class GameServersContentFragment : BaseFragment<Any?>() {

    private var mAdapter: GameServersContentAdapter? = null
    private var mLayoutManager: LinearLayoutManager? = null
    private var mExposureListener: ExposureListener? = null
    private var mLlParams: RelativeLayout.LayoutParams? = null
    private var mViewModel: GameServersContentViewModel? = null
    private var mSkeleton: ViewSkeletonScreen? = null
    private var mShowPullDownTipFlag = true
    private var mHidePullDownTipFlag = true
    private var mIsRefresh = false

    private var mIsRefreshDownload = true

    private var mBinding: FragmentKaifuContentBinding? = null

    private val dataWatcher: DataWatcher = object : DataWatcher() {
        override fun onDataChanged(downloadEntity: DownloadEntity) {
            val locationList = mViewModel?.locationMap?.get(downloadEntity.packageName)
            if (locationList != null && mIsRefreshDownload) {
                for (location in locationList) {
                    mViewModel?.listLiveData?.value?.second?.safelyGetInRelease(location)?.let { gameEntity ->
                        DownloadItemUtils.processDate(gameEntity, downloadEntity, mAdapter, location + 1)
                    }
                }
                if (XapkUnzipStatus.FAILURE.name == downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS]) {
                    for (position in locationList) {
                        val targetView = mLayoutManager?.findViewByPosition(position + 1)
                        if (targetView != null) {
                            DialogUtils.showUnzipFailureDialog(requireContext(), downloadEntity)
                            break
                        }
                    }
                }
            }
        }
    }

    override fun getLayoutId() = 0

    override fun getInflatedLayout(): View {
        return FragmentKaifuContentBinding.inflate(layoutInflater).apply { mBinding = this }.root
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mLlParams =
            RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
        (mBinding?.recyclerView?.itemAnimator as DefaultItemAnimator?)?.supportsChangeAnimations = false
        mBinding?.recyclerView?.layoutManager = LinearLayoutManager(requireContext()).apply { mLayoutManager = this }
        mViewModel = viewModelProvider()
//        mViewModel?.type = arguments?.getString(EntranceUtils.KEY_TYPE, "开服")
        mViewModel?.listLiveData?.observe(this, androidx.lifecycle.Observer {
            if (it.second.isEmpty()) return@Observer

            if (it.first == "down") {
                mAdapter?.submitList(it.second, isShowPullDownTip = false, isDown = true, downSize = it.third)
                mBinding?.kaifuTimeContainer?.kaifuItemTime?.visibility = View.VISIBLE
            } else {
                mAdapter?.submitList(
                    it.second,
                    mShowPullDownTipFlag || mBinding?.pullDownTip?.visibility == View.VISIBLE
                )
            }
            showPullDownTip()
            if (mIsRefresh) {
                mIsRefresh = false
                handleHeaderView(it.second[0].kaifuTimeHint ?: 0L)
            }
        })
        mViewModel?.loadStatusLiveData?.observe(this) {
            when (it.second) {
                LoadStatus.INIT_LOADED, LoadStatus.INIT_OVER -> loadDone()
                LoadStatus.INIT_EMPTY -> loadEmpty()
                LoadStatus.INIT_FAILED -> loadError()
                else -> {
                    //do nothing
                }
            }
            mAdapter?.loadChange(it)
        }

        mBinding?.root?.setBackgroundColor(R.color.background_white.toColor(requireContext()))
        mSkeleton = Skeleton.bind(mBinding?.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(R.layout.fragment_game_servers_skeleton)
            .show()

        mAdapter = GameServersContentAdapter(requireContext(), mViewModel!!, mEntrance)
        mExposureListener = ExposureListener(this, mAdapter!!)
        mBinding?.recyclerView?.addOnScrollListener(mExposureListener!!)
        mBinding?.recyclerView?.adapter = mAdapter
        mBinding?.recyclerView?.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)
                mBinding?.recyclerView?.run {
                    if (translationY != 0F) {
                        animate().translationY(0F).setDuration(200).start()
                        hidePullDownTip()
                        mBinding?.kaifuTimeContainer?.kaifuItemTime?.visibility = View.GONE
                    }
                }

                if (mLayoutManager?.findFirstVisibleItemPosition() == 0
                    && newState == RecyclerView.SCROLL_STATE_IDLE
                    && !mAdapter!!.isPrevOver()
                    && !mAdapter!!.isPrevLoading()
                ) {
                    mViewModel?.run {
                        mAdapter?.loadChange(Pair("down", LoadStatus.INIT))
                        loadData(action = "down")
                    }
                } else if (mLayoutManager?.findLastVisibleItemPosition() == mAdapter!!.itemCount - 1
                    && newState == RecyclerView.SCROLL_STATE_IDLE
                    && !mAdapter!!.isNextOver()
                    && !mAdapter!!.isNextLoading()
                ) {
                    mViewModel?.run {
                        loadData(action = "up")
                    }
                }
                mIsRefreshDownload = newState == RecyclerView.SCROLL_STATE_IDLE
            }

            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
                if (dy != 0) hidePullDownTip()
                if (mLayoutManager?.findFirstVisibleItemPosition() == 0) {
                    mBinding?.kaifuTimeContainer?.kaifuItemTime?.visibility = View.GONE
                } else if (dy != 0) {
                    mBinding?.kaifuTimeContainer?.kaifuItemTime?.visibility = View.VISIBLE
                }
                val position = mLayoutManager?.findFirstVisibleItemPosition() ?: 0
                val dataList = mViewModel?.listLiveData?.value?.second
                if (position == RecyclerView.NO_POSITION || position < 1 || dataList?.isEmpty() == true) return
                val gameEntity = dataList?.get(position - 1)
                val kaifuTimeHint = gameEntity?.kaifuTimeHint

                // 悬挂的文案
                val timeGameEntity = dataList?.get(position - 1)
                val fixedTopHint = timeGameEntity?.fixedTop ?: false
                if (fixedTopHint) {
                    mBinding?.kaifuTimeContainer?.kaifuItemTimeTv
                    mBinding?.kaifuTimeContainer?.kaifuItemTimeTv?.text = "热门开服"
                    mBinding?.kaifuTimeContainer?.kaifuItemTimeTv?.tag = timeGameEntity?.kaifuTimeHint
                    mBinding?.kaifuTimeContainer?.kaifuItemHeader?.setImageResource(R.drawable.ic_kaifu_hot)
                } else {
                    val timeHint = timeGameEntity?.kaifuTimeHint
                    val dateFm = SimpleDateFormat("yyyy-MM-dd (EEEE) HH:mm", Locale.CHINA)
                    if (timeHint == null || timeHint == 0L) {
                        val serverEntity = timeGameEntity?.serverEntity
                        if (serverEntity != null) {
                            mBinding?.kaifuTimeContainer?.kaifuItemTimeTv?.text =
                                dateFm.format(serverEntity.getTime() * 1000)
                            mBinding?.kaifuTimeContainer?.kaifuItemHeader?.setImageResource(R.drawable.kaifu_time_icon)
                            mBinding?.kaifuTimeContainer?.kaifuItemTimeTv?.tag = serverEntity.getTime()
                        }
                    } else {
                        mBinding?.kaifuTimeContainer?.kaifuItemTimeTv?.text = dateFm.format(timeHint * 1000)
                        mBinding?.kaifuTimeContainer?.kaifuItemHeader?.setImageResource(R.drawable.kaifu_time_icon)
                        mBinding?.kaifuTimeContainer?.kaifuItemTimeTv?.tag = timeHint
                    }
                }

                // 悬挂界面移动
                if (kaifuTimeHint != null && kaifuTimeHint != 0L) {
                    val bottom = mLayoutManager?.findViewByPosition(position)?.bottom ?: 0
                    if (bottom <= mBinding?.kaifuTimeContainer?.kaifuItemTime?.height ?: 0) {
                        mLlParams?.topMargin = bottom - (mBinding?.kaifuTimeContainer?.kaifuItemTime?.height
                            ?: 0)
                    } else {
                        mLlParams?.topMargin = 0
                    }
                } else {
                    mLlParams?.topMargin = 0
                }
                mBinding?.kaifuTimeContainer?.kaifuItemTime?.layoutParams = mLlParams
            }
        })
        mBinding?.reuseNoneData?.reuseResetLoadTv?.setOnClickListener {
            val parentFragment = parentFragment
            if (parentFragment is GameServersPublishFragment) {
                onEvent("开服表", "开服Tab", "查看全部")
                parentFragment.resetFilter()
            }
        }
        mBinding?.noConnectionContainer?.root?.setOnClickListener {
            onRefreshPage()
        }

        mBinding?.recyclerView?.run {
            val listener = object : ViewTreeObserver.OnGlobalLayoutListener {
                override fun onGlobalLayout() {
                    mLayoutManager?.scrollToPosition(1)
                    if (mLayoutManager?.findFirstVisibleItemPosition() == 1) {
                        viewTreeObserver?.removeOnGlobalLayoutListener(this)
                    }
                }
            }
            viewTreeObserver?.addOnGlobalLayoutListener(listener)
            postDelayed({
                tryCatchInRelease {
                    mBinding?.recyclerView?.viewTreeObserver?.removeOnGlobalLayoutListener(listener)
                }
            }, 2000)
        }
    }


    private fun handleHeaderView(responseTime: Long) {
        mBinding?.run {
            recyclerView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
                override fun onGlobalLayout() {
                    val canScrollVertically = recyclerView.canScrollVertically(-1)
                    if (mViewModel?.hour != null) {
                        val responseHour = TimeUtils.getFormatTime(responseTime, "HH")
                        val tempHour = mViewModel!!.hour!!.toInt()
                        val requestHour = if (tempHour >= 10) tempHour.toString() else "0${tempHour}"
                        if (responseHour != requestHour) {
                            noMatchView.translationY = 0F
                            noMatchView.visibility = View.VISIBLE
                            recyclerView.translationY =
                                if (canScrollVertically) 40F.dip2px().toFloat() else -(8F.dip2px().toFloat())
                            postDelayedRunnable({
                                tryCatchInRelease {
                                    noMatchView.animate().translationY(-(40F.dip2px().toFloat())).setDuration(200)
                                        .start()
                                    recyclerView.animate()
                                        .translationY(recyclerView.translationY - 40F.dip2px().toFloat())
                                        .setDuration(200).start()
                                }
                            }, 2000)
                        } else {
                            recyclerView.translationY = if (canScrollVertically) 0F else -(48F.dip2px().toFloat())
                        }
                    } else {
                        recyclerView.translationY = if (canScrollVertically) 0F else -(48F.dip2px().toFloat())
                    }
                    recyclerView.viewTreeObserver.removeOnGlobalLayoutListener(this)
                }
            })
        }
    }

    private fun showPullDownTip() {
        if (mShowPullDownTipFlag) {
            postDelayedRunnable({
                tryCatchInRelease {
                    mBinding?.run {
                        mShowPullDownTipFlag = false
                        pullDownTip.translationY = -(8F.dip2px().toFloat())
                        pullDownTip.visibility = View.VISIBLE
                        pullDownTip.animate().translationY(0F).setDuration(500).start()
                    }
                }
            }, 500)
        }
    }

    private fun hidePullDownTip() {
        mBinding?.run {
            if (pullDownTip.visibility == View.VISIBLE && mHidePullDownTipFlag) {
                mHidePullDownTipFlag = false
                pullDownTip.animate()
                    .translationY(-(8F.dip2px().toFloat()))
                    .setDuration(500)
                    .withEndAction { pullDownTip.visibility = View.GONE }
                    .start()
            }
        }
    }

    fun filterData(day: String?, hour: String?, type: String?, tags: String?) {
        mViewModel?.run {
            this.day = day
            this.hour = hour
//            this.type = type
            this.tags = tags
            onRefreshPage()
        }
    }

    fun vpScrollState(status: Int) {
        if (status == ViewPager.SCROLL_STATE_IDLE) {
            mIsRefreshDownload = true
        } else if (status == ViewPager.SCROLL_STATE_DRAGGING) {
            mIsRefreshDownload = false
        }
    }

    override fun onResume() {
        super.onResume()
        if (mAdapter != null) {
            mAdapter?.notifyDataSetChanged()
            DownloadManager.getInstance().addObserver(dataWatcher)
        }
    }

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

    private fun onRefreshPage() {
        mIsRefresh = true
        mAdapter?.resetStatus()
        mBinding?.root?.setBackgroundColor(R.color.background_white.toColor(requireContext()))
        mSkeleton?.show()
        mBinding?.loadingContainer?.reuseLlLoading?.visibility = View.VISIBLE
        mBinding?.noConnectionContainer?.reuseNoConnection?.visibility = View.GONE
        mBinding?.reuseNoneData?.reuseNoneData?.visibility = View.GONE
        mBinding?.kaifuTimeContainer?.kaifuItemTime?.visibility = View.GONE
        mBinding?.recyclerView?.visibility = View.GONE
        mLayoutManager?.scrollToPositionWithOffset(1, 0)
        mViewModel?.loadData(true)
    }

    // 下载被删除事件
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(status: EBDownloadStatus) {
        DownloadManager.getInstance().removePlatform(status.name, status.platform)
        if ("delete" == status.status) {
            mViewModel?.locationMap?.get(status.packageName)?.let {
                for (location in it) {
                    mViewModel?.listLiveData?.value?.second?.safelyGetInRelease(location)?.getEntryMap()
                        ?.remove(status.platform)
                    mAdapter?.notifyItemChanged(location)
                }
            }
        }
    }

    override fun loadDone() {
        super.loadDone()
//        mBinding?.kaifuTimeContainer?.kaifuItemTime?.visibility = View.VISIBLE
        mSkeleton?.hide()
        mBinding?.run {
            root.setBackgroundColor(Color.TRANSPARENT)
            recyclerView.visibility = View.VISIBLE
            noConnectionContainer.reuseNoConnection.visibility = View.GONE
            reuseNoneData.reuseNoneData?.visibility = View.GONE
            loadingContainer.reuseLlLoading.visibility = View.GONE
        }
//        mBinding?.refreshLayout?.finishRefresh()
    }

    override fun loadError() {
        if (!isAdded) return
        super.loadError()
        toast(R.string.loading_failed_hint)
        mBinding?.run {
            root.setBackgroundColor(Color.TRANSPARENT)
            mSkeleton?.hide()
            recyclerView.visibility = View.GONE
            kaifuTimeContainer.kaifuItemTime.visibility = View.GONE
            noConnectionContainer.reuseNoConnection.visibility = View.VISIBLE
            reuseNoneData.reuseNoneData?.visibility = View.GONE
            loadingContainer.reuseLlLoading.visibility = View.GONE
            pullDownTip.visibility = View.GONE
        }
    }

    override fun loadEmpty() {
        super.loadEmpty()
        mBinding?.run {
            root.setBackgroundColor(Color.TRANSPARENT)
            mSkeleton?.hide()
            recyclerView.visibility = View.GONE
            kaifuTimeContainer.kaifuItemTime.visibility = View.GONE
            noConnectionContainer.reuseNoConnection.visibility = View.GONE
            reuseNoneData.reuseNoneData?.visibility = View.VISIBLE
            reuseNoneData.reuseResetLoadTv?.visibility = View.VISIBLE
            reuseNoneData.reuseResetLoadTv?.text = "查看全部"
            loadingContainer.reuseLlLoading.visibility = View.GONE
            pullDownTip.visibility = View.GONE
        }
    }

    private fun scrollToTop() {
        mLayoutManager?.scrollToPosition(0)
        mBaseHandler.postDelayed({
            mLlParams?.topMargin = 0
            mBinding?.kaifuTimeContainer?.kaifuItemTime?.layoutParams = mLlParams
        }, 10)
    }

    override fun onDarkModeChanged() {
        super.onDarkModeChanged()
        mBinding?.recyclerView?.run {
            recycledViewPool.clear()
            adapter?.run {
                notifyItemRangeChanged(0, itemCount)
            }
        }
    }
}