package com.gh.gamecenter.home.video

import android.graphics.Rect
import android.os.Handler
import android.os.Looper
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.NetworkUtils
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.video.detail.CustomManager
import com.halo.assistant.HaloApp

class ScrollCalculatorHelper(
    val mListRv: RecyclerView,
    private val mPlayId: Int,
    private val mRangeTop: Int,
    private var isEnabled: Boolean = true
) {

    private var mFirstVisible = -1
    private var mLastVisible = 0
    private var mRunnable: PlayRunnable? = null
    private val mPlayHandler = Handler(Looper.getMainLooper())
    var currentPlayer: AutomaticVideoView? = null

    fun enableAndPlayIfValid() {
        isEnabled = true
        playIfValid()
    }

    fun playIfValid() {
        if (mListRv.isAttachedToWindow
            && mListRv.scrollState == RecyclerView.SCROLL_STATE_IDLE) {
            playVideo(mListRv)
        }
    }

    fun onScrollStateChanged(scrollState: Int) {
        if (scrollState == RecyclerView.SCROLL_STATE_IDLE) {
            playVideo(mListRv)
        }
    }

    fun onScroll() {
        stopIfNeeded()
    }

    fun onScroll(firstVisibleItem: Int, lastVisibleItem: Int) {
        mFirstVisible = firstVisibleItem
        mLastVisible = lastVisibleItem
        stopIfNeeded()
    }

    //判断player是否划出了屏幕，划出了屏幕则需要释放
    private fun stopIfNeeded() {
        val rect = Rect()
        if (currentPlayer != null) {
            currentPlayer?.getLocalVisibleRect(rect)
            val width = currentPlayer?.width
            val height = currentPlayer?.height
            if (rect.top != 0 || rect.bottom != height || rect.left != 0 || rect.right != width) {
                //保存进度
                val currentScheduler = currentPlayer?.currentPositionWhenPlaying?.toLong() ?: 0L
                savePlaySchedule(MD5Utils.getContentMD5(currentPlayer?.getUrl()), currentScheduler)
                currentPlayer?.initUIState()
                currentPlayer?.resetDetailMask()
                currentPlayer = null
                mRunnable?.let { mPlayHandler.removeCallbacks(it) }
            }
        }
    }

    fun forceStop() {
        //保存进度
        currentPlayer ?: return
        val currentScheduler = currentPlayer?.currentPositionWhenPlaying?.toLong() ?: 0L
        savePlaySchedule(MD5Utils.getContentMD5(currentPlayer?.getUrl()), currentScheduler)
        currentPlayer?.initUIState()
        currentPlayer?.resetDetailMask()
        currentPlayer = null
        mRunnable?.let { mPlayHandler.removeCallbacks(it) }
    }

    fun release() {
        if (currentPlayer != null) {
            val currentScheduler = currentPlayer?.currentPositionWhenPlaying?.toLong() ?: 0L
            savePlaySchedule(MD5Utils.getContentMD5(currentPlayer?.getUrl()), currentScheduler)
            CustomManager.releaseAllVideos(currentPlayer?.getKey())
            mRunnable?.let { mPlayHandler.removeCallbacks(it) }
            currentPlayer?.resetDetailMask()
            currentPlayer = null
        }
    }

    private fun playVideo(view: RecyclerView?) {
        if (view == null || !view.isAttachedToWindow || !isEnabled) return
        val layoutManager = view.layoutManager
        var gsyBaseVideoPlayer: AutomaticVideoView
        for (i in mFirstVisible until mLastVisible + 1) {
            if (layoutManager == null) return

            val child = mListRv.findViewHolderForAdapterPosition(i)?.itemView
            if (child is RecyclerView && child.layoutManager is LinearLayoutManager) {
                val hasChildVideoPlaying = playChildVideo(child)
                if (hasChildVideoPlaying) break
            } else if (child is ViewGroup) {
                val childList = findRecyclerView(child)
                if (childList != null) {
                    val hasChildVideoPlaying = playChildVideo(childList)
                    if (hasChildVideoPlaying) break
                }
            }

            val player: View? = child?.findViewById(mPlayId)
            if (player == null || player.visibility != View.VISIBLE || player !is AutomaticVideoView) continue

            val rect = Rect()
            player.getLocalVisibleRect(rect)
            val width = player.width
            val height = player.height
            if (rect.left == 0 && rect.right == width && rect.top == 0 && rect.bottom == height) {
                gsyBaseVideoPlayer = player
                if (mRunnable != null) {
                    mPlayHandler.removeCallbacks(mRunnable!!)
                    mRunnable = null
                }
                if (currentPlayer == gsyBaseVideoPlayer) return

                val screenPosition = IntArray(2)
                gsyBaseVideoPlayer.getLocationInWindow(screenPosition)
                val rangePosition = screenPosition[1]
                if (rangePosition >= mRangeTop) {
                    mRunnable?.let { mPlayHandler.removeCallbacks(it) }
                    mRunnable = PlayRunnable(gsyBaseVideoPlayer)
                    if (currentPlayer != null) {
                        currentPlayer?.initUIState()
                        currentPlayer?.resetDetailMask()
                    }
                    //降低频率
                    mPlayHandler.postDelayed(mRunnable!!, 100)
                    break
                }
            }
        }
    }

    private fun playChildVideo(recyclerView: RecyclerView): Boolean {
        val childLayoutManager = recyclerView.layoutManager as LinearLayoutManager
        val childFirstVisibleItemPosition = childLayoutManager.findFirstVisibleItemPosition()
        val childLastVisibleItemPosition = childLayoutManager.findLastVisibleItemPosition()
        var gsyBaseVideoPlayer: AutomaticVideoView
        for (index in childFirstVisibleItemPosition until childLastVisibleItemPosition + 1) {
            val child = recyclerView.findViewHolderForAdapterPosition(index)?.itemView
            val player: View? = child?.findViewById(mPlayId)
            if (player == null || player.visibility != View.VISIBLE || player !is AutomaticVideoView) continue

            val rect = Rect()
            player.getLocalVisibleRect(rect)
            val width = player.width
            val height = player.height
            if (rect.left == 0 && rect.right == width && rect.top == 0 && rect.bottom == height) {
                gsyBaseVideoPlayer = player
                if (mRunnable != null && currentPlayer != null) {
                    mPlayHandler.removeCallbacks(mRunnable!!)
                    mRunnable = null
                }
                if (currentPlayer == gsyBaseVideoPlayer) return true
                val screenPosition = IntArray(2)
                gsyBaseVideoPlayer.getLocationInWindow(screenPosition)
                val rangePosition = screenPosition[0]
                if (rangePosition >= 0) {
                    mRunnable?.let { mPlayHandler.removeCallbacks(it) }
                    mRunnable = PlayRunnable(gsyBaseVideoPlayer)
                    if (currentPlayer != null) {
                        currentPlayer?.initUIState()
                        currentPlayer?.resetDetailMask()
                    }
                    //降低频率
                    mPlayHandler.postDelayed(mRunnable!!, 100)
                    return true
                }
            }
        }
        return false
    }

    /**
     * 如果布局层次结构复杂，这里递归可能过深，为避免此情况，这里暂时只考虑一层的情况
     */
    private fun findRecyclerView(container: ViewGroup): RecyclerView? {
        val childCount = container.childCount
        for (index in 0 until childCount) {
            val child = container.getChildAt(index)
            if (child is RecyclerView && child.layoutManager is LinearLayoutManager) {
                return child
            }
        }
        return null
    }

    private inner class PlayRunnable(var videoView: AutomaticVideoView?) : Runnable {
        override fun run() {
            if (videoView != null && !videoView!!.isInPlayingState) {

                val videoOption =
                    SPUtils.getString(Constants.SP_HOME_OR_DETAIL_VIDEO_OPTION, Constants.VIDEO_OPTION_WIFI)
                        ?: Constants.VIDEO_OPTION_WIFI

                when (videoOption) {
                    Constants.VIDEO_OPTION_ALL -> {
                        startPlayLogic(videoView)
                    }

                    Constants.VIDEO_OPTION_WIFI -> {
                        if (NetworkUtils.isWifiConnected(HaloApp.getInstance().application)) {
                            startPlayLogic(videoView)
                        }
                    }

                    else -> {
                        //do nothing
                    }
                }
            }
        }
    }

    private fun startPlayLogic(videoView: AutomaticVideoView?) {
        videoView?.startPlayLogic()
        currentPlayer = videoView
    }

    companion object {

        fun savePlaySchedule(key: String, schedule: Long) {
            val record = SPUtils.getMap(Constants.SP_HOME_VIDEO_PLAY_RECORD)
            record[key] = schedule.toString()
            SPUtils.setMap(Constants.SP_HOME_VIDEO_PLAY_RECORD, record)
        }

        fun getPlaySchedule(key: String): Long {
            val record = SPUtils.getMap(Constants.SP_HOME_VIDEO_PLAY_RECORD)
            return record[key]?.toLong() ?: 0L
        }
    }

}