package com.gh.gamecenter.gamedetail.video

import android.app.Activity
import android.content.Context
import android.media.AudioManager
import android.util.AttributeSet
import android.view.*
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.SeekBar
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import com.gh.common.util.LogUtils
import com.gh.download.cache.ExoCacheManager
import com.gh.gamecenter.R
import com.gh.gamecenter.common.observer.MuteCallback
import com.gh.gamecenter.common.observer.VolumeObserver
import com.gh.gamecenter.common.utils.ImageUtils
import com.gh.gamecenter.common.utils.NetworkUtils
import com.gh.gamecenter.common.utils.debounceActionWithInterval
import com.gh.gamecenter.common.utils.rxTimer
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.runOnUiThread
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.core.utils.MtaHelper
import com.gh.gamecenter.core.utils.StringUtils
import com.gh.gamecenter.entity.GameDetailEntity
import com.gh.gamecenter.gamedetail.GameDetailViewModel
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
import com.gh.gamecenter.video.detail.CustomManager
import com.lightgame.utils.Utils
import com.shuyu.gsyvideoplayer.utils.CommonUtil
import com.shuyu.gsyvideoplayer.utils.Debuger
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 TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
    StandardGSYVideoPlayer(context, attrs) {

    private var mMuteCallback: MuteCallback
    private var mVolumeObserver: VolumeObserver? = null

    var gameName = ""
    var video: GameDetailEntity.Video? = null
    var viewModel: GameDetailViewModel? = null
    var uuid = UUID.randomUUID().toString()
    private var mMuteDisposable: Disposable? = null
    private var mContentLength = 0.0
    private var mIsAutoPlay = false

    val combinedTitleAndId: String
        get() = StringUtils.combineTwoString(video?.title, video?.videoId)

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

            findViewById<View>(R.id.volume).setOnClickListener { toggleMute() }
        }

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

        if (!isInEditMode) {
            mVolumeObserver = VolumeObserver(mMuteCallback)
        }

        setBackFromFullScreenListener {
            if (it.id == R.id.fullscreen) {
                MtaHelper.onEvent("游戏详情_顶部视频", "${getMtaKeyPrefix()}-退出全屏", combinedTitleAndId)
            } else if (it.id == R.id.back) {
                MtaHelper.onEvent("游戏详情_顶部视频", "${getMtaKeyPrefix()}-点击返回", combinedTitleAndId)
            }
            clearFullscreenLayout()
        }

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

    //这个必须配置最上面的构造才能生效
    override fun getLayoutId(): Int {
        return R.layout.layout_game_detail_video_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 (isAutoPlay) {
            MtaHelper.onEvent("游戏详情_顶部视频", "视频播放方式", "自动播放")
            MtaHelper.onEvent("游戏详情_顶部视频", "顶部视频-自动播放", combinedTitleAndId)
        } else {
            MtaHelper.onEvent("游戏详情_顶部视频", "视频播放方式", "手动播放")
        }
        if (isAutoPlay) {
            val seekTime = ScrollCalculatorHelper.getPlaySchedule(MD5Utils.getContentMD5(video?.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
        findViewById<ImageView>(R.id.volume)?.setImageResource(R.drawable.ic_game_detail_volume_off)
        CustomManager.getCustomManager(getKey()).isNeedMute = true
        if (isManual) {
            Utils.toast(context, "当前处于静音状态")
            uploadVideoStreamingPlaying("点击静音")
            MtaHelper.onEvent("游戏详情_顶部视频", "${getMtaKeyPrefix()}-点击静音", combinedTitleAndId)
        }
    }

    private fun unMute(isManual: Boolean = false) {
        viewModel?.videoIsMuted = false
        findViewById<ImageView>(R.id.volume)?.setImageResource(R.drawable.ic_game_detail_volume_on)
        CustomManager.getCustomManager(getKey()).isNeedMute = false
        mAudioManager.requestAudioFocus(
            onAudioFocusChangeListener,
            AudioManager.STREAM_MUSIC,
            AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
        )
        if (isManual) {
            uploadVideoStreamingPlaying("取消静音")
            MtaHelper.onEvent("游戏详情_顶部视频", "${getMtaKeyPrefix()}-解除静音", combinedTitleAndId)
        }
    }

    override fun onSeekComplete() {
        super.onSeekComplete()
        MtaHelper.onEvent("游戏详情_顶部视频", "${getMtaKeyPrefix()}-拖动进度条", combinedTitleAndId)
    }

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

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

    fun updateThumb(url: String) {
        ImageUtils.picasso.load(url).fit().into(findViewById<ImageView>(R.id.thumbImage))
    }

    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() {
        // 这个方法在内核被释放时也会被回调，所以可以用来统计播放量和播放时长
        val playedTime = (gsyVideoManager.currentPosition / 1000).toInt()

        MtaHelper.onEventWithTime("视频播放量_按位置", playedTime, "游戏详情-顶部视频", combinedTitleAndId)
        MtaHelper.onEventWithTime("视频播放量_游戏加位置", playedTime, gameName, "游戏详情-顶部视频")

        //播放完成后判断是否已缓冲完毕,没有完成显示播放错误状态
        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_game_detail_pause)
                GSYVideoView.CURRENT_STATE_ERROR -> imageView.setImageResource(R.drawable.ic_game_detail_play)
                else -> imageView.setImageResource(R.drawable.ic_game_detail_play)
            }
        }
    }

    override fun startPrepare() {
        if (gsyVideoManager.listener() != null) {
            gsyVideoManager.listener().onCompletion()
        }
        if (mVideoAllCallBack != null) {
            Debuger.printfLog("onStartPrepared")
            mVideoAllCallBack.onStartPrepared(mOriginUrl, mTitle, this)
        }
        gsyVideoManager.setListener(this)
        gsyVideoManager.playTag = mPlayTag
        gsyVideoManager.playPosition = mPlayPosition
        if (viewModel?.videoIsMuted == false) {
            mAudioManager.requestAudioFocus(
                onAudioFocusChangeListener,
                AudioManager.STREAM_MUSIC,
                AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
            )
        }
        try {
            if (mContext is Activity) {
                (mContext as Activity).window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        mBackUpPlayingBufferState = -1
        gsyVideoManager.prepare(
            mUrl,
            if (mMapHeadData == null) HashMap() else mMapHeadData,
            mLooping,
            mSpeed,
            mCache,
            mCachePath,
            mOverrideExtension
        )
        setStateAndUi(CURRENT_STATE_PREPAREING)
    }

    override fun setStateAndUi(state: Int) {
        super.setStateAndUi(state)

        if (state == CURRENT_STATE_AUTO_COMPLETE) {
            hideAllWidget()
            findViewById<LinearLayout>(R.id.replayContainer)?.visibility = View.VISIBLE
            mTopContainer.visibility = View.VISIBLE
            findViewById<ImageView>(R.id.replayIv).setOnClickListener {
                MtaHelper.onEvent("游戏详情_顶部视频", "${getMtaKeyPrefix()}-点击重新播放", combinedTitleAndId)
                startButton.performClick()
                violenceUpdateMuteStatus()
                uploadVideoStreamingPlaying("重新播放")
            }
            updateThumb(video!!.poster)
        } else if (state == CURRENT_STATE_PLAYING) {
            if (!CustomManager.getCustomManager(getKey()).isNeedMute) {
                mAudioManager.requestAudioFocus(
                    onAudioFocusChangeListener,
                    AudioManager.STREAM_MUSIC,
                    AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
                )
            }
        } else {
            findViewById<LinearLayout>(R.id.replayContainer)?.visibility = View.GONE
        }
    }

    private fun showBackBtn() {
        mTopContainer.background = ContextCompat.getDrawable(context, R.drawable.video_title_bg)
        findViewById<View>(R.id.back)?.visibility = View.VISIBLE
    }

    private fun hideBackBtn() {
        mTopContainer?.setBackgroundResource(0)
        findViewById<View>(R.id.back)?.visibility = View.GONE
    }

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

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

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        if (!isIfCurrentIsFullscreen) {
            parent.requestDisallowInterceptTouchEvent(true)
        }
        return super.onInterceptTouchEvent(ev)
    }

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

    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()
        findViewById<LinearLayout>(R.id.errorContainer)?.visibility = View.GONE
    }

    override fun changeUiToPreparingShow() {
        super.changeUiToPreparingShow()
        findViewById<LinearLayout>(R.id.errorContainer)?.visibility = View.GONE
    }

    override fun changeUiToPlayingShow() {
        super.changeUiToPlayingShow()
        findViewById<LinearLayout>(R.id.errorContainer)?.visibility = View.GONE
    }

    override fun changeUiToPauseShow() {
        super.changeUiToPauseShow()
        findViewById<LinearLayout>(R.id.errorContainer)?.visibility = View.GONE
    }

    override fun changeUiToCompleteShow() {
        super.changeUiToCompleteShow()
        findViewById<LinearLayout>(R.id.errorContainer)?.visibility = View.GONE
    }

    override fun changeUiToError() {
        super.changeUiToError()
        setViewShowState(mStartButton, View.INVISIBLE)
        findViewById<LinearLayout>(R.id.errorContainer)?.visibility = View.VISIBLE
    }

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

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

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

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

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

    override fun onClick(v: View) {
        when (v.id) {
            R.id.start -> {
                if (currentState == GSYVideoView.CURRENT_STATE_PLAYING) {
                    MtaHelper.onEvent("游戏详情_顶部视频", "${getMtaKeyPrefix()}-点击暂停", combinedTitleAndId)
                } else {
                    MtaHelper.onEvent("游戏详情_顶部视频", "${getMtaKeyPrefix()}-点击播放", combinedTitleAndId)
                }
                super.onClick(v)
            }
            else -> super.onClick(v)
        }
    }

    private fun getMtaKeyPrefix() = if (mIfCurrentIsFullscreen) "顶部视频（全屏）" else "顶部视频"

    fun getCurrentPosition(): Long {
        return mCurrentPosition
    }

    fun uploadVideoStreamingPlaying(action: String) {
        if (video == null || video?.url.isNullOrEmpty()) return
        runOnIoThread(isHeavyWightTask = true) {
            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()
                )
            }
        }
    }

    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 -> ""
        }
    }
}