package com.gh.gamecenter.home.video

import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.Surface
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import com.facebook.drawee.generic.RoundingParams
import com.facebook.drawee.view.SimpleDraweeView
import com.gh.common.util.LogUtils
import com.gh.download.cache.ExoCacheManager
import com.gh.gamecenter.R
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.ImageUtils
import com.gh.gamecenter.common.utils.countDownTimer
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.rxTimer
import com.gh.gamecenter.common.view.DrawableView
import com.gh.gamecenter.common.view.RadiusCardView
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.runOnUiThread
import com.gh.gamecenter.core.utils.RandomUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.doOnEnd
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.video.detail.CustomManager
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
import com.shuyu.gsyvideoplayer.video.base.GSYVideoViewBridge
import io.reactivex.disposables.Disposable
import java.util.*

class AutomaticVideoView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
    StandardGSYVideoPlayer(context, attrs) {
    var thumbImage: SimpleDraweeView = findViewById(R.id.thumbImage)
    var containerView: RadiusCardView = findViewById(R.id.container)
    var detailBtn: TextView? = null
    var isMute = true
    private var mIsFirstPlay = true
    private var mMuteDisposable: Disposable? = null
    private var mMaskDisposable: Disposable? = null
    private val mUUID = UUID.randomUUID().toString()
    private var mShouldShowMask = true
    private var mContentLength = 0.0
    private var mGameEntity: GameEntity? = null
    private var mPlaceholderColor: String? = null
    private var mClickListener: OnClickListener? = null
    private var mRandomPlaceholderColor = 0
    private var mVideoViewRadius = 6F
    private var mIsBottomRightAngle = true
    private var mLastGetContentLengthTime = 0L
    private var mIsSurfaceSizeChanged = false

    init {
        val array = context.obtainStyledAttributes(attrs, R.styleable.AutomaticVideoView)
        mVideoViewRadius = array.getFloat(R.styleable.AutomaticVideoView_avRadius, 6F)
        mIsBottomRightAngle = array.getBoolean(R.styleable.AutomaticVideoView_avBottomRightAngle, true)

        val bottomAngle = if (mIsBottomRightAngle) 0F else mVideoViewRadius
        val roundingParams =
            RoundingParams().setRoundAsCircle(false)
        thumbImage.hierarchy.roundingParams = roundingParams

        containerView.setRadius(mVideoViewRadius, mVideoViewRadius, bottomAngle, bottomAngle)
        array.recycle()
    }

    override fun getLayoutId(): Int {
        return R.layout.empty_control_video
    }

    fun setParamsData(entity: GameEntity?, color: String?, isOnlyTop: Boolean = false) {
        mGameEntity = entity
        mPlaceholderColor = color
        setPlaceholderColor(mThumbImageViewLayout, false)
    }

    fun startPlayLogic(showMask: Boolean) {
        mShouldShowMask = showMask
        startPlayLogic()
    }

    override fun startPlayLogic() {
        if (mVideoAllCallBack != null) {
            mVideoAllCallBack.onClickStartThumb(mOriginUrl, mTitle, this)
        }
        prepareVideo()
        if (mIsFirstPlay) {
            isMute = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
            mIsFirstPlay = false
        }
        violenceUpdateMuteStatus()
        resetDetailMask()
    }

    private fun violenceUpdateMuteStatus() {
        if (mMuteDisposable != null) {
            mMuteDisposable?.dispose()
            mMuteDisposable = null
        }
        mMuteDisposable = rxTimer(25) {
            if (it >= 400) {
                mMuteDisposable?.dispose()
                mMuteDisposable = null
            }
            if (isMute) {
                mute()
            } else {
                unMute()
            }
        }
    }

    fun mute() {
        isMute = true
        CustomManager.getCustomManager(getKey()).isNeedMute = true
    }

    fun unMute() {
        isMute = false
        CustomManager.getCustomManager(getKey()).isNeedMute = false
    }

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

    private fun showDetailMask() {
        detailBtn = (parent as ViewGroup).findViewById(R.id.detailBtn)
        if (mMaskDisposable != null) {
            mMaskDisposable?.dispose()
            mMaskDisposable = null
        }
        setPlaceholderColor(detailBtn)
        mMaskDisposable = countDownTimer(5) { finish, _ ->
            if (finish) {
                val offset = 44f.dip2px().toFloat()
                containerView.setRadius(
                    mVideoViewRadius,
                    mVideoViewRadius,
                    if (mIsBottomRightAngle) 0F else mVideoViewRadius,
                    if (mIsBottomRightAngle) 0F else mVideoViewRadius
                )

                detailBtn?.let { mask ->
                    var params = mask.layoutParams as ConstraintLayout.LayoutParams
                    params.height = 0
                    mask.layoutParams = params
                    mask.alpha = 0f
                    mask.visibility = VISIBLE
                    val heightAnimator = ValueAnimator.ofFloat(0F, offset).apply {
                        addUpdateListener {
                            params = mask.layoutParams as ConstraintLayout.LayoutParams
                            params.height = (it.animatedValue as Float).toInt()
                            mask.layoutParams = params
                        }
                    }
                    val alphaAnimator = ValueAnimator.ofFloat(0F, 1F).apply {
                        addUpdateListener {
                            mask.alpha = it.animatedValue as Float
                        }
                    }
                    val animatorSet = AnimatorSet()
                    animatorSet.playTogether(heightAnimator, alphaAnimator)
                    animatorSet.duration = 300L
                    animatorSet.doOnEnd {
                        uploadVideoStreamingPlaying("出现遮罩")
                    }
                    animatorSet.start()
                }
            }
        }
    }

    private fun setPlaceholderColor(view: View?, isOnlyTop: Boolean = true) {
        if (!mPlaceholderColor.isNullOrEmpty()) {
            try {
                //去掉透明度
                val color = if (mPlaceholderColor!!.length == 9) {
                    "#${mPlaceholderColor!!.substring(3)}"
                } else {
                    mPlaceholderColor
                }
                if (color!!.length < 7) {
                    setRandomBackground(view, isOnlyTop)
                } else {
                    val topRadius = if (isOnlyTop) 0F else mVideoViewRadius
                    val drawable = DrawableView.getCornerDrawable(
                        Color.parseColor(color),
                        topRadius,
                        topRadius,
                        mVideoViewRadius,
                        mVideoViewRadius
                    )
                    view?.background = drawable
                }
            } catch (e: Exception) {
                setRandomBackground(view, isOnlyTop)
            }
        } else {
            setRandomBackground(view, isOnlyTop)
        }
    }

    private fun setRandomBackground(view: View?, isOnlyTop: Boolean = true) {
        if (mRandomPlaceholderColor == 0) {
            mRandomPlaceholderColor = RandomUtils.getRandomPlaceholderColor()
        }
        val topRadius = if (isOnlyTop) 0F else mVideoViewRadius
        val drawable = DrawableView.getCornerDrawable(
            ContextCompat.getColor(context, mRandomPlaceholderColor),
            topRadius,
            topRadius,
            mVideoViewRadius,
            mVideoViewRadius
        )
        view?.background = drawable
    }

    fun resetDetailMask() {
        detailBtn?.visibility = View.GONE
        containerView.setRadius(
            mVideoViewRadius,
            mVideoViewRadius,
            if (mIsBottomRightAngle) 0F else mVideoViewRadius,
            if (mIsBottomRightAngle) 0F else mVideoViewRadius
        )
        if (mMaskDisposable != null && !mMaskDisposable!!.isDisposed) {
            mMaskDisposable?.dispose()
            mMaskDisposable = null
        }
    }

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

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

        mCurrentState = state
        if (state == CURRENT_STATE_NORMAL && isCurrentMediaListener || state == CURRENT_STATE_AUTO_COMPLETE || state == CURRENT_STATE_ERROR) {
            mHadPrepared = false
        }

        when (mCurrentState) {
            CURRENT_STATE_NORMAL -> {
                if (isCurrentMediaListener) {
                    cancelProgressTimer()
                    gsyVideoManager.stop()
                    mBufferPoint = 0
                    mSaveChangeViewTIme = 0
                    if (mAudioManager != null) {
                        mAudioManager.abandonAudioFocus(onAudioFocusChangeListener)
                    }
                }
                releaseNetWorkState()
            }

            CURRENT_STATE_PREPAREING -> resetProgressAndTime()
            CURRENT_STATE_PLAYING -> if (isCurrentMediaListener) {
                startProgressTimer()
            }

            CURRENT_STATE_PAUSE -> {
                startProgressTimer()
            }

            CURRENT_STATE_ERROR -> if (isCurrentMediaListener) {
                gsyVideoManager.stop()
            }

            CURRENT_STATE_AUTO_COMPLETE -> {
                cancelProgressTimer()
            }
        }
        resolveUIState(state)
        if (mGsyStateUiListener != null) {
            mGsyStateUiListener.onStateChanged(state)
        }
    }

    override fun setProgressAndTime(
        progress: Int,
        secProgress: Int,
        currentTime: Int,
        totalTime: Int,
        forceChange: Boolean
    ) {
        if (mGSYVideoProgressListener != null && mCurrentState == CURRENT_STATE_PLAYING) {
            mGSYVideoProgressListener.onProgress(progress, secProgress, currentTime, totalTime)
        }

        // https://jira.shanqu.cc/browse/GHZS-4986
        // 参考 https://blog.csdn.net/qq_22706515/article/details/135296398
        // 处理部分设备下拉推送自动弹出时有声音无画面，视频画面没有正确渲染（onSurfaceSizeChanged没有调用）
        // 需要循环向上调用 requestLayout 重新创建 surface
        if (currentState == CURRENT_STATE_PLAYING || currentState == CURRENT_STATE_PLAYING_BUFFERING_START) {
            if (!mIsSurfaceSizeChanged) {
                try {
                    requestLayoutLoop(this)
                } catch (e: Exception) {
                    onCompletion()
                } catch (o: OutOfMemoryError) {
                    onCompletion()
                }
                return
            }
        }
    }

    // 一直循环向上调用requestLayout
    private fun requestLayoutLoop(obj: Any?) {
        if (obj is View) {
            obj.requestLayout()
            requestLayoutLoop(obj.parent)
        }
    }

    override fun onSurfaceSizeChanged(surface: Surface?, width: Int, height: Int) {
        super.onSurfaceSizeChanged(surface, width, height)
        mIsSurfaceSizeChanged = true
    }

    override fun addTextureView() {
        super.addTextureView()
        mIsSurfaceSizeChanged = false
    }

    override fun resolveUIState(state: Int) {
        if ((state == CURRENT_STATE_NORMAL || state == CURRENT_STATE_AUTO_COMPLETE || state == CURRENT_STATE_ERROR)
            && thumbImageViewLayout.visibility != View.VISIBLE
        ) {
            setViewShowState(thumbImageViewLayout, VISIBLE)
        }
    }

    override fun onAutoCompletion() {
        super.onAutoCompletion()
        uploadVideoStreamingPlaying("播放完毕")
    }

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

    fun getKey(): String {
        return mUUID
    }

    fun getUrl(): String {
        return mUrl
    }

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

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

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

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

    override fun touchSurfaceMoveFullLogic(absDeltaX: Float, absDeltaY: Float) {
        super.touchSurfaceMoveFullLogic(absDeltaX, absDeltaY)
        //不给触摸快进，如果需要，屏蔽下方代码即可
        mChangePosition = false
        //不给触摸音量，如果需要，屏蔽下方代码即可
        mChangeVolume = false
        //不给触摸亮度，如果需要，屏蔽下方代码即可
        mBrightness = false
    }

    override fun touchDoubleUp(e: MotionEvent?) {

    }

    fun getCurrentPosition(): Long {
        return mCurrentPosition
    }

    fun setCurrentPosition(mCurrentPosition: Long) {
        this.mCurrentPosition = mCurrentPosition
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        disposableTimer()
        resetDetailMask()
    }

    fun setOnVideoClickListener(listener: OnClickListener) {
        mClickListener = listener
    }

    override fun onClick(v: View?) {
        //super.onClick(v)
        mClickListener?.onClick(v)
    }

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

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

    fun uploadVideoStreamingPlaying(action: String, hasDetailMask: Boolean? = null) {
        if (mGameEntity == null) return
        val topVideo = mGameEntity?.topVideo
        if (topVideo == null || topVideo.url.isEmpty()) return
        val videoPlayTs = currentPositionWhenPlaying / 1000
        val videoTotalTime = duration / 1000
        runOnIoThread(isHeavyWightTask = true) {
            val progress = if (videoTotalTime != 0) videoPlayTs.toFloat() / videoTotalTime.toFloat() * 100 else 0f
            if (mContentLength == 0.0) {
                val newGetContentLengthTime = System.currentTimeMillis()
                if (newGetContentLengthTime - mLastGetContentLengthTime > 5000) {
                    mLastGetContentLengthTime = newGetContentLengthTime
                    mContentLength = ExoCacheManager.getContentLength(topVideo.url) / 1024.0 / 1024.0
                }
            }

            //https://exoplayer.dev/hello-world.html#a-note-on-threading
            runOnUiThread {
                LogUtils.uploadHomeVideoStreamingPlaying(
                    action, hasDetailMask
                        ?: (detailBtn?.visibility == View.VISIBLE), topVideo.id, topVideo.title,
                    mGameEntity?.id, mGameEntity?.name, mContentLength, videoTotalTime, videoPlayTs, progress.toInt()
                )
            }
        }
    }
}