package com.abbidot.tracker.base

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.Rect
import android.os.Bundle
import android.text.TextUtils
import android.view.Gravity
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.inputmethod.InputMethodManager
import android.widget.Button
import android.widget.EditText
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import androidx.viewbinding.ViewBinding
import com.abbidot.baselibrary.constant.MMKVKey
import com.abbidot.baselibrary.network.exception.ErrorCode
import com.abbidot.baselibrary.util.AppUtils
import com.abbidot.baselibrary.util.LogUtil
import com.abbidot.baselibrary.util.MMKVUtil
import com.abbidot.tracker.R
import com.abbidot.tracker.constant.ConstantInt
import com.abbidot.tracker.constant.GetResultCallback
import com.abbidot.tracker.util.Util
import com.abbidot.tracker.util.ViewUtil
import com.baidu.platform.comapi.util.NetworkUtil
import com.hjq.toast.Toaster
import com.qmuiteam.qmui.alpha.QMUIAlphaButton
import com.qmuiteam.qmui.alpha.QMUIAlphaImageButton
import com.qmuiteam.qmui.util.QMUIDisplayHelper
import com.qmuiteam.qmui.util.QMUIStatusBarHelper
import com.qmuiteam.qmui.widget.QMUITopBar
import com.qmuiteam.qmui.widget.dialog.QMUITipDialog


/**
 *Created  by .yzq on 2021/11/2/002.
 * @link
 * @description: Activity基类
 */
abstract class BaseActivity<T : ViewBinding>(val inflater: (inflater: LayoutInflater) -> T) :
    AppCompatActivity(), View.OnClickListener {

    protected lateinit var mViewBinding: T
    var mTopBar: QMUITopBar? = null
    lateinit var mContext: Context
    lateinit var mActivity: Activity
    private var mLoadingDialog: QMUITipDialog? = null

    //默认删除去掉titleTopBar底部间隔下划线
    private var mDeleteBottomDivider: Boolean = true

    //Activity是否在前台显示运行
    var isFrontRunning = false

    //右边图标按钮
    var mRightImageButton: QMUIAlphaImageButton? = null

    //右边按钮
    var mRightTextButton: Button? = null

    //网络请求失败，需要重试次数
    var mNetworkRequestsFailRetryCount = 0
    val mNetworkRequestsFailMaxCount = 3
    val mNetworkRequestsFailLimit = "networkRequestsFailLimit"

    //是否拦截网络请求错误code提示
    var isInterceptNetErrorCodeTip = false

    //软键盘管理
    private var mInputMethodManager: InputMethodManager? = null

    // 监听因输入框弹出,遮挡输入框,界面移动,需要移动的view
    private var mTranslateView: View? = null

    /*****************************监听软键盘弹出，输入框上移 ************************************/
    var isKeyboardTranslate = true

    //是否需要适配底部EdgeToEdge
    var isEdgeToEdgeAdapterNavigationBars = true

    //防止按钮多次点击
    private var mLimitExecutionTime = 0L
    var checkCrash = true

    override fun onCreate(savedInstanceState: Bundle?) {
        isFrontRunning = true
        super.onCreate(savedInstanceState)
        mViewBinding = inflater(layoutInflater)
        mContext = this
        mActivity = this
        //禁用屏幕旋转 代码设置无效
//        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        mViewBinding.root.apply {
            //点击屏幕页面隐藏软键盘start
            setOnClickListener {
                hideInputMethod(this)
            }

            //判断是否是深色模式
            if (AppUtils.isDarkThemeEnabled(mContext)) {
                // 设备处于深色模式
                setBackgroundResource(R.color.gray)
            } else {
                // 设备处于浅色模式,统一设置的渐变背景色
                background = ContextCompat.getDrawable(mContext, R.drawable.v2_bg_color_gradient)
            }
        }
        setContentView(mViewBinding.root)
        mTopBar = getTopBar()

        //拦截返回按键
        onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                listenBackPressed()
            }
        })

        initData()
        liveDataObserve()
    }

    // 字体大小不跟随系统
    override fun attachBaseContext(newBase: Context) {
        super.attachBaseContext(getConfigurationContext(newBase))
    }

    // 字体大小不跟随系统
    private fun getConfigurationContext(context: Context): Context {
        val configuration = context.resources.configuration
        configuration.fontScale = 1F
        return context.createConfigurationContext(configuration)
    }

    /*
    lifecycleScope.launch {

        Dispatchers.IO
            专为磁盘和网络IO进行了优化
            数据库-文件读写-网络处理
        Dispatchers.Default
            专为CPU密集型任务进行了优化
            数组排序 - JSON数据解析-处理差异判断
        withContext(Dispatchers.Default){

        }
        lifecycleScope.coroutineContext
    }
    */

    override fun onResume() {
        super.onResume()
        isFrontRunning = true
    }

    override fun onPause() {
        super.onPause()
        isFrontRunning = false
        //键盘隐藏恢复默认状态
        mTranslateView?.apply {
            scrollTo(0, 0)
            isKeyboardTranslate = false
        }
    }

    override fun onStop() {
        super.onStop()
        showLoading(false)
        isFrontRunning = false
    }

    /**
     * 没有TopBar就设置返回null
     */
    abstract fun getTopBar(): QMUITopBar?

    /**
     * 注册监听livedata观察者
     */
    open fun liveDataObserve() {}

    /**
     * open修饰的类和方法可以被子类继承和重写
     * 初始化
     */
    open fun initData() {
        if (checkCrash) {
            //出现闪退,退出当前页面
            val isCrash = MMKVUtil.getBoolean(MMKVKey.isCrash, false)
            if (isCrash) finish()
        }
        //沉浸式状态栏
        QMUIStatusBarHelper.translucent(window)
        //判断是否是深色模式
        if (AppUtils.isDarkThemeEnabled(mContext)) {
            setStatusBarDark()
        } else {
            setStatusBarLight()
        }
        mTopBar?.apply {
            //适配状态栏
            this.parent?.let {
                edgeToEdgeAdapterBars(it as View, WindowInsetsCompat.Type.statusBars())
            }
            //去掉titleTopBar底部间隔下划线
            if (mDeleteBottomDivider) updateBottomDivider(0, 0, 0, 0)
        }
        //适配底部导航栏
        if (isEdgeToEdgeAdapterNavigationBars) edgeToEdgeAdapterBars(mViewBinding.root)
    }

    /**
     * 和 setContentView 对应的方法
     */
    private fun getContentView(): ViewGroup {
        return findViewById(Window.ID_ANDROID_CONTENT)
    }

    /**
     * 监听键盘弹出和隐藏，解决键盘弹出挡住输入框的问题
     */
    fun setListenKeyboardChange(
        windowTranslateY: Int = 500,
        view: View = window.decorView,
        methodType: Int = ConstantInt.Type0
    ) {
        val metrics = getResources().displayMetrics
        val screenWidth = metrics.widthPixels
//        val screenHeight = metrics.heightPixels
        val scaleFactor = screenWidth / 1080 // 假设 1080 是设计宽度
        view.viewTreeObserver.addOnGlobalLayoutListener {
            if (methodType == ConstantInt.Type0) {
                onLayoutChange(view, windowTranslateY * scaleFactor)
            } else {
                onGlobalLayoutChange(view, windowTranslateY * scaleFactor)
            }
        }
    }


    /**
     * 设置其他包含的view点击。隐藏软键盘，如ScrollView
     */
    fun setViewClickHideInputMethod(view: View) {
        // 点击外部隐藏软键盘，提升用户体验
        view.setOnClickListener {
            hideInputMethod(view)
        }
    }

    /**
     * edgeToEdge全面屏适配Android15 底部。防止view被菜单、状态栏遮挡
     * https://mp.weixin.qq.com/s?__biz=MzA5MzI3NjE2MA==&mid=2650286452&idx=1&sn=354b78ae82c52b6d3d510256779a3df9&scene=21&poc_token=HN91iGij_n_mGA9z9ZarQC_44XYBhBjN9N9z_w1_
     */
    fun edgeToEdgeAdapterBars(
        view: View, typeMask: Int = WindowInsetsCompat.Type.navigationBars()
    ) {
        ViewCompat.setOnApplyWindowInsetsListener(view) { v, insets ->
            val bars = insets.getInsets(typeMask)
            v.setPadding(bars.left, bars.top, bars.right, bars.bottom)
            insets
        }
    }

    /**
     * 修改状态颜色,有状态栏时用到,现在状态栏直接被占位
     */
//    fun setStatusBarColor(color: Int) {
//        //这里动态修改颜色
//        window.statusBarColor = color
//    }

    /**
     * 设置状态栏白色字体与图标
     */
    fun setStatusBarDark() {
        QMUIStatusBarHelper.setStatusBarDarkMode(this)
    }

    /**
     * 设置状态栏黑色字体与图标
     */
    fun setStatusBarLight() {
        QMUIStatusBarHelper.setStatusBarLightMode(this)
    }

    /**
     * 设置多个view的监听事件
     */
    fun setOnClickListenerViews(vararg views: View?) {
        for (v in views) {
            v?.let {
                if (v is QMUIAlphaButton) {
                    //设置按下点击透明效果
                    v.setChangeAlphaWhenPress(true)
                } else if (v is QMUIAlphaImageButton) {
                    //设置按下点击透明效果
                    v.setChangeAlphaWhenPress(true)
                }
                v.setOnClickListener(this)
            }
        }
    }

    /**
     * 限制多次点击按钮
     */
    fun isLimitClick(): Boolean {
        //防止执行多次弹窗
        if (Util.isTimeLimit(mLimitExecutionTime)) {
            return true
        }
        mLimitExecutionTime = System.currentTimeMillis()
        return false
    }

    override fun onClick(v: View?) {
    }

    /**
     * 按钮开启/禁用点击
     */
    fun setButtonEnabled(v: View, enabled: Int = ConstantInt.SpecialType) {
        when (enabled) {
            ConstantInt.SpecialType -> v.isEnabled = !v.isEnabled
            ConstantInt.Type0 -> v.isEnabled = false
            ConstantInt.Type1 -> v.isEnabled = true
        }
    }

    /**
     * 设置title标题 resIdTitle
     */
    fun setTopBarTitle(resIdTitle: Int) {
        setTopBarTitle(getString(resIdTitle))
    }

    /**
     * 设置透明一体化状态栏TopBarTitle，只有返回按钮
     */
    fun setTranslucentTopBar() {
        //去掉titleTopBar背景颜色,设置TopBar背景透明
        mTopBar!!.setBackgroundAlpha(0)
        setTopBarTitle("")
    }

    /**
     * 设置按钮图片
     */
    fun setLeftBackImage(@DrawableRes resId: Int) {
        mTopBar!!.removeAllLeftViews()
        val leftBtn = mTopBar!!.addLeftImageButton(resId, R.id.topbar_left_change_button)
        if (resId == 0) {
            return
        }
        leftBtn.setOnClickListener { leftBackOnClick() }
    }

    /**
     * 需要重写返回按钮时
     */
    open fun leftBackOnClick() {
        finish()
    }

    open fun listenBackPressed() {
        leftBackOnClick()
    }


    /**
     * 添加TopBar右边图片按钮
     */
    fun addRightImageButton(
        @DrawableRes resId: Int, setOnClick: Boolean = true
    ): QMUIAlphaImageButton {
        val rightBtn = mTopBar!!.addRightImageButton(resId, R.id.topbar_right_change_button)
        if (setOnClick) setOnClickListenerViews(rightBtn)
        return rightBtn
    }

    /**
     * 添加TopBar右边文字按钮
     */
    fun addRightTextButton(
        @StringRes resId: Int, textColor: Int = R.color.select_color
    ): Button {
        val textButton = mTopBar!!.addRightTextButton(
            getString(resId), R.id.topbar_right_change_textview
        ).apply {
            setBackgroundResource(R.drawable.selector_transparent_pressed)
            setTextColor(ContextCompat.getColor(mContext, textColor))
            setOnClickListenerViews(this)
        }
        return textButton
    }

    /**
     * 设置title标题titleString
     */
    fun setTopBarTitle(title: String) {
        if (null != mTopBar) {
            if (TextUtils.isEmpty(title)) mTopBar!!.showTitleView(false)
            else {
                mTopBar!!.setTitle(title)
                val tf =
                    ViewUtil.instance.setTypeface(mContext, getString(R.string.roboto_bold_font))
                mTopBar!!.titleView!!.setTypeface(tf)
            }
            mTopBar!!.addLeftBackImageButton().setOnClickListener { leftBackOnClick() }
        }
    }

    fun isShowLoading(): Boolean {
        return null != mLoadingDialog && mLoadingDialog!!.isShowing
    }

    fun showLoading(show: Boolean, tipsRes: Int, cancelable: Boolean = true) {
        showLoading(show, getString(tipsRes), cancelable)
    }

    fun showLoading(show: Boolean, tip: String = "", cancelable: Boolean = true) {
//        if (!isFrontRunning) {
//            return
//        }
//        if (show) {
//            if (isShowLoading()) {
//                mLoadingDialog!!.dismiss()
//            }
//            var message = tip
//            if (TextUtils.isEmpty(tip)) {
//                message = getString(R.string.txt_loading)
//            }
//            mLoadingDialog =
//                QMUITipDialog.Builder(mContext).setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING)
//                    .setTipWord(message).create(cancelable).apply {
//                        setCanceledOnTouchOutside(false)
//                        show()
//                    }
//        } else {
//            mLoadingDialog?.dismiss()
//        }
    }

    fun showNoCancelableLoading(show: Boolean, message: String = getString(R.string.txt_loading)) {
        if (!isFrontRunning) {
            return
        }
        if (show) {
            if (isShowLoading()) {
                mLoadingDialog!!.dismiss()
            }
//            var message = tip
//            if (TextUtils.isEmpty(tip)) {
//            }
            mLoadingDialog =
                QMUITipDialog.Builder(mContext).setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING)
                    .setTipWord(message).create(false).apply {
                        setCanceledOnTouchOutside(false)
                        show()
                    }
        } else {
            mLoadingDialog?.dismiss()
        }
    }

    /**
     * 显示提示toast
     */
    fun showToast(
        tip: String, isFinish: Boolean = false, gravity: Int = Gravity.BOTTOM
//        @QMUITipDialog.Builder.IconType iconType: Int = QMUITipDialog.Builder.ICON_TYPE_NOTHING
    ) {
        if (gravity == Gravity.BOTTOM) Toaster.setGravity(gravity, 0, 300)
        else Toaster.setGravity(gravity)
        if (isFinish) {
//            DialogUtils.showTipDialog(mContext, mViewBinding.root, tip, iconType, true)
            //activity前台显示运行才弹出
            if (isFrontRunning) {
                Toaster.show(tip)
                //根据文字长度来决定显示时间长短
                var showTime = if (AppUtils.isChina()) {
                    tip.length * (1000L / 4)
                } else {
                    tip.length * (1000L / 10)
                }
                if (showTime < 1000) showTime = 1500
                if (showTime > 8000) showTime = 8000
                mViewBinding.root.postDelayed({
                    if (!isFinishing) {
                        Toaster.cancel()
                        finish()
                    }
                }, showTime)
            }
        } else {
            Toaster.show(tip)
        }
    }

    fun showToast(
        resIdString: Int, isFinish: Boolean = false, gravity: Int = Gravity.BOTTOM
//        @QMUITipDialog.Builder.IconType iconType: Int = QMUITipDialog.Builder.ICON_TYPE_NOTHING
    ) {
        showToast(getString(resIdString), isFinish, gravity)
    }

    fun hideFragment(fragmentTransaction: FragmentTransaction, fragment: Fragment) {
        if (fragment.isAdded) {
            fragmentTransaction.hide(fragment)
        }
    }

    override fun finish() {
        super.finish()
        overridePendingTransition(R.anim.slide_still, R.anim.slide_out_right)
    }

    override fun startActivity(intent: Intent) {
        super.startActivity(intent)
        overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left)
    }

    fun startActivityFinish(intent: Intent) {
        startActivity(intent)
        super.finish()
    }

    override fun startActivity(intent: Intent, options: Bundle?) {
        super.startActivity(intent, options)
        overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left)
    }

    /**
     * onActivityResult 替换跳转方法
     */
    fun launchActivity(activityResultLauncher: ActivityResultLauncher<Intent>, intent: Intent) {
        activityResultLauncher.launch(intent)
        overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left)
    }

    /**
     * 统一处理网络请求结果
     */
    fun <T> dealRequestResult(
        it: Result<T>,
        getResultCallback: GetResultCallback,
        showLoading: Boolean = false,
        isShowNoDataTip: Boolean = true,
        isShowRequestErrorTip: Boolean = true,
        isShowCodeError: Boolean = true,
        errorTip: String = getString(R.string.txt_net_error)
    ) {
        try {
            showLoading(showLoading)
            //服务器返回错误信息
            val exceptionMessage = it.exceptionOrNull()?.message
            //服务器返回错误code
            val exceptionCode: String? = it.exceptionOrNull()?.toString()
            LogUtil.d("Throwable异常", "code=${exceptionCode},${exceptionMessage}")
            if (null != exceptionCode) {
                //处理注册用户已存在的情况
                if (exceptionCode == ErrorCode.USER_HAS_EXIST.toString()) {
                    getResultCallback.onRequestError(exceptionCode)
                }

                if (exceptionCode == ErrorCode.DEVICE_HAS_BIND.toString()) {
                    val str =
                        String.format(getString(R.string.txt_device_has_bind), exceptionMessage)
                    showToast(str)
                    getResultCallback.onInterceptCode()
                    return
                }
                //拦截请求异常code
                else if (netErrorCodeTips(exceptionCode, isShowCodeError)) {
                    //已经处理相关错误码就直接返回
                    getResultCallback.onInterceptCode()
                    return
                }
            }

            val data = it.getOrNull()
            if (null == data) {
                if (isShowRequestErrorTip) {
                    if (NetworkUtil.isNetworkAvailable(mContext)) {
                        showToast(errorTip)
                    } else {
                        showToast(R.string.txt_no_internet)
                    }
                }
                if (mNetworkRequestsFailRetryCount < mNetworkRequestsFailMaxCount) {
                    mNetworkRequestsFailRetryCount++
                    getResultCallback.onRequestError(exceptionCode)
                } else {
                    //请求次数上限
                    getResultCallback.onRequestError(mNetworkRequestsFailLimit)
                }
            } else {
                mNetworkRequestsFailRetryCount = 0
                if (isShowNoDataTip && data is MutableList<*> && data.size == 0) {
                    showToast(R.string.no_data)
                }
                //不做强制类型转换
                getResultCallback.onResult(0)
            }
        } catch (e: Exception) {
            finish()
            LogUtil.e("接口出错造成的异常:${e.message}")
        }
    }

    /**
     * 网络请求错误code提示
     */
    private fun netErrorCodeTips(exceptionCode: String, isShowCodeError: Boolean = true): Boolean {
        //设备已过期,请续费
        when (exceptionCode) {
            ErrorCode.DEVICE_RENEWAL.toString() -> {
                if (isShowCodeError) showToast(R.string.txt_device_renewal)
                return true
            }
            //TOKEN失效或者过期
            ErrorCode.TOKEN_OVERDUE.toString() -> {
                if (isShowCodeError) showToast(R.string.txt_token_overdue)
                return true
            }
            //用户名或密码错误
            ErrorCode.USER_PASSWORD_ERROR.toString() -> {
                if (isShowCodeError) showToast(
                    R.string.txt_user_password_error, gravity = Gravity.CENTER
                )
                return true
            }
            //验证码错误
            ErrorCode.VERIFY_CODE_ERROR.toString() -> {
                if (isShowCodeError) showToast(
                    R.string.txt_verify_code_error, gravity = Gravity.CENTER
                )
                return true
            }
            //验证码已过期
            ErrorCode.VERIFY_CODE_EXPIRE.toString() -> {
                if (isShowCodeError) showToast(
                    R.string.txt_verify_code_expire, gravity = Gravity.CENTER
                )
                return true
            }
            //注册失败
            ErrorCode.REGISTER_FAIL.toString() -> {
                if (isShowCodeError) showToast(R.string.txt_register_fail, gravity = Gravity.CENTER)
                return true
            }
            //用户不存在
            ErrorCode.USER_NO_EXIST.toString() -> {
                if (isShowCodeError) showToast(R.string.txt_user_no_exist, gravity = Gravity.CENTER)
                return true
            }
            //用户已存在
            ErrorCode.USER_HAS_EXIST.toString() -> {
                if (!isInterceptNetErrorCodeTip && isShowCodeError) {
                    showToast(R.string.txt_user_has_exist, gravity = Gravity.BOTTOM)
                }
                return true
            }
            //邮箱格式不对
            ErrorCode.EMAIL_FORMAT_ERROR.toString() -> {
                if (isShowCodeError) showToast(
                    R.string.txt_email_format_error, gravity = Gravity.CENTER
                )
                return true
            }
            //不能分享给自己
            ErrorCode.NO_SHARE_MYSELF.toString() -> {
                if (isShowCodeError) showToast(R.string.txt_no_share_myself)
                return true
            }
            //当前用户已经绑定该设备
            ErrorCode.DEVICE_HAS_BOUND.toString() -> {
                if (isShowCodeError) showToast(R.string.txt_device_has_bound)
                return true
            }
            //该设备已被绑定
//            ErrorCode.DEVICE_HAS_BIND.toString() -> {
//                if (isShowCodeError) showToast(R.string.txt_device_has_bind)
//                return true
//            }
            //设备不存在
            ErrorCode.DEVICE_NOT_EXIST.toString() -> {
                if (isShowCodeError) showToast(R.string.txt_no_dfu)
                return true
            }
            //系统异常
            "1001" -> {
                if (isShowCodeError) showToast(R.string.txt_system_error, gravity = Gravity.CENTER)
                return true
            }

            "1002" -> {
                if (isShowCodeError) showToast(R.string.txt_missing_param, gravity = Gravity.CENTER)
                return true
            }

            "1003" -> {
                if (isShowCodeError) showToast(R.string.txt_tracker_busy, gravity = Gravity.CENTER)
                return true
            }

            "1004" -> {
                if (isShowCodeError) showToast(
                    R.string.txt_tracker_offline, gravity = Gravity.CENTER
                )
                return true
            }

            "1005" -> {
                if (isShowCodeError) showToast(R.string.txt_tracker_live, gravity = Gravity.CENTER)
                return true
            }

            "1006" -> {
                if (isShowCodeError) showToast(
                    R.string.txt_time_out_try_again, gravity = Gravity.CENTER
                )
                return true
            }

            "1007" -> {
                if (isShowCodeError) showToast(R.string.txt_abnormity, gravity = Gravity.CENTER)
                return true
            }

            else -> return false
        }
    }

    /**
     * 监听软键盘隐藏
     */
    open fun listenHideKeyboard() {}

    /******************************点击屏幕页面隐藏软键盘start**************************************/
//    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
//        if (ev.action == MotionEvent.ACTION_DOWN) {
//            val v = currentFocus
//            v?.let {
//                //如果搜索框内没有输入，隐藏键盘时则返回Contacts页面
//                if (isShouldHideKeyboard(v, ev)) {
//                    if (hideInputMethod(it)) {
//                        LogUtil.e("dispatchTouchEvent-->listenHideKeyboard,隐藏键盘")
//                        listenHideKeyboard()
//                        //这里可以执行隐藏需要执行的任务;
//                        //隐藏键盘时，其他控件不响应点击事件==》注释则不拦截点击事件
//                        //不拦截事件，按钮需要事件
////                        return true
//                    }
//                }
//            }
//
//        }
//        return super.dispatchTouchEvent(ev)
//    }

    /**
     * 获取InputMethodManager
     */
    private fun getInputMethodManager(): InputMethodManager? {
        if (null == mInputMethodManager) mInputMethodManager =
            getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        return mInputMethodManager
    }

    /**
     * 隐藏软键盘
     */
    fun hideInputMethod(view: View): Boolean {
        getInputMethodManager()?.apply {
            return hideSoftInputFromWindow(view.windowToken, 0)
        }
        return false
    }

    /**
     * 弹出软键盘
     */
    fun showInputMethod(view: View) {
        getInputMethodManager()?.apply {
            showSoftInput(view, InputMethodManager.SHOW_IMPLICIT)
        }
    }

    /**
     * 根据EditText所在坐标和用户点击的坐标相对比，来判断是否隐藏键盘，因为当用户点击EditText时则不能隐藏
     */
    private fun isShouldHideKeyboard(v: View?, ev: MotionEvent): Boolean {
        if (v != null && (v is EditText)) {
            val l = intArrayOf(0, 0)
            v.getLocationInWindow(l)
            val left = l[0]
            val top = l[1]
            val bottom = top + v.getHeight()
            val right = left + v.getWidth()
            return !(ev.x > left && ev.x < right && ev.y > top && ev.y < bottom)
        }
        // 如果焦点不是EditText则忽略，这个发生在视图刚绘制完，第一个焦点不在EditText上，和用户用轨迹球选择其他的焦点
        return false
    }

    /******************************点击屏幕页面隐藏软键盘end**************************************/


    /**
     * 软键盘显示
     */
    open fun showSoftKeyboardCallback() {
        LogUtil.e("监听重写软键盘弹出")
    }

    /**
     * 软键盘隐藏
     */
    open fun hideSoftKeyboardCallback() {
        LogUtil.e("监听重写软键盘隐藏")
    }

    /*
     * 获取导航栏高度
     */
    private fun getNavigatorBarHeight(): Int {
//        val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
//        val height = resources.getDimensionPixelSize(resourceId)
        return QMUIDisplayHelper.getNavMenuHeight(mContext)
    }

    /**
     * 监听因输入框弹出,遮挡输入框,界面移动
     * @param translateView 需要移动的view
     * @param translateY 移动的坐标点
     */
    private fun onLayoutChange(translateView: View, translateY: Int) {
        mTranslateView = translateView
        //获取当前屏幕内容的高度
        val screenHeight = translateView.height
        //获取View可见区域的bottom
        val rect = Rect()
        translateView.getWindowVisibleDisplayFrame(rect)
        if (screenHeight - getNavigatorBarHeight() > rect.bottom) {
            // 获取按钮的左上角，按钮高度为40dp
//            val location = IntArray(2)
//            translateView.getLocationOnScreen(location)
//            val bottom = location[1] + resources.getDimensionPixelSize(R.dimen.dp_80)
////             如果按钮被覆盖，移动整个界面向上移动
//            if (bottom > rect.bottom) {
//                translateView.scrollBy(0, bottom - rect.bottom)
//                isKeyboardTranslate = true
//            }
            if (!isKeyboardTranslate) {
                //移动到指定位置点坐标
                translateView.scrollBy(0, translateY)
                isKeyboardTranslate = true
            }
            LogUtil.e("软键盘弹出")
            showSoftKeyboardCallback()
        } else {
            LogUtil.e("隐藏软键盘")
            if (isKeyboardTranslate) {
                translateView.scrollTo(0, 0)
                isKeyboardTranslate = false
            }
            hideSoftKeyboardCallback()
        }
    }

    private fun onGlobalLayoutChange(translateView: View, translateY: Int) {
        mTranslateView = translateView
        val r = Rect()
        translateView.getWindowVisibleDisplayFrame(r)
        val heightDiff = translateView.getRootView().height - (r.bottom - r.top)
        if (heightDiff > 200) { // 如果高度差大于200，说明键盘是弹出的
            // 进行布局调整
            if (!isKeyboardTranslate) {
                //移动到指定位置点坐标
                translateView.scrollBy(0, translateY)
                isKeyboardTranslate = true
            }
            LogUtil.e("如果高度差大于200，说明键盘是弹出的")
            showSoftKeyboardCallback()
        } else {
            // 键盘隐藏，恢复布局
            isKeyboardTranslate = false
            LogUtil.e("键盘隐藏，恢复布局")
            translateView.scrollTo(0, 0)
            hideSoftKeyboardCallback()
        }
    }
    /*****************************监听软键盘弹出，输入框上移end************************************/
}