package com.gh.gamecenter.common.utils

import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface.OnCancelListener
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Typeface
import android.graphics.drawable.ColorDrawable
import android.text.Html
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.style.StyleSpan
import android.view.*
import android.widget.ImageView
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.annotation.DrawableRes
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import androidx.viewbinding.ViewBinding
import com.gh.gamecenter.common.R
import com.gh.gamecenter.common.base.TrackableDialog
import com.gh.gamecenter.common.callback.ConfirmListener
import com.gh.gamecenter.common.databinding.DialogAlertDefaultBinding
import com.gh.gamecenter.common.databinding.DialogGuideBinding
import com.gh.gamecenter.common.databinding.DialogProgressBinding
import com.gh.gamecenter.core.provider.IConfigProvider
import com.gh.gamecenter.core.provider.IDirectProvider
import com.gh.gamecenter.core.provider.ISettingProvider
import com.gh.gamecenter.core.provider.IUpdateManagerProvider
import com.gh.gamecenter.core.utils.EmptyCallback
import com.gh.gamecenter.core.utils.MtaHelper
import com.google.android.material.imageview.ShapeableImageView
import com.lightgame.download.DownloadEntity
import com.lightgame.utils.AppManager
import com.lightgame.view.CheckableLinearLayout
import com.therouter.TheRouter
import splitties.systemservices.layoutInflater

object DialogHelper {

    /**
     * 光环常规弹窗
     *
     * extraConfig，可选标题居中、内容居中、是否显示关闭按钮、是否显示正文辅助文本以及显示标题左侧图标等
     *
     * uiModificationCallback，可用来手动微调样式的回调，可使用 binding 来修改颜色、文字大小等
     */
    @JvmOverloads
    fun showDialog(
        context: Context,
        title: String,
        content: CharSequence,
        confirmText: String,
        cancelText: String,
        confirmClickCallback: (() -> Unit)? = null,
        cancelClickCallback: (() -> Unit)? = null,
        dialogCancelCallback: (() -> Unit)? = null,
        touchOutsideCallback: (() -> Unit)? = null,
        extraConfig: Config? = null,
        uiModificationCallback: ((binding: DialogAlertDefaultBindingWrapper) -> Unit)? = null,
        trackMtaEvent: Boolean = false,
        mtaEvent: String = "",
        mtaKey: String = ""
    ): DialogAlertDefaultBindingWrapper? {
        val solidContext = checkDialogContext(context) ?: return null

        if (solidContext is Activity && solidContext.isFinishing) return null

        val dialog = if (trackMtaEvent) {
            TrackableDialog(solidContext, R.style.GhAlertDialog, mtaEvent, mtaKey)
        } else {
            Dialog(solidContext, R.style.GhAlertDialog)
        }

        val binding = DialogAlertDefaultBindingWrapper(
            dialog = dialog,
            binding = DialogAlertDefaultBinding.inflate(LayoutInflater.from(solidContext))
        )
        val contentView = binding.root
        binding.contentTv.text = content
        binding.titleTv.text = title

        extraConfig?.let {
            if (it.hint.isNotEmpty()) {
                binding.hintTv.visibility = View.VISIBLE
                binding.hintTv.text = it.hint
            }

            if (it.centerTitle) {
                binding.titleTv.gravity = Gravity.CENTER
            }

            if (it.centerContent) {
                binding.contentTv.gravity = Gravity.CENTER
            }

            if (it.showCloseIcon) {
                binding.closeContainer.visibility = View.VISIBLE
                binding.closeContainer.enlargeTouchArea()
                binding.closeContainer.setOnClickListener {
                    binding.markDismissByTouchInside()
                    dialog.dismiss()
                }
            }

            if (it.titleIcon != -1) {
                binding.titleTv.setDrawableStart(it.titleIcon)
            }
        }

        if (cancelText.isEmpty()) {
            binding.cancelTv.visibility = View.GONE
            binding.centerDivider.visibility = View.GONE
        }

        binding.cancelTv.text = cancelText
        binding.confirmTv.text = confirmText

        binding.cancelTv.setOnClickListener {
            binding.markDismissByTouchInside()

            if (trackMtaEvent) {
                MtaHelper.onEvent(mtaEvent, mtaKey, "点击$cancelText")
            }

            cancelClickCallback?.invoke()
            dialog.dismiss()
        }

        binding.confirmTv.setOnClickListener {
            binding.markDismissByTouchInside()

            if (trackMtaEvent) {
                MtaHelper.onEvent(mtaEvent, mtaKey, "点击$confirmText")
            }

            confirmClickCallback?.invoke()
            dialog.dismiss()
        }

        binding.setOnTouchOutsideListener {
            touchOutsideCallback?.invoke()
        }

        uiModificationCallback?.invoke(binding)

        dialog.setOnCancelListener {
            dialogCancelCallback?.invoke()
        }
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        dialog.setContentView(contentView)
        dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        dialog.show()

        return binding
    }

    /**
     * 光环引导弹窗
     *
     * extraConfig，可选标题居中、内容居中、是否显示关闭按钮、是否显示正文辅助文本以及显示标题左侧图标等
     *
     * uiModificationCallback，可用来手动微调样式的回调，可使用 binding 来修改颜色、文字大小等
     */
    fun showGuideDialog(
        context: Context,
        title: String,
        content: CharSequence,
        confirmText: String,
        cancelText: String,
        confirmClickCallback: (() -> Unit)? = null,
        cancelClickCallback: (() -> Unit)? = null,
        touchOutsideCallback: (() -> Unit)? = null,
        extraConfig: Config? = null,
        uiModificationCallback: ((binding: DialogGuideBindingWrapper) -> Unit)? = null,
        trackMtaEvent: Boolean = false,
        mtaEvent: String = "",
        mtaKey: String = ""
    ): Dialog? {

        val solidContext = checkDialogContext(context) ?: return null

        if (solidContext is Activity && solidContext.isFinishing) return null

        val dialog = if (trackMtaEvent) {
            TrackableDialog(solidContext, R.style.GhAlertDialog, mtaEvent, mtaKey)
        } else {
            Dialog(solidContext, R.style.GhAlertDialog)
        }

        val binding = DialogGuideBindingWrapper(
            dialog = dialog,
            binding = DialogGuideBinding.inflate(LayoutInflater.from(solidContext))
        )
        val contentView = binding.root
        binding.contentTv.text = content
        binding.titleTv.text = title

        initGuideDialogExtraConfig(binding, extraConfig)

        if (cancelText.isEmpty()) {
            binding.cancelTv.visibility = View.GONE
        }

        binding.cancelTv.text = cancelText
        binding.confirmTv.text = confirmText

        binding.cancelTv.setOnClickListener {
            binding.markDismissByTouchInside()

            if (trackMtaEvent) MtaHelper.onEvent(mtaEvent, mtaKey, "点击$cancelText")

            cancelClickCallback?.invoke()
            dialog.dismiss()
        }

        binding.confirmTv.setOnClickListener {
            binding.markDismissByTouchInside()
            if (trackMtaEvent) MtaHelper.onEvent(mtaEvent, mtaKey, "点击$confirmText")

            confirmClickCallback?.invoke()
            dialog.dismiss()
        }

        uiModificationCallback?.invoke(binding)

        binding.setOnTouchOutsideListener {
            touchOutsideCallback?.invoke()
        }

        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        dialog.setContentView(contentView)
        dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        dialog.show()

        return dialog
    }

    private fun initGuideDialogExtraConfig(binding: DialogGuideBindingWrapper, extraConfig: Config?) {
        extraConfig?.let {
            if (it.hint.isNotEmpty()) {
                binding.hintTv.visibility = View.VISIBLE
                binding.hintTv.text = it.hint
            }

            if (it.centerTitle) {
                val constraintSet = ConstraintSet()
                constraintSet.clone(binding.rootContainer)
                constraintSet.setHorizontalBias(R.id.titleTv, 0.5F)
                constraintSet.applyTo(binding.rootContainer)
            }

            if (it.centerContent) {
                binding.contentTv.gravity = Gravity.CENTER
            }

            if (it.showCloseIcon) {
                binding.closeContainer.visibility = View.VISIBLE
                binding.closeContainer.enlargeTouchArea()
                binding.closeContainer.setOnClickListener {
                    binding.markDismissByTouchInside()
                    binding.dismiss()
                }
            }

            if (it.showAlternativeCancelStyle) {
                binding.cancelTv.visibility = View.GONE
                binding.alternativeCancelTv.visibility = View.VISIBLE
                binding.alternativeCancelTv.setOnClickListener {
                    binding.cancelTv.performClick()
                }
            }

            if (it.titleIcon != -1) {
                binding.titleTv.setDrawableStart(it.titleIcon)
            }
        }
    }

    /**
     * For legacy java invocation
     */
    @JvmStatic
    @Deprecated("Kotlin 中请使用其它方法调用")
    fun showDialog(
        context: Context,
        title: String,
        content: CharSequence,
        positiveText: String,
        negativeText: String,
        positiveClickCallback: EmptyCallback,
        negativeClickCallback: EmptyCallback,
        trackMtaEvent: Boolean = false,
        mtaEvent: String = "",
        mtaKey: String = ""
    ) {
        showDialog(
            context = context,
            title = title,
            content = content,
            confirmText = positiveText,
            cancelText = negativeText,
            confirmClickCallback = { positiveClickCallback.onCallback() },
            cancelClickCallback = { negativeClickCallback.onCallback() },
            extraConfig = Config(centerTitle = true, centerContent = true),
            trackMtaEvent = trackMtaEvent,
            mtaEvent = mtaEvent,
            mtaKey = mtaKey
        )
    }

    /**
     * For legacy java invocation
     */
    @JvmStatic
    @JvmOverloads
    @Deprecated("Kotlin 中请使用其它方法调用")
    fun showCenterDialog(
        context: Context,
        title: String,
        content: CharSequence,
        positiveText: String,
        negativeText: String,
        positiveClickCallback: EmptyCallback,
        negativeClickCallback: EmptyCallback,
        touchOutsideCallback: EmptyCallback? = null,
    ) {
        showDialog(
            context = context,
            title = title,
            content = content,
            confirmText = positiveText,
            cancelText = negativeText,
            confirmClickCallback = { positiveClickCallback.onCallback() },
            cancelClickCallback = { negativeClickCallback.onCallback() },
            touchOutsideCallback = { touchOutsideCallback?.onCallback() },
            extraConfig = Config(centerTitle = true, centerContent = true)
        )
    }

    @JvmStatic
    fun getProgressDialog(
        context: Context,
        content: String,
        uiModificationCallback: ((binding: DialogProgressBinding) -> Unit)? = null
    ): Dialog {
        val dialog = Dialog(context)
        val binding = DialogProgressBinding.inflate(context.layoutInflater)
        binding.contentTv.text = content
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        dialog.setContentView(binding.root)
        dialog.setCanceledOnTouchOutside(false)
        dialog.window?.setBackgroundDrawableResource(R.drawable.background_shape_white_radius_8)
        dialog.window?.attributes = dialog.window?.attributes?.apply { width = 160F.dip2px() }
        uiModificationCallback?.invoke(binding)
        dialog.show()
        return dialog
    }

    /**
     * 展示签名冲突提示弹窗
     * @param context 啥下文
     * @param gameId 游戏ID-神策数据埋点字段
     * @param gameName 游戏名称-神策数据埋点字段
     * @param gameType 游戏类型-神策数据埋点字段
     */
    @JvmStatic
    fun showSignatureConflictDialog(
        context: Context,
        gameId: String = "",
        gameName: String = "",
        gameType: String = "",
        confirmClickCallback: (() -> Unit)? = null
    ) {
        SensorsBridge.trackConflictSignatureInstallDialogShow(
            gameId = gameId,
            gameName = gameName,
            gameType = gameType
        )
        showDialog(
            context,
            "温馨提示",
            "检测到安装包与已安装应用的签名不一致，需要卸载后才能安装，是否立即卸载",
            "卸载",
            "取消",
            confirmClickCallback = {
                confirmClickCallback?.invoke()
                SensorsBridge.trackConflictSignatureInstallDialogClick(
                    buttonName = "卸载",
                    gameId = gameId,
                    gameName = gameName,
                    gameType = gameType
                )
            },
            cancelClickCallback = {
                SensorsBridge.trackConflictSignatureInstallDialogClick(
                    buttonName = "取消",
                    gameId = gameId,
                    gameName = gameName,
                    gameType = gameType
                )
            },
            touchOutsideCallback = {
                SensorsBridge.trackConflictSignatureInstallDialogClick(
                    buttonName = "关闭弹窗",
                    gameId = gameId,
                    gameName = gameName,
                    gameType = gameType
                )
            },
            extraConfig = Config(hint = "注意：卸载会让游戏数据丢失，请提前做好备份"),
            uiModificationCallback = { binding -> binding.hintTv.setTextColor(R.color.text_theme.toColor(context)) }
        )
    }

    /**
     * 展示插件化安装提示弹窗
     * @param context 啥下文
     * @param pluginDesc 插件化提示文字
     * @param gameId 游戏ID-神策数据埋点字段
     * @param gameName 游戏名称-神策数据埋点字段
     * @param gameType 游戏类型-神策数据埋点字段
     * @param platform 平台类型-神策数据埋点字段
     */
    @JvmStatic
    fun showPluginDialog(
        context: Context,
        pluginDesc: String? = null,
        gameId: String = "",
        gameName: String = "",
        gameType: String = "",
        platform: String = "",
        confirmClickCallback: (() -> Unit)? = null
    ) {
        SensorsBridge.trackPluginInstallDialogShow(
            gameId = gameId,
            gameName = gameName,
            gameType = gameType,
            platform = platform
        )
        NewFlatLogUtils.logPluginInstallPopShow(
            gameId = gameId,
            gameName = gameName,
            platform = platform
        )
        val pluginDescNonNull = pluginDesc ?: "插件"
        MtaHelper.onEvent("插件化", "插件化安装弹窗", "出现弹窗提示")
        showDialog(
            context,
            "${pluginDescNonNull}化安装",
            "您将进行${pluginDescNonNull}化安装以实现${pluginDescNonNull}功能，此过程将卸载当前使用的版本并安装${pluginDescNonNull}版本",
            "确认，开始${pluginDescNonNull}化",
            "取消",
            confirmClickCallback = {
                confirmClickCallback?.invoke()
                MtaHelper.onEvent("插件化", "插件化安装弹窗", "确认并开始")
                SensorsBridge.trackPluginInstallDialogClick(
                    buttonName = "开始${pluginDesc}化",
                    gameId = gameId,
                    gameName = gameName,
                    gameType = gameType,
                    platform = platform
                )
                NewFlatLogUtils.logPluginInstallPopClick(
                    buttonName = "开始${pluginDesc}化",
                    gameId = gameId,
                    gameName = gameName,
                    platform = platform
                )
            },
            cancelClickCallback = {
                MtaHelper.onEvent("插件化", "插件化安装弹窗", "取消")
                SensorsBridge.trackPluginInstallDialogClick(
                    buttonName = "取消",
                    gameId = gameId,
                    gameName = gameName,
                    gameType = gameType,
                    platform = platform
                )
                NewFlatLogUtils.logPluginInstallPopClick(
                    buttonName = "取消",
                    gameId = gameId,
                    gameName = gameName,
                    platform = platform
                )
            },
            touchOutsideCallback = {
                SensorsBridge.trackPluginInstallDialogClick(
                    buttonName = "关闭弹窗",
                    gameId = gameId,
                    gameName = gameName,
                    gameType = gameType,
                    platform = platform
                )
                NewFlatLogUtils.logPluginInstallPopClick(
                    buttonName = "关闭弹窗",
                    gameId = gameId,
                    gameName = gameName,
                    platform = platform
                )
            },
            extraConfig = Config(hint = "注意：卸载前请妥善保存游戏账号与密码"),
            uiModificationCallback = { binding -> binding.hintTv.setTextColor(R.color.text_FF0000.toColor()) }
        )
    }

    @JvmStatic
    fun showUpgradeDialog(context: Context) {
        showDialog(
            context,
            "提示",
            "当前版本暂不支持该功能，\n建议您升级到最新版本体验哦",
            "检查升级",
            "取消",
            confirmClickCallback = {
                val settingProvider = TheRouter.get(ISettingProvider::class.java)

                context.startActivity(settingProvider?.getAboutIntent(context, true))
            },
            uiModificationCallback = {
                it.titleTv.gravity = Gravity.CENTER
                it.contentTv.gravity = Gravity.CENTER
            }
        )
    }

    @JvmStatic
    fun showDowngradeHintDialog(
        context: Context,
        confirmClickCallback: (() -> Unit)? = null
    ) {
        showDialog(
            context,
            "温馨提示",
            "您已安装较高版本，若要安装历史版本需先卸载再安装\n",
            "我知道了",
            "",
            { confirmClickCallback?.invoke() })
    }

    @JvmStatic
    fun showCenterWarningDialog(
        context: Context,
        title: String,
        msg: CharSequence,
        confirmClickCallback: EmptyCallback
    ) {
        showCenterWarningDialog(
            context = context,
            title = title,
            msg = msg,
            confirmClickCallback = { confirmClickCallback.onCallback() },
            cancelClickCallback = null,
        )
    }

    @JvmStatic
    fun showWarningDialog(
        context: Context,
        title: String,
        msg: CharSequence,
        cancelText: String = "取消",
        confirmText: String = "确定",
        confirmClickCallback: (() -> Unit)? = null,
        cancelClickCallback: (() -> Unit)? = null
    ) {
        showDialog(
            context,
            title,
            msg,
            confirmText,
            cancelText,
            confirmClickCallback,
            cancelClickCallback
        )
    }

    @JvmStatic
    fun showCenterWarningDialog(
        context: Context,
        title: String,
        msg: CharSequence,
        cancelText: String = "取消",
        confirmText: String = "确定",
        confirmClickCallback: (() -> Unit)? = null,
        cancelClickCallback: (() -> Unit)? = null
    ) {
        showDialog(
            context,
            title,
            msg,
            confirmText,
            cancelText,
            confirmClickCallback,
            cancelClickCallback,
            extraConfig = Config(centerContent = true, centerTitle = true)
        )
    }

    @JvmStatic
    fun showDownloadDialog(context: Context, listener: ConfirmListener) {
        showCenterWarningDialog(
            context,
            "下载提示",
            "您当前使用的网络为2G/3G/4G，开始下载将会消耗移动流量，确定下载？",
            confirmClickCallback = { listener.onConfirm() }
        )
    }

    @JvmStatic
    fun showCancelDialog(
        context: Context,
        confirmClickCallback: (() -> Unit)? = null,
        cancelClickCallback: (() -> Unit)? = null
    ) {
        val content = Html.fromHtml(context.getString(R.string.cancel_concern_dialog))
        showDialog(
            context,
            "取消关注",
            content,
            "确定取消",
            "暂不取消",
            confirmClickCallback,
            cancelClickCallback,
            extraConfig = Config(centerTitle = true, centerContent = true)
        )
    }

    @JvmStatic
    fun showDialogWithHtmlContent(
        context: Context,
        title: String,
        content: String,
        confirmText: String,
        cancelText: String,
        confirmClickCallback: (() -> Unit)? = null,
        cancelClickCallback: (() -> Unit)? = null,
        touchOutsideCallback: (() -> Unit)? = null,
        extraConfig: Config? = null
    ) {
        val webContent = Html.fromHtml(content)
        showDialog(
            context,
            title,
            webContent,
            confirmText,
            cancelText,
            confirmClickCallback,
            cancelClickCallback,
            touchOutsideCallback = touchOutsideCallback,
            extraConfig = extraConfig
        )
    }

    fun showDeleteGameCommentDialog(
        context: Context,
        content: String,
        confirmClickCallback: (() -> Unit)
    ) {
        showDialog(
            context,
            "提示",
            content,
            "删除",
            "取消",
            confirmClickCallback,
            extraConfig = Config(centerTitle = true, centerContent = true)
        )
    }

    @JvmStatic
    fun showLibaoActivityDialog(
        context: Context,
        isHideHint: Boolean,
        hintClickCallback: EmptyCallback
    ) {
        showDialog(
            context,
            "查看礼包码",
            "游戏礼包可通过参与活动获取",
            "我知道了",
            "",
            extraConfig = Config(centerTitle = true),
            uiModificationCallback = { binding ->
                binding.hintTv.run {
                    if (isHideHint) {
                        visibility = View.GONE
                    } else {
                        visibility = View.VISIBLE
                        text = "查看活动详情"
                        setTextColor(R.color.text_theme.toColor(context))
                        setDrawableEnd(R.drawable.ic_libao_activity_arrow)
                        compoundDrawablePadding = 4F.dip2px()
                        setOnClickListener {
                            hintClickCallback.onCallback()
                        }
                    }
                }

                binding.lineView.visibility = View.GONE

                binding.confirmTv.run {
                    layoutParams = (layoutParams as ViewGroup.MarginLayoutParams).apply {
                        leftMargin = 24F.dip2px()
                        topMargin = 24F.dip2px()
                        rightMargin = 24F.dip2px()
                        bottomMargin = 26F.dip2px()
                    }
                    setBackgroundResource(R.drawable.button_blue_oval)
                    setTextColor(R.color.text_white.toColor(context))
                }
            }
        )
    }

    fun showVideoUnsupportedDialog(context: Context) {
        showDialog(
            context,
            "提示",
            "抱歉，您当前系统版本过低，暂不支持视频功能",
            "我知道了",
            "",
            null,
            null
        )
    }

    @JvmStatic
    fun showDeleteDialog(
        context: Context,
        title: String,
        msg: CharSequence,
        confirmText: String,
        cancelText: String,
        confirmClickCallback: EmptyCallback?,
        cancelClickCallback: EmptyCallback?,
        isReverse: Boolean
    ) {
        showDialog(
            context,
            title,
            msg,
            if (isReverse) cancelText else confirmText,
            if (isReverse) confirmText else cancelText,
            confirmClickCallback = {
                if (isReverse) cancelClickCallback?.onCallback() else confirmClickCallback?.onCallback()
            },
            cancelClickCallback = {
                if (isReverse) confirmClickCallback?.onCallback() else cancelClickCallback?.onCallback()
            },
            uiModificationCallback = {
                val colorAccentRes = if (isReverse) R.color.secondary_red else R.color.text_secondary
                val colorDefaultRes = if (isReverse) R.color.text_secondary else R.color.secondary_red
                it.cancelTv.setTextColor(colorAccentRes.toColor(context))
                it.confirmTv.setTextColor(colorDefaultRes.toColor(context))
            },
            extraConfig = Config(centerTitle = true, centerContent = true)
        )?.setOnCancelListener {
            cancelClickCallback?.onCallback()
        }
    }

    // 网络劫持时 打开QQ客户端，创建临时会话
    @JvmStatic
    fun showQqSessionDialog(context: Context) {
        val configProvider = TheRouter.get(IConfigProvider::class.java)
        val directProvider = TheRouter.get(IDirectProvider::class.java)
        val qq = configProvider?.getQQ() ?: ""
        showDialog(
            context, "警告", "您当前网络环境异常，下载地址可能被运营商恶意替换（网络劫持）" +
                    "，如多次下载失败，请联系客服获取正确的下载地址（客服QQ：" + qq + "）", "前往QQ", "取消",
            { directProvider?.directToQqConversation(context, qq) },
            extraConfig = Config(centerTitle = true)
        )
    }


    @JvmStatic
    fun showUnsupportedFeatureDialog(context: Context) {
        showDialog(
            context = context,
            title = context.getString(R.string.unsupported_feature_dialog_title),
            content = context.getString(R.string.unsupported_feature_dialog_hint),
            confirmText = context.getString(R.string.unsupported_feature_dialog_confirm_text),
            cancelText = context.getString(R.string.unspported_feature_dialog_cancel_text),
            confirmClickCallback = {
                if (context is FragmentActivity) {
                    val updateManager = TheRouter.get(IUpdateManagerProvider::class.java)
                    updateManager?.checkUpdate(context, false)
                }
            },
            cancelClickCallback = {},
            extraConfig = Config(centerTitle = true, centerContent = true)
        )
    }

    fun showMiuiOptimizationWarning(
        context: Context,
        downloadEntity: DownloadEntity,
        onHintClick: () -> Unit,
        onConfirmClick: (DialogAlertDefaultBindingWrapper) -> Unit,
    ) {
        SensorsBridge.trackMiuiOptimizeCloseDialogShow(
            gameId = downloadEntity.gameId,
            gameName = downloadEntity.name,
            gameType = downloadEntity.categoryChinese
        )
        showDialog(
            context = context,
            title = context.getString(R.string.miui_optimization_warning_dialog_title),
            content = SpannableStringBuilder(
                context.getString(R.string.miui_optimization_warning_dialog_content)
            ).apply {
                setSpan(StyleSpan(Typeface.BOLD), 10, 15, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
            },
            confirmText = context.getString(R.string.miui_optimizaition_warning_dialog_confirm),
            cancelText = context.getString(R.string.miui_optimizaition_warning_dialog_cancel),
            extraConfig = Config(),
            uiModificationCallback = { binding ->
                binding.hintTv.text = context.getString(R.string.miui_optimizaition_warning_dialog_hint)
                binding.hintTv.visibility = View.VISIBLE
                binding.hintTv.paint.flags = Paint.UNDERLINE_TEXT_FLAG
                binding.hintTv.paint.isAntiAlias = true
                binding.hintTv.setTextColor(ContextCompat.getColor(context, R.color.text_theme))
                binding.hintTv.setOnClickListener {
                    SensorsBridge.trackMiuiOptimizeCloseDialogClick(
                        buttonName = "查看教程",
                        gameId = downloadEntity.gameId,
                        gameName = downloadEntity.name,
                        gameType = downloadEntity.categoryChinese
                    )
                    onHintClick.invoke()
                }
                binding.confirmTv.setOnClickListener {
                    SensorsBridge.trackMiuiOptimizeCloseDialogClick(
                        buttonName = "立即关闭",
                        gameId = downloadEntity.gameId,
                        gameName = downloadEntity.name,
                        gameType = downloadEntity.categoryChinese
                    )
                    onConfirmClick.invoke(binding)
                }
            },
            cancelClickCallback = {
                SensorsBridge.trackMiuiOptimizeCloseDialogClick(
                    buttonName = "以后再说",
                    gameId = downloadEntity.gameId,
                    gameName = downloadEntity.name,
                    gameType = downloadEntity.categoryChinese
                )
            },
            touchOutsideCallback = {
                SensorsBridge.trackMiuiOptimizeCloseDialogClick(
                    buttonName = "关闭弹窗",
                    gameId = downloadEntity.gameId,
                    gameName = downloadEntity.name,
                    gameType = downloadEntity.categoryChinese
                )
            }
        )
    }

    /**
     * @param context may be is application context
     * @return activity context
     */
    fun checkDialogContext(context: Context?): Context? {
        if (context == null) {
            throw NullPointerException("dialog context is null")
        }
        return context as? Activity ?: AppManager.getInstance().currentActivity()

        // currentActivity 是否存在 isDestroyed 的情况?
    }

    class Config(
        val hint: String = "",
        val showCloseIcon: Boolean = false,
        val centerTitle: Boolean = false,
        val centerContent: Boolean = false,
        val showAlternativeCancelStyle: Boolean = false, // 是否显示另类的取消样式
        @DrawableRes
        val titleIcon: Int = -1
    )

    class DialogGuideBindingWrapper(
        dialog: Dialog,
        binding: DialogGuideBinding
    ) : DialogBindingWrapper<DialogGuideBinding>(dialog, binding) {
        val rootContainer: ConstraintLayout get() = binding.rootContainer
        val titleTv: TextView get() = binding.titleTv
        val hintTv: TextView get() = binding.hintTv
        val extraHintIv: ImageView get() = binding.extraHintIv
        val cancelTv: TextView get() = binding.cancelTv
        val confirmTv: TextView get() = binding.confirmTv
        val closeContainer: View get() = binding.closeContainer
        val headIv: ShapeableImageView get() = binding.headIv
        val closeIv: ImageView get() = binding.closeIv
        val contentTv: TextView get() = binding.contentTv
        val alternativeCancelTv: TextView get() = binding.alternativeCancelTv
        val selectorContainer: CheckableLinearLayout get() = binding.selectorContainer
    }

    /**
     * 通用Alert弹窗包装类
     */
    class DialogAlertDefaultBindingWrapper(
        dialog: Dialog,
        binding: DialogAlertDefaultBinding
    ) : DialogBindingWrapper<DialogAlertDefaultBinding>(dialog, binding) {
        val titleTv: TextView get() = binding.titleTv
        val contentTv: TextView get() = binding.contentTv
        val hintTv: TextView get() = binding.hintTv
        val centerDivider: View get() = binding.centerDivider
        val closeContainer: RelativeLayout get() = binding.closeContainer
        val cancelTv: TextView get() = binding.cancelTv
        val confirmTv: TextView get() = binding.confirmTv
        val lineView: View get() = binding.lineView
        val extraContentView: View get() = binding.extraContentView
        val extraContentTv: TextView get() = binding.extraContentTv
    }

    /**
     * 通用弹窗Binding包装类，可通过该类代理一些Dialog相关的方法
     */
    abstract class DialogBindingWrapper<T: ViewBinding>(
        val dialog: Dialog,
        protected val binding: T
    ) {
        val root: View = binding.root

        private var dismissByTouchInside: Boolean = false

        private var onDismissListener: ((DialogBindingWrapper<T>) -> Unit)? = null

        private var onTouchOutsideListener: ((DialogBindingWrapper<T>) -> Unit)? = null

        init {
            dialog.setOnDismissListener {
                if (!dismissByTouchInside) {
                    onTouchOutsideListener?.invoke(this)
                }
                onDismissListener?.invoke(this)
            }
        }

        fun markDismissByTouchInside() {
            dismissByTouchInside = true
        }

        fun setOnCancelListener(listener: OnCancelListener) {
            dialog.setOnCancelListener(listener)
        }

        fun setOnDismissListener(listener: ((DialogBindingWrapper<T>) -> Unit)?) {
            onDismissListener = listener
        }

        fun setOnTouchOutsideListener(listener: ((DialogBindingWrapper<T>) -> Unit)?) {
            onTouchOutsideListener = listener
        }

        fun setCancelable(cancelable: Boolean) {
            dialog.setCancelable(cancelable)
        }

        fun dismiss() = dialog.dismiss()
    }

}