package com.gh.gamecenter.qa.video.detail

import android.content.Context
import android.os.Handler
import android.os.Looper
import android.util.AttributeSet
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.Surface
import android.view.View
import android.widget.ImageView
import android.widget.SeekBar
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import com.gh.gamecenter.R
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.entity.AdditionalParamsEntity
import com.gh.gamecenter.common.entity.NormalShareEntity
import com.gh.gamecenter.common.observer.MuteCallback
import com.gh.gamecenter.common.observer.VolumeObserver
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.databinding.LayoutForumVideoDetailVideoviewPortraitBinding
import com.gh.gamecenter.feature.entity.ForumVideoEntity
import com.gh.gamecenter.forum.home.ForumScrollCalculatorHelper
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.qa.dialog.MoreFunctionPanelDialog
import com.gh.gamecenter.video.detail.CustomManager
import com.lightgame.utils.Utils
import com.shuyu.gsyvideoplayer.utils.CommonUtil
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
import com.shuyu.gsyvideoplayer.video.base.GSYVideoViewBridge
import io.reactivex.disposables.Disposable
import java.util.*

class ForumTopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
    StandardGSYVideoPlayer(context, attrs) {
    private var mMuteCallback: MuteCallback
    private var mVolumeObserver: VolumeObserver
    private var mMuteDisposable: Disposable? = null
    private var mIsAutoPlay = false
    private lateinit var mBinding: LayoutForumVideoDetailVideoviewPortraitBinding
    var mForumVideoEntity: ForumVideoEntity? = null
    var viewModel: ForumVideoDetailViewModel? = null
    var uuid = UUID.randomUUID().toString()
    var parentTag: String = ""

    private var mMaxPlayedProgress: Int = 0
    private var mStartTrackRunnable: Runnable? = null
    private var mStopTrackRunnable: Runnable? = null

    private val mTrackHandler = Handler(Looper.getMainLooper())

    init {
        post {
            gestureDetector =
                GestureDetector(getContext().applicationContext, object : GestureDetector.SimpleOnGestureListener() {
                    override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
                        if (!mChangePosition && !mChangeVolume && !mBrightness) {
                            onClickUiToggle(e)
                        }
                        return super.onSingleTapConfirmed(e)
                    }
                })

            if (mIfCurrentIsFullscreen) {
                showBackBtn()
            } else {
                hideBackBtn()
            }

            mBinding.layoutBottom.volume.setOnClickListener { toggleMute() }
        }

        mMuteCallback = object : MuteCallback {
            override fun onMute(isMute: Boolean) {
                if (isMute) {
                    mute()
                } else {
                    unMute()
                }
            }
        }

        mVolumeObserver = VolumeObserver(mMuteCallback)

        setBackFromFullScreenListener {
            clearFullscreenLayout()
        }

        mBinding.errorBtn.setOnClickListener {
            debounceActionWithInterval(mBinding.errorBtn.id, 1000) {
                if (!com.shuyu.gsyvideoplayer.utils.NetworkUtils.isAvailable(mContext)) {
                    Utils.toast(context, "网络异常，请检查手机网络状态")
                    setViewShowState(mStartButton, INVISIBLE)
                    mBinding.errorContainer.visibility = VISIBLE
                    return@debounceActionWithInterval
                }
                startPlayLogic(false)
            }
        }
    }

    override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
        super.onProgressChanged(seekBar, progress, fromUser)
        // 记录播放进度的最大值，用于埋点上报
        if (mMaxPlayedProgress < progress) {
            mMaxPlayedProgress = progress
        }
    }

    override fun startPlayLogic() {
        super.startPlayLogic()
        if (!isLooping) {

        }
    }

    override fun init(context: Context?) {
        super.init(context)
        mBinding = LayoutForumVideoDetailVideoviewPortraitBinding.bind(this.getChildAt(0))
    }

    fun setForumVideoEntity(entity: ForumVideoEntity?) {
        this.mStopTrackRunnable = null

        this.mForumVideoEntity = entity
        mBinding.title.text = if (mIfCurrentIsFullscreen) entity?.title else ""
    }

    //这个必须配置最上面的构造才能生效
    override fun getLayoutId(): Int {
        return R.layout.layout_forum_video_detail_videoview_portrait
    }

    fun observeVolume(fragment: Fragment?) {
        fragment?.context?.applicationContext?.contentResolver?.registerContentObserver(
            android.provider.Settings.System.CONTENT_URI, true, mVolumeObserver
        )

        fragment?.fragmentManager?.registerFragmentLifecycleCallbacks(
            object : FragmentManager.FragmentLifecycleCallbacks() {
                override fun onFragmentPaused(fm: FragmentManager, f: Fragment) {
                    if (f === fragment) {
                        fragment.context?.applicationContext?.contentResolver?.unregisterContentObserver(mVolumeObserver)
                        fragment.fragmentManager?.unregisterFragmentLifecycleCallbacks(this)
                    }
                }
            }, false
        )
    }

    fun startPlayLogic(isAutoPlay: Boolean) {
        mIsAutoPlay = isAutoPlay
        violenceUpdateMuteStatus()
        if (mIsAutoPlay && mForumVideoEntity != null) {
            val seekTime = ForumScrollCalculatorHelper.getPlaySchedule(MD5Utils.getContentMD5(mForumVideoEntity?.url))
            seekOnStart = seekTime
        }
        startPlayLogic()
    }

    fun violenceUpdateMuteStatus() {
        if (mMuteDisposable != null) {
            mMuteDisposable?.dispose()
            mMuteDisposable = null
        }
        mMuteDisposable = rxTimer(25) {
            if (it >= 400) {
                mMuteDisposable?.dispose()
                mMuteDisposable = null
            }
            updateMuteStatus()
        }
    }

    fun disposableTimer() {
        if (mMuteDisposable != null && !mMuteDisposable!!.isDisposed) {
            mMuteDisposable?.dispose()
            mMuteDisposable = null
        }
    }

    private fun toggleMute() {
        if (viewModel?.videoIsMuted == true) {
            unMute(true)
        } else {
            mute(true)
        }
    }

    fun updateMuteStatus() {
        if (viewModel?.videoIsMuted == true) {
            mute()
        } else {
            unMute()
        }
    }

    private fun mute(isManual: Boolean = false) {
        viewModel?.videoIsMuted = true
        mBinding.layoutBottom.volume.setImageResource(R.drawable.ic_video_volume_off)
        CustomManager.getCustomManager(getKey()).isNeedMute = true
        SPUtils.setBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
        if (isManual) {
            Utils.toast(context, "当前处于静音状态")
            uploadVideoStreamingPlaying("点击静音")
        }
    }

    private fun unMute(isManual: Boolean = false) {
        viewModel?.videoIsMuted = false
        mBinding.layoutBottom.volume.setImageResource(R.drawable.ic_video_volume_on)
        CustomManager.getCustomManager(getKey()).isNeedMute = false
        SPUtils.setBoolean(Constants.SP_VIDEO_PLAY_MUTE, false)
        if (isManual) {
            uploadVideoStreamingPlaying("取消静音")
        }
    }

    // 重载以减少横竖屏切换的时间
    override fun checkoutState() {
        removeCallbacks(mCheckoutTask)
        postDelayed(mCheckoutTask, 300)
    }

    override fun clearFullscreenLayout() {
        super.clearFullscreenLayout()
        updateMuteStatus()
        hideBackBtn()
    }

    fun updateThumb(url: String) {
        ImageUtils.display(mBinding.thumbImage, url)
    }

    override fun touchDoubleUp(e: MotionEvent?) {
        // we do not need double click to play or pause
    }

    // 不需要弹弹窗，直接播放
    override fun showWifiDialog() {
        startPlayLogic(false)
        //val trafficVideo = PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SettingsFragment.TRAFFIC_VIDEO_SP_KEY, false)
        //if (trafficVideo) {
        // 不延迟的话 isCacheFile 可能直接返回 false
        postDelayed({
            // 这个库的 NetworkUtils.isWifiConnected 可能会触发空指针，这里换为我们自己的
            if (!com.shuyu.gsyvideoplayer.utils.NetworkUtils.isAvailable(mContext) && !gsyVideoManager.isCacheFile) {
                Utils.toast(context, "网络异常，请检查手机网络状态")
            } else if (!NetworkUtils.isWifiConnected(mContext) && !gsyVideoManager.isCacheFile) {
                Utils.toast(context, "当前为非Wi-Fi环境，请注意流量消耗")
            }
        }, 100)
        // }
    }

    override fun getGSYVideoManager(): GSYVideoViewBridge {
        CustomManager.getCustomManager(getKey()).initContext(context.applicationContext)
        return CustomManager.getCustomManager(getKey())
    }

    fun getKey(): String {
        return uuid
    }

    override fun onAutoCompletion() {

        //播放完成后判断是否已缓冲完毕,没有完成显示播放错误状态
        if (mBufferPoint != 0 && mBufferPoint != 100 && isShown) {
            gsyVideoManager.releaseMediaPlayer()
            changeUiToPreparingShow()
            postDelayed({
                if (!com.shuyu.gsyvideoplayer.utils.NetworkUtils.isAvailable(mContext)) {
                    Utils.toast(context, "网络错误，视频播放失败")
                    changeUiToError()
                }
            }, 10 * 1000)
        }
        uploadVideoStreamingPlaying("播放完毕")
        super.onAutoCompletion()
    }

    override fun onStopTrackingTouch(seekBar: SeekBar?) {
        super.onStopTrackingTouch(seekBar)
        uploadVideoStreamingPlaying("拖动")
    }

    override fun isShowNetConfirm(): Boolean {
        return (!mOriginUrl.startsWith("file") && !mOriginUrl.startsWith("android.resource") && !CommonUtil.isWifiConnected(
            context
        )
                && mNeedShowWifiTip)
    }

    override fun updateStartImage() {
        if (mStartButton is ImageView) {
            val imageView = mStartButton as ImageView
            when (mCurrentState) {
                GSYVideoView.CURRENT_STATE_PLAYING -> imageView.setImageResource(R.drawable.ic_video_pause)
                GSYVideoView.CURRENT_STATE_ERROR -> imageView.setImageResource(R.drawable.ic_video_play)
                else -> imageView.setImageResource(R.drawable.ic_video_play)
            }
        }
    }

    override fun setStateAndUi(state: Int) {
        if (state != currentState
            && state == CURRENT_STATE_PLAYING
            && currentState != CURRENT_STATE_PLAYING_BUFFERING_START) {// 上报开始视频播放埋点
            // 视频停止播放后再恢复播放的间隔时间未超过3秒，则取消上报结束视频播放埋点
            mStopTrackRunnable?.let { runnable ->
                mTrackHandler.removeCallbacks(runnable)
            }

            mForumVideoEntity?.let {
                val startTrackRunnable = Runnable {
                    SensorsBridge.trackVideoStartPlaying(
                        articleId = it.id,
                        bbsId = it.bbs?.id ?: "",
                        bbsType = it.bbs?.typeChinese ?: "综合论坛",
                        customerType = it.user.auth?.text ?: "",
                        videoId = it.id,
                        playType = "视频贴",
                        gameForumType = it.bbs?.game?.categoryChinese ?: "",
                        activityTag = it.tagActivityName,
                        articleType = it.typeChinese
                    )
                    mStartTrackRunnable = null
                }.also {
                    mStartTrackRunnable = it
                }
                // 埋点要求视频播放3秒后再上报埋点
                mTrackHandler.postDelayed(startTrackRunnable, 3000)
            }
        } else if (currentState != state
            && (state == CURRENT_STATE_AUTO_COMPLETE
                    || state == CURRENT_STATE_ERROR
                    || state == CURRENT_STATE_PAUSE
                    || (currentState == CURRENT_STATE_PLAYING && state == CURRENT_STATE_NORMAL))
        ) {// 上报结束视频播放埋点
            // 从开始播放视频到停止播放视频的间隔时间没有超过3秒，则取消上报开始视频播放埋点
            val startTrackRunnable = this.mStartTrackRunnable
            if (startTrackRunnable != null) {
                mTrackHandler.removeCallbacks(startTrackRunnable)
                mStartTrackRunnable = null
            } else {
                mForumVideoEntity?.let {
                    val stopTrackRunnable = Runnable {
                        SensorsBridge.trackVideoEndPlaying(
                            articleId = it.id,
                            bbsId = it.bbs?.id ?: "",
                            bbsType = it.bbs?.typeChinese ?: "综合论坛",
                            customerType = it.user.auth?.text ?: "",
                            videoId = it.id,
                            playType = "视频贴",
                            gameForumType = it.bbs?.game?.categoryChinese ?: "",
                            activityTag = it.tagActivityName,
                            articleType = it.typeChinese,
                            result = if (mMaxPlayedProgress >= 95) "是" else "否"
                        )
                    }.also {
                        this.mStopTrackRunnable = it
                    }
                    // 埋点要求停止视频播放3秒后再上报埋点
                    mTrackHandler.postDelayed(stopTrackRunnable, 3000)
                }
            }
        }

        super.setStateAndUi(state)

        if (state == CURRENT_STATE_AUTO_COMPLETE) {
            hideAllWidget()
            mBinding.replayContainer.root.visibility = View.VISIBLE
            mTopContainer.visibility = View.VISIBLE
            mBinding.replayContainer.replayTv.setOnClickListener {
                startButton.performClick()
                violenceUpdateMuteStatus()
                uploadVideoStreamingPlaying("重新播放")
            }
            mBinding.replayContainer.shareTv.setOnClickListener {
                share()
            }
        } else {
            mBinding.replayContainer.root.visibility = View.GONE
        }
    }

    private fun share() {
        mForumVideoEntity?.let {
            val params = AdditionalParamsEntity().apply {
                contentType = "视频帖"
                contentId = it.id
                bbsId = it.bbs?.id ?: ""
                bbsType = it.bbs?.typeChinese ?: "综合论坛"
                customerType = it.user.auth?.text ?: ""
                activityTagName = it.tagActivityName
                gameForumType = it.bbs?.game?.categoryChinese ?: ""
                refUserId = UserManager.getInstance().userId
            }
            val shareEntity = NormalShareEntity(
                id = it.id,
                shareUrl = if (isPublishEnv()) {
                    "https://m.ghzs666.com/video/${it.id}"
                } else {
                    "https://dev-and-static.ghzs66.com/page/video_play/video/video.html?video=${it.id}"
                },
                shareIcon = it.poster,
                shareTitle = it.title,
                shareSummary = it.des,
                shareEntrance = ShareUtils.ShareEntrance.video,
                additionalParams = params
            )
            MoreFunctionPanelDialog.showMoreDialog(
                context as AppCompatActivity,
                arrayListOf(),
                shareEntity.shareTitle,
                shareEntity,
                "",
                parentTag
            )
        }
    }

    private fun showBackBtn() {
        mTopContainer.background = ContextCompat.getDrawable(context, com.shuyu.gsyvideoplayer.R.drawable.video_title_bg)
        mBinding.back.visibility = View.VISIBLE
        mForumVideoEntity?.run {
            mBinding.title.text = title
        }
    }

    private fun hideBackBtn() {
        mTopContainer?.setBackgroundResource(0)
        mBinding.back.visibility = View.GONE
        mBinding.title.text = ""
    }

    override fun getEnlargeImageRes(): Int {
        return R.drawable.ic_video_enter_full_screen
    }

    override fun getShrinkImageRes(): Int {
        return R.drawable.ic_video_exit_full_screen
    }

    /******************* 下方两个重载方法，在播放开始前不屏蔽封面，不需要可屏蔽 ********************/

    override fun onSurfaceUpdated(surface: Surface) {
        super.onSurfaceUpdated(surface)
        if (mThumbImageViewLayout != null && mThumbImageViewLayout.visibility == View.VISIBLE) {
            mThumbImageViewLayout.visibility = View.INVISIBLE
            uploadVideoStreamingPlaying("开始播放")
        }
    }

    override fun setViewShowState(view: View?, visibility: Int) {
        if (view === mThumbImageViewLayout && visibility != View.VISIBLE) {
            return
        }
        super.setViewShowState(view, visibility)
    }

    /********************************各类UI的状态显示*********************************************/

    override fun changeUiToNormal() {
        super.changeUiToNormal()
        mBinding.errorContainer.visibility = View.GONE
    }

    override fun changeUiToPreparingShow() {
        super.changeUiToPreparingShow()
        mBinding.errorContainer.visibility = View.GONE
    }

    override fun changeUiToPlayingShow() {
        super.changeUiToPlayingShow()
        mBinding.errorContainer.visibility = View.GONE
    }

    override fun changeUiToPauseShow() {
        super.changeUiToPauseShow()
        mBinding.errorContainer.visibility = View.GONE
    }

    override fun changeUiToCompleteShow() {
        super.changeUiToCompleteShow()
        mBinding.errorContainer.visibility = View.GONE
    }

    override fun changeUiToError() {
        super.changeUiToError()
        setViewShowState(mStartButton, View.INVISIBLE)
        mBinding.errorContainer.visibility = View.VISIBLE
    }

    override fun netWorkErrorLogic() {
        super.netWorkErrorLogic()
        Utils.toast(context, "网络错误，视频播放失败")
        setViewShowState(mStartButton, View.INVISIBLE)
        mBinding.errorContainer.visibility = View.VISIBLE
    }

    //监控播放错误
    override fun onError(what: Int, extra: Int) {
        super.onError(what, extra)
        Utils.toast(context, "网络错误，视频播放失败")
        setViewShowState(mStartButton, View.INVISIBLE)
        mBinding.errorContainer.visibility = View.VISIBLE

        // 部分设备由于MediaCodec实例达到上限导致 CodecException: Error 0xfffffff4，在此处尝试释放所有视频
        CustomManager.clearAllVideo()
    }

    override fun releaseVideos() {
        uploadVideoStreamingPlaying("结束播放")
        CustomManager.releaseAllVideos(getKey())
    }

    override fun onVideoPause() {
        super.onVideoPause()
        uploadVideoStreamingPlaying("暂停播放")
    }

    fun setVideoStatus(status: String) {
        if (status == "pending" || status == "fail") {
            mBinding.pendingView.text = if (status == "pending") "审核中...请耐心等待" else "审核不通过"
            mBinding.pendingView.visibility = View.VISIBLE
            mBottomContainer?.visibility = View.GONE
            mStartButton?.visibility = View.GONE
            mBottomProgressBar?.visibility = View.GONE
        } else {
            mBinding.pendingView.visibility = View.GONE
            mBottomContainer?.visibility = View.VISIBLE
            mStartButton?.visibility = View.VISIBLE
            mBottomProgressBar?.visibility = View.VISIBLE
        }
    }

    fun getCurrentPosition(): Long {
        return mCurrentPosition
    }

    fun uploadVideoStreamingPlaying(action: String) {
        /*if (video == null || video?.url.isNullOrEmpty()) return
        runOnIoThread {
            val isLandscape = mOrientationUtils != null
            val videoPlayModel = if (!isLandscape) {
                if (mIsAutoPlay) "自动播放" else "点击播放"
            } else "全屏播放"
            val videoPlayTs = currentPositionWhenPlaying / 1000
            val videoTotalTime = duration / 1000
            val progress = if (videoTotalTime != 0) videoPlayTs.toFloat() / videoTotalTime.toFloat() * 100 else 0f
            if (mContentLength == 0.0) {
                mContentLength = ExoCacheManager.getContentLength(video!!.url) / 1024.0 / 1024.0
            }

            //https://exoplayer.dev/hello-world.html#a-note-on-threading
            runOnUiThread {
                LogUtils.uploadTopVideoStreamingPlaying(action, video?.videoId, video?.title, viewModel?.game?.id, viewModel?.game?.name,
                        videoPlayModel, videoPlayStatus(), mContentLength, videoTotalTime, videoPlayTs, progress.toInt())
            }
        }*/
    }

    override fun onLossAudio() {
        if (!CustomManager.getCustomManager(getKey()).isNeedMute) {
            super.onLossAudio()
        }
    }

    override fun onLossTransientAudio() {
        // transient audio lost 代表的是短暂的 audio focus lost，不暂停播放。不然视频很容易就处于暂停状态
        // onLossAudio 回调的时候再决定是否需要暂停
    }

    private fun videoPlayStatus(): String {
        return when (mCurrentState) {
            CURRENT_STATE_PLAYING, CURRENT_STATE_PREPAREING, CURRENT_STATE_PLAYING_BUFFERING_START -> "play"
            GSYVideoView.CURRENT_STATE_PAUSE -> "pause"
            else -> ""
        }
    }
}