package com.gh.gamecenter.gamecollection.detail

import android.content.Context
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.LinearLayout
import android.widget.SeekBar
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import com.gh.common.util.NewLogUtils
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.utils.MD5Utils
import com.gh.gamecenter.entity.GamesCollectionDetailEntity
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.video.StandardGSYVideoPlayer
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
import com.shuyu.gsyvideoplayer.video.base.GSYVideoViewBridge
import io.reactivex.disposables.Disposable
import java.text.DecimalFormat
import java.util.*

class GameCollectionVideoView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
    StandardGSYVideoPlayer(context, attrs) {

    private var mMuteCallback: MuteCallback
    private var mVolumeObserver: VolumeObserver

    var gameName = ""
    var gameCollectionId = ""
    var gameCollectionTitle = ""
    var video: GamesCollectionDetailEntity.Video? = null
    var viewModel: GameCollectionDetailViewModel? = null
    var uuid = UUID.randomUUID().toString()
    private var mMuteDisposable: Disposable? = null
    private var mIsAutoPlay = false
    private var mIsManualStop = false

    private var volume: ImageView = findViewById(R.id.volume)
    private var errorBtn: TextView = findViewById(R.id.errorBtn)
    private var errorContainer: LinearLayout = findViewById(R.id.errorContainer)
    private var replayContainer: View = findViewById(R.id.replayContainer)
    private var replayIv: ImageView = findViewById(R.id.replayIv)
    private var back: ImageView = findViewById(R.id.back)

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

            volume.setOnClickListener { toggleMute() }
        }

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

        mVolumeObserver = VolumeObserver(mMuteCallback)

        setBackFromFullScreenListener {
            clearFullscreenLayout()
        }

        errorBtn.setOnClickListener {
            debounceActionWithInterval(errorBtn.id, 1000) {
                if (!com.shuyu.gsyvideoplayer.utils.NetworkUtils.isAvailable(mContext)) {
                    Utils.toast(context, "网络异常，请检查手机网络状态")
                    setViewShowState(mStartButton, INVISIBLE)
                    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()
        logVideoEvent("video_game_collect_detail_play", if (isAutoPlay) "自动播放" else "手动播放")
        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
        volume.setImageResource(R.drawable.ic_video_volume_off)
        CustomManager.getCustomManager(getKey()).isNeedMute = true
        if (isManual) {
            Utils.toast(context, "当前处于静音状态")
            logVideoEvent("video_game_collect_detail_mute")
        }
    }

    private fun unMute(isManual: Boolean = false) {
        viewModel?.videoIsMuted = false
        volume.setImageResource(R.drawable.ic_video_volume_on)
        CustomManager.getCustomManager(getKey()).isNeedMute = false
        if (isManual) {
            logVideoEvent("video_game_collect_detail_mute_cancel")
        }
    }

    // 重载以减少横竖屏切换的时间
    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()

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

    override fun onStopTrackingTouch(seekBar: SeekBar?) {
        super.onStopTrackingTouch(seekBar)
        logVideoEvent("video_game_collect_detail_progress_drag")
    }

    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) {
        super.setStateAndUi(state)

        if (state == CURRENT_STATE_AUTO_COMPLETE) {
            hideAllWidget()
            replayContainer.visibility = View.VISIBLE
            mTopContainer.visibility = View.VISIBLE
            replayIv.setOnClickListener {
                startButton.performClick()
                violenceUpdateMuteStatus()
                logVideoEvent("video_game_collect_detail_play", "再次播放")
            }
            updateThumb(video!!.poster)
        } else {
            replayContainer.visibility = View.GONE
        }
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

    override fun releaseVideos() {
        CustomManager.releaseAllVideos(getKey())
    }

    override fun onVideoPause() {
        super.onVideoPause()
        logVideoEvent("video_game_collect_detail_stop", stopAction = if (mIsManualStop) "手动停止" else "自动停止")
        mIsManualStop = false
    }

    override fun onVideoResume(seek: Boolean) {
        super.onVideoResume(seek)
        logVideoEvent("video_game_collect_detail_play", "继续播放")
    }

    override fun onClick(v: View) {
        when (v.id) {
            R.id.start -> {
                when (currentState) {
                    GSYVideoView.CURRENT_STATE_PLAYING -> mIsManualStop = true

                    GSYVideoView.CURRENT_STATE_PAUSE -> logVideoEvent("video_game_collect_detail_play", "继续播放")
                }
                super.onClick(v)
            }
            else -> super.onClick(v)
        }
    }

    fun getCurrentPosition(): Long {
        return mCurrentPosition
    }

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

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

    fun logVideoEvent(event: String, playAction: String = "", stopAction: String = "") {
        if (video == null || video?.url.isNullOrEmpty()) return
        val videoPlayTs = currentPositionWhenPlaying / 1000
        val videoTotalTime = duration / 1000
        val progress = if (videoTotalTime != 0) videoPlayTs.toFloat() / videoTotalTime.toFloat() * 100 else 0f
        //https://exoplayer.dev/hello-world.html#a-note-on-threading
        runOnIoThread {
            NewLogUtils.logGameCollectionVideoEvent(
                event,
                gameCollectionTitle,
                gameCollectionId,
                DecimalFormat("#.00").format(progress).toDouble(),
                videoPlayTs,
                playAction,
                stopAction
            )
        }
    }
}