package com.baijiayun.live.ui

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.Shader
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.text.TextUtils
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import android.view.animation.LinearInterpolator
import android.widget.FrameLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import com.baijiayun.bjyutils.kt.dp
import com.baijiayun.bjyutils.kt.removeViewFromParent
import com.baijiayun.bjyutils.kt.startActivityByUrl
import com.baijiayun.bjyutils.reactivex.RxUtils
import com.baijiayun.bjyutils.screen.DisplayUtils
import com.baijiayun.glide.Glide
import com.baijiayun.glide.request.target.SimpleTarget
import com.baijiayun.glide.request.transition.Transition
import com.baijiayun.live.ui.pptpanel.PPTFragment
import com.baijiayun.live.ui.pptpanel.pptmanage.PPTManageWindow
import com.baijiayun.live.ui.preview.VideoPreviewFragment
import com.baijiayun.live.ui.speakpanel.SpeakFragment
import com.baijiayun.live.ui.topmenu.TopMenuFragment
import com.baijiayun.livebase.utils.FileUtils
import com.baijiayun.livebase.utils.ThemeDataUtil
import com.baijiayun.livecore.LiveSDK
import com.baijiayun.livecore.utils.LPSdkVersionUtils
import com.baijiayun.liveuibase.announcement.AnnouncementPresenter
import com.baijiayun.liveuibase.announcement.AnnouncementWindow
import com.baijiayun.liveuibase.base.BaseUIConstant
import com.baijiayun.liveuibase.base.BaseWindow
import com.baijiayun.liveuibase.base.LiveRoomActivity
import com.baijiayun.liveuibase.liveshow.shop.ShopContainerFragment
import com.baijiayun.liveuibase.liveshow.shop.ShopExplainFragment
import com.baijiayun.liveuibase.panel.BaseMainVideoFragment
import com.baijiayun.liveuibase.panel.InteractiveFragment
import com.baijiayun.liveuibase.speaklist.Switchable
import com.baijiayun.liveuibase.speaklist.SwitchableStatus
import com.baijiayun.liveuibase.toolbox.bonuspoints.BonusPointsWindow
import com.baijiayun.liveuibase.utils.enableVideoPreviewBeforeClass
import com.baijiayun.liveuibase.utils.isAdmin
import com.baijiayun.liveuibase.utils.showBonusPointsTab
import com.baijiayun.liveuibase.utils.showToastMessage
import com.baijiayun.liveuibase.widgets.setting.SettingWindow
import com.baijiayun.liveuibase.widgets.setting.fragment.SettingOtherFragment
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.activity_live_room_pad.activity_live_room_video_preview
import java.util.concurrent.TimeUnit
import kotlin.math.roundToInt

/**
 * 标准三分屏界面
 */
open class LiveRoomTripleActivity : LiveRoomActivity() {
    private var announcementWindow: AnnouncementWindow? = null
    private var pptManageWindow: PPTManageWindow? = null
    private var disposeOfMainScreenNotice: Disposable? = null
    private var bonusPointsWindow: BaseWindow? = null

    private var mainScreenNoticeAnimator: ObjectAnimator? = null
    private var mainScreenNoticeContainer: FrameLayout? = null

    private var settingWindow: SettingWindow? = null
    private var isMusicModeOn = false
    private var videoPreviewFragment: VideoPreviewFragment? = null

    private val roomLayoutSwitchObserver by lazy {
        Observer<Boolean> {
            switchRoomLayout()
        }
    }
    private val switch2FullScreenObserver by lazy {
        Observer<Pair<Boolean, Switchable?>> {
            it?.run {
                removeViewFromParent(pptContainer)
                if (it.first) {
                    (mainScreenNoticeContainer?.layoutParams as? FrameLayout.LayoutParams)?.topMargin = 0
                    fullScreenContainer.addView(
                        pptContainer,
                        FrameLayout.LayoutParams.MATCH_PARENT,
                        FrameLayout.LayoutParams.MATCH_PARENT
                    )
                } else {
                    pptContainerViewGroup?.addView(
                        pptContainer,
                        FrameLayout.LayoutParams.MATCH_PARENT,
                        FrameLayout.LayoutParams.MATCH_PARENT
                    )
                    it.second?.run {
                        when (switchableStatus) {
                            SwitchableStatus.MaxScreen -> {
                                // 这里如果是 placeHolderItem 需要检查 mainVideoItem 存在与否
                                // 如果 mainVideoItem 存在则占位图回 mainFragment
                                if (this.isPlaceholderItem && routerViewModel.mainVideoItem?.isPlaceholderItem != true) {
                                    switchToMainScreen()
                                } else {
                                    switchToMaxScreen()
                                }
                            }
                            SwitchableStatus.MainVideo -> switchToMainScreen()
                            SwitchableStatus.SpeakList -> switchToSpeakList()
                            else -> {
                                // 不处理
                            }
                        }
                    }
                }
            }
        }
    }

    private val fullScreenContainer by lazy {
        findViewById<FrameLayout>(R.id.activity_live_room_pad_room_full_screen_container)
    }

    protected val pptContainer by lazy {
        FrameLayout(this)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        initFullScreen()
        super.onCreate(savedInstanceState)
        setContentView(getContentResId())
        supportActionBar?.hide()
        LiveSDK.IS_TRTC_VIDEO_RESOLUTION_MODE_LANDSCAPE = true
        LPSdkVersionUtils.setSdkVersion(LPSdkVersionUtils.MULTI_CLASS_UI + BuildConfig.VERSION_NAME)
        rootContainer = findViewById(R.id.activity_live_room_root_container)
        marqueeContainer = rootContainer
        timerShowyFragmentAssignParentView = findViewById(R.id.activity_live_room_pad_background)
        enterRoom()
    }

    override fun initFullScreen() {
        if (!DisplayUtils.isPad(this)) {
            supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
            window.setFlags(
                WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN
            )
        }
    }

    // pad 和手机布局不同所以写 sw480dp
    open fun getContentResId() = R.layout.activity_live_room_pad

    override fun initView() {
        pptContainer.id = View.generateViewId()
        removeViewFromParent(pptContainer)
        toolboxLayer = findViewById(R.id.activity_live_toolbox)
        topMenuLayout = findViewById(R.id.activity_live_room_pad_room_top_container)
        pptContainerViewGroup = findViewById(R.id.activity_live_room_pad_room_ppt_container)
        pptContainerViewGroup?.addView(
            pptContainer,
            FrameLayout.LayoutParams.MATCH_PARENT,
            FrameLayout.LayoutParams.MATCH_PARENT
        )
        if (!TextUtils.isEmpty(routerViewModel.liveRoom.partnerConfig.largeClassLiveBackgroundUrl)) {
            Glide.with(this).asBitmap()
                .load(routerViewModel.liveRoom.partnerConfig.largeClassLiveBackgroundUrl)
                .into(LiveBackgroundDrawable(this, pptContainer))
        }
        responderButtonContainer = toolboxLayer
        supportFragmentManager.beginTransaction()
            .replace(
                R.id.activity_live_room_pad_room_main_video_container,
                BaseMainVideoFragment.newInstance()
            )
            .replace(
                R.id.activity_live_room_pad_room_interaction_container,
                InteractiveFragment.newInstance()
            )
            .replace(pptContainer.id, PPTFragment.newInstance())
            .replace(R.id.activity_live_room_pad_room_videos_container, SpeakFragment.newInstance())
            .commitNowAllowingStateLoss()
        routerViewModel.isShowEyeCare.value =
            findViewById<View>(R.id.activity_class_eye_care_layer).visibility == View.VISIBLE
    }

    private fun switchRoomLayout() {
        findViewById<View>(R.id.activity_live_room_pad_room_main_video_container).visibility =
            if (routerViewModel.isLiveWall()) View.GONE else View.VISIBLE
    }

    override fun observeActions() {
        super.observeActions()
        with(routerViewModel) {
            action2UpdateTheme.observe(this@LiveRoomTripleActivity) {
                skinInflateFactory.updateTheme(ThemeDataUtil.getThemeConfig())
                rootContainer.setBackgroundColor(
                    ThemeDataUtil.getColorFromThemeConfigByAttrId(
                        this@LiveRoomTripleActivity,
                        com.baijiayun.liveuibase.R.attr.base_theme_room_bg_color
                    )
                )
                initView()
            }
            speakListCount.observe(this@LiveRoomTripleActivity) {
                it?.let {
                    this@LiveRoomTripleActivity.findViewById<View>(R.id.activity_live_room_pad_room_videos_container)?.visibility =
                        if (it == 0) View.GONE else View.VISIBLE
                    //不显示座位席&显示了标题栏，主屏公告主动下移一个标题栏高度，避免遮挡
                    mainScreenNoticeContainer?.run {
                        val margin = if (it == 0 && this@LiveRoomTripleActivity.findViewById<View>(R.id.activity_live_room_pad_room_top_parent)?.visibility == View.VISIBLE)
                            resources.getDimension(R.dimen.top_menu_height).toInt() else 0
                        (layoutParams as? FrameLayout.LayoutParams)?.topMargin = margin
                    }
                }
            }
            action2Setting.observe(this@LiveRoomTripleActivity) { action ->
                action?.let {
                    if (settingWindow == null) {
                        settingWindow =
                            SettingWindow(this@LiveRoomTripleActivity, supportFragmentManager)
                        // 为了在断网重连或切换线路时记住音乐模式的设置
                        settingWindow!!.setMusicModeChangeListener(object :
                            SettingOtherFragment.MusicModeChangeListener {
                            override fun onMusicModeChange(isOpen: Boolean) {
                                isMusicModeOn = isOpen
                            }
                        })
                        showWindow(
                            settingWindow,
                            520.dp,
                            300.dp
                        )
                    }
                }
            }
            actionShowPPTManager.observe(this@LiveRoomTripleActivity) {
                it?.let {
                    handlePPTManageWindow(it)
                }
            }
            actionShowAnnouncementFragment.observe(this@LiveRoomTripleActivity) {
                if (it == true) {
                    navigateToAnnouncement()
                }
            }
            action2ShowMainScreenNotice.observe(this@LiveRoomTripleActivity, Observer { list ->
                RxUtils.dispose(disposeOfMainScreenNotice)
                mainScreenNoticeAnimator?.cancel()
                if (list.isEmpty()) {
                    return@Observer
                }
                mainScreenNoticeContainer = FrameLayout(this@LiveRoomTripleActivity)
                val bgDrawable = ColorDrawable(Color.parseColor(list[0].bgColor))
                val interval = list[0].rollInterval
                bgDrawable.alpha = ((list[0].bgTransparency / 100f) * 255).roundToInt()
                mainScreenNoticeContainer?.background = bgDrawable
                var index = 0
                disposeOfMainScreenNotice =
                    Observable.interval(0, interval.toLong(), TimeUnit.SECONDS)
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe {
                            if (mainScreenNoticeAnimator?.isRunning == true) {
                                return@subscribe
                            }
                            val mainScreenNoticeModel = list[index % list.size]
                            val noticeTextView = TextView(this@LiveRoomTripleActivity)
                            noticeTextView.run {
                                text = mainScreenNoticeModel.content
                                textSize = mainScreenNoticeModel.fontSize
                                alpha = mainScreenNoticeModel.fontTransparency / 100f
                                setTextColor(Color.parseColor(mainScreenNoticeModel.fontColor))
                                if (mainScreenNoticeModel.link.startsWith("http")) {
                                    setOnClickListener {
                                        startActivityByUrl(
                                            this@LiveRoomTripleActivity,
                                            mainScreenNoticeModel.link
                                        )
                                    }
                                }
                            }
                            val noticeTextViewSize = DisplayUtils.getUnDisplayViewSize(noticeTextView)
                            val layoutParams = FrameLayout.LayoutParams(
                                FrameLayout.LayoutParams.WRAP_CONTENT,
                                FrameLayout.LayoutParams.WRAP_CONTENT
                            )
                            layoutParams.run {
                                gravity = Gravity.END
                                marginEnd = -noticeTextViewSize[0]
                                topMargin = 4.dp
                                bottomMargin = topMargin
                            }
                            mainScreenNoticeContainer?.addView(noticeTextView, layoutParams)
                            val noticeContainerLayoutParams = FrameLayout.LayoutParams(
                                FrameLayout.LayoutParams.MATCH_PARENT,
                                FrameLayout.LayoutParams.WRAP_CONTENT
                            )
                            //显示标题&没显示发言列表，设置topMargin避免主屏公告被遮挡
                            if (this@LiveRoomTripleActivity.findViewById<View>(R.id.activity_live_room_pad_room_top_parent)?.visibility == View.VISIBLE &&
                                this@LiveRoomTripleActivity.findViewById<View>(R.id.activity_live_room_pad_room_videos_container)?.visibility == View.GONE
                            ) {
                                noticeContainerLayoutParams.topMargin =
                                    resources.getDimension(R.dimen.top_menu_height).toInt()
                            }
                            pptContainer.addView(mainScreenNoticeContainer, noticeContainerLayoutParams)
                            mainScreenNoticeAnimator = ObjectAnimator.ofFloat(
                                noticeTextView,
                                "translationX",
                                -pptContainer.width.toFloat() - noticeTextViewSize[0]
                            )
                            mainScreenNoticeAnimator?.run {
                                duration = ((pptContainer.width + noticeTextViewSize[0]) / 100f * 1000).toLong()
                                interpolator = LinearInterpolator()
                                addListener(object : AnimatorListenerAdapter() {
                                    override fun onAnimationEnd(animation: Animator) {
                                        mainScreenNoticeContainer?.removeAllViews()
                                        pptContainer.removeView(mainScreenNoticeContainer)
                                    }
                                })
                                start()
                            }
                            index++
                        }
            })
            showShop.observe(this@LiveRoomTripleActivity) {
                it?.let {
                    if (shopFragment == null) {
                        // 如 app 中没有设置 Fragment，则使用默认 Fragment
                        shopFragment = ShopContainerFragment()
                    }
                    supportFragmentManager.beginTransaction()
                        .replace(R.id.activity_live_room_pad_shop_container, shopFragment!!)
                        .commitAllowingStateLoss()
                }
            }
            actionCloseShopFragment.observe(this@LiveRoomTripleActivity) {
                it?.let {
                    removeFragment(shopFragment)
                }
            }

            actionRoomLayoutSwitch.observeForever(roomLayoutSwitchObserver)
        }
    }

    override fun observeSuccess() {
        super.observeSuccess()
        with(routerViewModel) {
            actionShowBonusPointsWindow.observe(this@LiveRoomTripleActivity) {
                it?.let {
                    if (it) {
                        bonusPointsWindow = BonusPointsWindow(this@LiveRoomTripleActivity)
                        (bonusPointsWindow as BonusPointsWindow).closeListener =
                            View.OnClickListener {
                                routerViewModel.actionShowBonusPointsWindow.value = false
                            }
                        showWindow(
                            bonusPointsWindow,
                            resources.getDimensionPixelSize(R.dimen.bjy_base_live_bonus_points_window_width),
                            if (isAdmin(liveRoom)) {
                                resources.getDimensionPixelSize(R.dimen.bjy_base_live_bonus_points_window_height)
                            } else {
                                if (showBonusPointsTab(liveRoom)) {
                                    resources.getDimensionPixelSize(R.dimen.bjy_base_live_bonus_points_window_height_student)
                                } else {
                                    resources.getDimensionPixelSize(R.dimen.bjy_base_live_bonus_points_window_height_student_small)
                                }
                            }
                        )
                    } else {
                        destroyWindow(bonusPointsWindow)
                    }
                }
            }
            showTimerShowy.observe(this@LiveRoomTripleActivity) {
                it?.let { if (it.first) showTimerShowy(it.second) }
            }
            switch2FullScreen.observeForever(switch2FullScreenObserver)
            afterObserveSuccess()
        }
    }

    open fun afterObserveSuccess() {
    }

    private fun handlePPTManageWindow(open: Boolean) {
        if (pptManageWindow == null) {
            pptManageWindow = PPTManageWindow()
        }
        if (open) {
            if (!pptManageWindow!!.isAdded) {
                addFragment(R.id.activity_live_room_ppt_manage, pptManageWindow)
            }
            if (pptManageWindow!!.isHidden) {
                showFragment(pptManageWindow)
            }
        } else {
            hideFragment(pptManageWindow)
        }
    }

    //显示公告
    private fun navigateToAnnouncement() {
        if (announcementWindow == null) {
            announcementWindow =
                AnnouncementWindow(
                    this,
                    supportFragmentManager
                )
            val presenter =
                AnnouncementPresenter(
                    announcementWindow
                )
            bindVP(announcementWindow!!, presenter)
            showWindow(
                announcementWindow,
                resources.getDimensionPixelSize(R.dimen.live_ui_announce_dialog_width),
                resources.getDimensionPixelSize(R.dimen.live_ui_announce_dialog_height)
            )
        }
    }

    override fun navigateToMain() {
        super.navigateToMain()
        // 进房间之后才显示顶栏
        if (enableVideoPreviewBeforeClass(routerViewModel)) {
            videoPreviewFragment = VideoPreviewFragment.newInstance()
            supportFragmentManager
                .beginTransaction()
                .replace(
                    R.id.activity_live_room_pad_room_top_container,
                    TopMenuFragment.newInstance()
                )
                .replace(R.id.activity_live_room_video_preview, videoPreviewFragment!!)
                .commitAllowingStateLoss()
        } else {
            activity_live_room_video_preview.visibility = View.GONE
            supportFragmentManager
                .beginTransaction()
                .replace(
                    R.id.activity_live_room_pad_room_top_container,
                    TopMenuFragment.newInstance()
                )
                .commitAllowingStateLoss()
        }

        if (routerViewModel.isSupportLiveShow() && !isAdmin(routerViewModel.liveRoom)) {
            supportFragmentManager.beginTransaction()
                .replace(R.id.activity_live_room_pad_shop_explain_container, ShopExplainFragment.newInstance())
                .commitNowAllowingStateLoss()
        }
    }

    override fun onClassStart() {
        super.onClassStart()
        if (videoPreviewFragment != null) {
            activity_live_room_video_preview.visibility = View.GONE
            supportFragmentManager
                .beginTransaction()
                .remove(videoPreviewFragment!!)
                .commitAllowingStateLoss()
        }
    }

    override fun removeObservers() {
        super.removeObservers()
        routerViewModel.switch2FullScreen.removeObserver(switch2FullScreenObserver)
        routerViewModel.actionRoomLayoutSwitch.removeObserver(roomLayoutSwitchObserver)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        screenShareHelper?.onActivityResult(requestCode, resultCode, data)
        pipHelper?.onActivityResult(requestCode, resultCode, data)
        if (resultCode == Activity.RESULT_OK && data != null &&
            BaseUIConstant.UploadType.containsValue(requestCode)
        ) {
            val uri = data.data
            try {
                if (uri != null) {
                    val path: String? = FileUtils.getPath(this, uri)
                    if (path == null) {
                        showToastMessage(getString(R.string.live_file_not_exist))
                        return
                    }
                    val value = HashMap<BaseUIConstant.UploadType, String>()
                    val uploadType = BaseUIConstant.UploadType.valueOf(requestCode)
                    if (uploadType != null) {
                        value[uploadType] = path
                    }
                    pptManageWindow?.onUpload(value)
                }
            } catch (e: java.lang.Exception) {
                showToastMessage(getString(R.string.live_load_file_error))
                e.printStackTrace()
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        pptManageWindow?.onDestroy()
    }

    override fun onDismissAnnouncement() {
        super.onDismissAnnouncement()
        destroyWindow(announcementWindow)
        announcementWindow = null
    }

    override fun onDismissSetting() {
        super.onDismissSetting()
        destroyWindow(settingWindow)
        settingWindow = null
    }

    override fun showWindow(
        window: BaseWindow?,
        windowWidth: Int,
        windowHeight: Int,
        center: Boolean
    ) {
        val layoutParams = FrameLayout.LayoutParams(windowWidth, windowHeight)
        //全屏下，窗口居中
        if (!center && pptContainerViewGroup?.measuredWidth!! > layoutParams.width && routerViewModel.switch2FullScreen.value?.first != true) {
            layoutParams.gravity = Gravity.CENTER_VERTICAL
            layoutParams.leftMargin =
                (pptContainerViewGroup?.measuredWidth?.minus(layoutParams.width))?.div(2) ?: 0
        } else {
            layoutParams.leftMargin = ((toolboxLayer?.width ?: windowWidth) - windowWidth) / 2
            layoutParams.topMargin = ((toolboxLayer?.height ?: windowHeight) - windowHeight) / 2
        }
        if (showMaskLayer(window)) {
            toolboxLayer?.setBackgroundColor(ContextCompat.getColor(this, R.color.base_half_black))
        }
        toolboxLayer?.addWindow(window, layoutParams)
    }

    companion object {
        private var shopFragment: Fragment? = null

        @JvmStatic
        fun setLiveShowShopFragment(fragment: Fragment?) {
            shopFragment = fragment
        }
    }

    private class LiveBackgroundDrawable(
        private val context: Context,
        private val viewGroup: ViewGroup
    ) : SimpleTarget<Bitmap?>() {
        override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap?>?) {
            val bitmapDrawable = BitmapDrawable(context.resources, resource)
            val color = ThemeDataUtil.getColorFromThemeConfigByAttrId(
                context,
                R.attr.base_theme_blackboard_color
            )
            bitmapDrawable.setColorFilter(color, PorterDuff.Mode.DST_OVER)
            bitmapDrawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT)
            viewGroup.background = bitmapDrawable
        }
    }
}
