package com.remax.visualnovel.ui.chat


import android.graphics.Point
import android.view.View.GONE
import android.view.View.VISIBLE
import androidx.activity.viewModels
import androidx.core.view.GravityCompat
import androidx.core.view.marginLeft
import androidx.core.view.marginRight
import androidx.core.view.marginTop
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
import com.hjq.permissions.OnPermissionCallback
import com.hjq.permissions.XXPermissions
import com.hjq.permissions.permission.PermissionLists
import com.hjq.permissions.permission.base.IPermission
import com.remax.visualnovel.app.base.BaseBindingActivity
import com.remax.visualnovel.utils.Routers
import com.pengxr.modular.eventbus.generated.events.EventDefineOfUserEvents
import com.remax.visualnovel.R
import com.remax.visualnovel.databinding.ActivityActorChatBinding
import com.remax.visualnovel.entity.request.ChatSetting
import com.remax.visualnovel.event.model.OnLoginEvent
import com.remax.visualnovel.extension.countDownCoroutines
import com.remax.visualnovel.extension.launchAndLoadingCollect
import com.remax.visualnovel.extension.launchWithRequest
import com.remax.visualnovel.extension.setMargin
import com.remax.visualnovel.extension.toast
import com.remax.visualnovel.manager.nim.NimManager
import com.remax.visualnovel.ui.chat.call.ChatCallView
import com.remax.visualnovel.ui.chat.setting.model.ChatModelDialog
import com.remax.visualnovel.ui.chat.ui.HoldToTalkDialog
import com.remax.visualnovel.utils.RecordHelper
import com.remax.visualnovel.utils.StatusBarUtil3
import com.remax.visualnovel.utils.setOnKeyboardHeightChangeListener
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Job
import timber.log.Timber
import kotlin.getValue


@AndroidEntryPoint
@Route(path = Routers.CHAT)
class ChatActivity : BaseBindingActivity<ActivityActorChatBinding>() {
    private var mMode = MODE_TEXT
    private val chatViewModel by viewModels<ChatViewModel>()
    private val mRecordAssist = RecordAssist()
    private val mImeHelper = ImeHelper()




    override fun initView() {
        /*ARouter.getInstance().inject(this)
        StatusBarUtils.setStatusBarAndNavBarIsLight(this, false)
        StatusBarUtils.setTransparent(this)
        StatusBarUtil2.initImmersive(this, lightStatusBar = true) */
        StatusBarUtil3.setImmersiveStatusBar(this, true)
        binding.toolbar.addRightIcon(R.mipmap.chat_title_setting) {
            binding.drawerMenu.openDrawer(GravityCompat.END)
        }

        with(binding) {
            initInputPanelEvents()
            initCallViewEvents()
        }

        mImeHelper.startImeListen()
    }

    override fun initData() {

    }

    private val loginObserver = Observer<OnLoginEvent?> {
        launchWithRequest({
            //TODO - business handling for login events
            if (it?.isLogin() == true) {

            } else {

            }
        })
    }

    override fun onDestroy() {
        super.onDestroy()
        EventDefineOfUserEvents.onLoginStatusChanged().removeObserver(loginObserver)
        mRecordAssist.stopTalk()
    }


    /**
     * 处理发送消息的错误码
     */
    private val sendMsgErrorCallback: (Int) -> Unit = { code ->
        when (code) {
            NimManager.SEND_IM_INSUFFICIENT_BALANCE -> {
                showSelectModelDialog()
            }
        }
    }

    private fun initCallViewEvents() {
        with(binding.callView) {
            setEventListener(object : ChatCallView.IEventListener {
                override fun onExitCall() {
                    switchMode(MODE_TEXT)
                }
            })
        }
    }

    private fun initInputPanelEvents() {
        with(binding.inputPanel) {
            holdToTalk(
                {
                    mRecordAssist.startRecording()
                },
                {
                    mRecordAssist.stopTalk()
                },
                touchPosCallback = { point ->
                    mRecordAssist.onTouchPointChanged(point)
                }
            )

            setEventListener(object : InputPanel.IEventListener {
                override fun onEnterCall() {
                    switchMode(MODE_CALL)
                }

                override fun onEnterShortChat() {
                    // TODO("Not yet implemented")
                }

                override fun onSendText(content: CharSequence) {
                    // TODO("Not yet implemented")
                }

                override fun onMsgRvScroll2Bottom() {
                    // TODO("Not yet implemented")
                }

                override fun onCheckVipStatus() {
                    // TODO("Not yet implemented")
                }
            })

        }
    }


    private fun switchMode(newMode: Int) {
        if (newMode != mMode) {
            mMode = newMode
            binding.run {
                when (mMode) {
                    MODE_VOICE, MODE_TEXT -> {
                        callView.visibility = GONE
                        textVoiceChatContainer.visibility = VISIBLE
                    }

                    MODE_CALL -> {
                        callView.visibility = VISIBLE
                        textVoiceChatContainer.visibility = GONE
                    }
                }
            }
        }
    }


    /**
     * 检查麦克风权限
     */
    private fun checkRecordAudioPermission(onGranted: () -> Unit, allowGranted: (() -> Unit)? = null) {
        val permission = PermissionLists.getRecordAudioPermission()
        if (XXPermissions.isGrantedPermission(this, permission)) {
            onGranted.invoke()
        } else {
            XXPermissions.with(this).permission(permission)
                .request(object : OnPermissionCallback {
                    override fun onDenied(permissions: MutableList<IPermission>, doNotAskAgain: Boolean) {
                        this@ChatActivity.toast(R.string.no_permission)
                        if (doNotAskAgain) {
                            // 如果是被永久拒绝就跳转到应用权限系统设置页面
                            XXPermissions.startPermissionActivity(this@ChatActivity, permissions)
                        }
                    }

                    override fun onGranted(permissions: MutableList<IPermission>, allGranted: Boolean) {
                        if (!allGranted) {
                            this@ChatActivity.toast(getString(R.string.no_permission))
                        } else {
                            allowGranted?.invoke()
                        }
                    }
                })
        }
    }


    private fun showSelectModelDialog() {
        with(chatViewModel) {
            fun createModelDialog() {
                val modelDialog = ChatModelDialog(this@ChatActivity)

                modelDialog.build(chatModels ?: emptyList(), chatSet?.modelCode, {

                }) { model ->
                    launchAndLoadingCollect({
                        setChatModel(
                            ChatSetting(aiId, model.code)
                        )
                    }) {
                        onSuccess = { res ->
                            modelDialog.dismiss()
                        }
                    }
                }
                modelDialog.show()
            }

            if (chatModels.isNullOrEmpty()) {
                launchAndLoadingCollect({
                    chatViewModel.getChatModels()
                }) {
                    onSuccess = {
                        createModelDialog()
                    }
                }
            } else {
                createModelDialog()
            }
        }
    }

    override fun onResume() {
        super.onResume()
    }

    override fun onStop() {
        super.onStop()
    }


    companion object {
        const val MODE_TEXT = 1
        const val MODE_VOICE = 2
        const val MODE_CALL = 3


        const val ACTOR_ID = "ACTOR_ID"
        fun start(actorId: Int) {
            ARouter.getInstance()
                .build(Routers.CHAT)
                .withInt(ACTOR_ID, actorId)
                .navigation()
        }

    }


    inner class RecordAssist {

        private var mIsCancelled = false
        private var recordJob: Job? = null

        private val recordHelper by lazy {
            RecordHelper()
        }

        private val holdToTalkDialog by lazy {
            HoldToTalkDialog(this@ChatActivity).build()
        }

        /**
         * 开始按住说话
         */
        fun startRecording() {
            // TODO - check bill count
            checkRecordAudioPermission({ startTalk() })
            /*when {
                // 没钱就去充值
                WalletManager.balance < 1000L -> WalletManager.showChargeDialog()
                // 检查权限
                else -> {
                    checkRecordAudioPermission({ startTalk() })
                }

            }*/
        }


        private fun startTalk() {
            val maxTalkTime = 60
            val minTalkTime = 1
            var recordingProgress = 0
            mIsCancelled = false

            holdToTalkDialog.show()
            recordHelper.startRecording(this@ChatActivity, {
                recordJob = lifecycleScope.countDownCoroutines(maxTalkTime, {
                    Timber.i("startRecording countDownCoroutines: %d", it)
                    recordingProgress = maxTalkTime - it
                }, {
                    stopTalk()
                })

            }, {
                if (!mIsCancelled) {
                    if (recordingProgress >= minTalkTime) {
                        Timber.i("startRecording onStop: ${recordHelper.getFilename()}")

                        launchAndLoadingCollect({
                            chatViewModel.voiceASR(recordHelper.getFilename())
                        }) {
                            onSuccess = {
                                if (!it?.content.isNullOrBlank()) {
                                    chatViewModel.sendMsg(it.content, errorCallback = sendMsgErrorCallback)
                                }
                            }
                        }

                    } else {
                        showToast(R.string.min_voice_time)  //录音最少1秒
                    }
                }
            })
        }


        fun stopTalk() {
            mIsCancelled = holdToTalkDialog.isTouchInCancelArea;
            holdToTalkDialog.dismiss()
            recordJob?.cancel()
            recordHelper.stopRecording()
        }

        fun onTouchPointChanged(point: Point) {
            if (holdToTalkDialog.isShowing) {
                holdToTalkDialog.onTouchPointChanged(point)
            }
        }

    }


    inner class ImeHelper {
        fun startImeListen() {
            val rootView = binding.root
            rootView.setOnKeyboardHeightChangeListener { keyboardHeight, isVisible ->
                updateLayoutForKeyboard(keyboardHeight, isVisible)
            }
        }

        private fun updateLayoutForKeyboard(keyboardHeight: Int, isVisible: Boolean) {
            with (binding.contentSubContainer) {
                setMargin(marginLeft, marginTop, marginRight, keyboardHeight)
            }
        }
    }


}