package com.gh.common

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.util.Base64
import android.view.View
import android.webkit.JavascriptInterface
import androidx.annotation.Keep
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import com.gh.common.exposure.ExposureManager
import com.gh.common.util.*
import com.gh.common.util.LogUtils
import com.gh.download.DownloadManager
import com.gh.download.PackageObserver
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.ImageViewerActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.common.callback.BiCallback
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.Constants.SP_MEMBER_PAYMENT_BUTTON_CLICK
import com.gh.gamecenter.common.constant.Constants.SP_MEMBER_RECHARGE_BUTTON_CLICK
import com.gh.gamecenter.common.entity.NotificationUgc
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.loghub.LoghubUtils
import com.gh.gamecenter.common.provider.IHelpAndFeedbackProvider
import com.gh.gamecenter.common.tracker.Tracker
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.utils.NewFlatLogUtils
import com.gh.gamecenter.common.utils.SensorsBridge.EVENT_MEMBER_RECHARGE_BUTTON_CLICK
import com.gh.gamecenter.common.utils.SensorsBridge.EVENT_NAME
import com.gh.gamecenter.common.utils.SensorsBridge.KEY_IS_FIRST_TIME
import com.gh.gamecenter.common.view.dsbridge.CompletionHandler
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.core.provider.IPushProvider
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.runOnUiThread
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.entity.SensorsEvent
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.entity.AcctRecordEntity
import com.gh.gamecenter.feature.entity.Badge
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.OrderEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.login.user.LoginTag
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.login.user.UserRepository
import com.gh.gamecenter.login.utils.LoginHelper
import com.gh.gamecenter.login.utils.QuickLoginHelper
import com.gh.gamecenter.login.view.LoginActivity
import com.gh.gamecenter.personalhome.border.AvatarBorderActivity
import com.gh.gamecenter.setting.SettingBridge
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.halo.assistant.accelerator.repository.AccelerationRepository.Companion.PAYMENT_TYPE_ALIPAY
import com.halo.assistant.accelerator.repository.AccelerationRepository.Companion.PAYMENT_TYPE_WECHAT
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus.*
import com.lightgame.utils.Utils
import com.therouter.TheRouter
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.json.JSONObject
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileOutputStream
import java.util.*

class DefaultJsApi(
    var context: Context,
    val entrance: String = "",
    private val mFragment: Fragment? = null,
    private var mBbsId: String? = "",
    private var mOriginUrl: String? = "",
    private val mForumName: String? = "",
    private val listener: OnWebClickListener? = null
) {

    companion object {
        private const val SOURCE_ENTRANCE = "webView"
    }

    private var mLoginHandler: CompletionHandler<Any>? = null
    private var mDownloadWatcher: DataWatcher? = null // 下载观察者
    private var mDownloadUrlSet: HashSet<String>? = null // 下载的 url 集合
    private var mDownloadHandler: CompletionHandler<Any>? = null // 下载信息回调
    private var mExposureEvent: ExposureEvent? = null // 活动曝光实体

    private val handler = Handler(Looper.getMainLooper())

    init {
        if (mFragment != null) {
            EventBus.getDefault().register(this)
            autoUnregisterDownloadObserverIfNeeded(mFragment)
        }
    }

    @JavascriptInterface
    fun isEnableForceDark(msg: Any): Boolean {
        return DarkModeUtils.isWebViewForceDarkEnabled
    }

    @JavascriptInterface
    fun isGhzs(msg: Any): String {
        return "true"
    }

    @JavascriptInterface
    fun toast(msg: Any) {
        Utils.toast(HaloApp.getInstance().application, msg.toString())
    }

    @JavascriptInterface
    fun logMtaEvent(event: Any) {
        // do nothing, mta is deprecated
    }

    @JavascriptInterface
    fun logSensorsEvent(event: Any) {
        val sensorsEvent = event.toString().toObject() ?: SensorsEvent()
        val trackEvent = JSONObject()
        tryCatchInRelease {
            sensorsEvent.kv.split(",").forEach {
                val kv = it.split(":")
                trackEvent.put(kv[0], kv[1])
            }
        }
        SensorsBridge.trackEvent(sensorsEvent.name, trackEvent)
    }

    @JavascriptInterface
    fun getUserInfo(msg: Any): String {
        return UserManager.getInstance().userInfoEntity?.toJson() ?: ""
    }

    @JavascriptInterface
    fun getUserToken(msg: Any): String {
        return if (UserManager.getInstance().isLoggedIn) UserManager.getInstance().loginTokenEntity.accessToken.value else ""
    }

    @JavascriptInterface
    fun login(msg: Any) {
        if (NetworkUtils.isQuickLoginEnabled(context)) {
            QuickLoginHelper.startLogin(context, "浏览器")
        } else {
            val intent = LoginActivity.getIntent(context, "浏览器")
            context.startActivity(intent)
        }
    }

    @JavascriptInterface
    fun refreshUserInfoBadge(msg: Any) {
        val userInfoEntity = UserManager.getInstance().userInfoEntity
        if (msg.toString().isNotEmpty()) {
            val badge = msg.toString().toObject() ?: Badge()
            userInfoEntity?.badge = badge
        } else {
            userInfoEntity?.badge = null
        }
        UserManager.getInstance().userInfoEntity = userInfoEntity
    }

    @JavascriptInterface
    fun getChannel(msg: Any): String {
        return HaloApp.getInstance().channel
    }

    @JavascriptInterface
    fun getAppVersion(msg: Any): String {
        return BuildConfig.VERSION_NAME
    }

    @JavascriptInterface
    fun getAppVersionCode(msg: Any): Int {
        return PackageUtils.getGhVersionCode()
    }

    @JavascriptInterface
    fun bindWechat(msg: Any, handler: CompletionHandler<Any>) {
        context.ifLogin("浏览器") {
            LoginHelper.loginWithWechat(object : LoginHelper.LoginCallback {
                @SuppressLint("CheckResult")
                override fun onLoginSuccess(loginType: LoginTag, jsonContent: JSONObject) {

                    val wechatLoginInfoMap = hashMapOf<String, String>()
                    wechatLoginInfoMap["openid"] = jsonContent.getString("openid")
                    wechatLoginInfoMap["unionid"] = jsonContent.getString("unionid")
                    wechatLoginInfoMap["access_token"] = jsonContent.getString("access_token")
                    wechatLoginInfoMap["refresh_token"] = jsonContent.getString("refresh_token")

                    WechatBindHelper.bindWechat(wechatLoginInfoMap, object : BiCallback<Boolean, Boolean> {
                        override fun onFirst(first: Boolean) {
                            handler.complete(true)
                        }

                        override fun onSecond(second: Boolean) {
                            handler.complete(false)
                        }
                    })

                    LoginHelper.unregisterCallback()
                }

                override fun onLoginFailure(loginType: LoginTag, error: String) {
                    handler.complete(false)

                    LoginHelper.unregisterCallback()
                }
            })
        }
    }

    @JavascriptInterface
    fun refreshWechatBindData(msg: Any) {
        WechatBindHelper.getWechatConfig(null)
    }

    @JavascriptInterface
    fun copyText(msg: Any) {
        runOnUiThread {
            msg.toString().copyTextAndToast()
        }
    }

    @JavascriptInterface
    fun startApp(msg: Any) {
        val packageName = msg.toString()
        val context = HaloApp.getInstance().application

        runOnUiThread {
            // 若畅玩列表中安装了，优先启动畅玩游戏
            if (VHelper.isInstalled(packageName)) {
                VHelper.validateVSpaceBeforeAction(context, packageName, null) {
                    VHelper.launch(context, packageName)
                }
            } else {
                val wechatPkgName = "com.tencent.mm"
                if (packageName == wechatPkgName && !PackageUtils.isInstalled(context, wechatPkgName)) {
                    // 如果是微信客户端，需要检查是否安装微信
                    ToastUtils.showToast(R.string.wechat_app_not_install_tips.toResString())
                    return@runOnUiThread
                }
                PackageLauncher.launchApp(context, packageName = packageName)
            }
        }
    }

    @JavascriptInterface
    fun openImage(event: Any) {
        val imageEvent = event.toString().toObject() ?: ImageEvent()

        val context = CurrentActivityHolder.getCurrentActivity()

        context?.startActivity(
            ImageViewerActivity.getIntent(
                context,
                imageEvent.imageList,
                imageEvent.position,
                "浏览器"
            )
        )
    }

    @JavascriptInterface
    fun isInstalled(event: Any): String {
        val localInstalledPackageList = PackageHelper.getInstalledPackageNameList(HaloApp.getInstance().application, 0)
        val packageNameList: ArrayList<String> = event.toString().toObject() ?: ArrayList()

        for (packageName in packageNameList) {
            if (!localInstalledPackageList.contains(packageName)) {
                return "false"
            }
        }

        return "true"
    }

    @JavascriptInterface
    fun openBase64Image(event: Any) {
        val context = CurrentActivityHolder.getCurrentActivity()

        ImageViewerActivity.base64Image = event.toString()

        context?.startActivity(ImageViewerActivity.getBase64Intent(context, true))
    }

    @JavascriptInterface
    fun openNotificationSetting(msg: Any) {
        NotificationHelper.show(context as AppCompatActivity, NotificationUgc.LOGIN)
    }

    @JavascriptInterface
    fun useDarkStatusBarText(msg: Any) {
        runOnUiThread {
            DisplayUtils.transparentStatusBar(context as AppCompatActivity)
            DisplayUtils.setLightStatusBar(context as AppCompatActivity, msg.toString() == "true")
        }
    }

    /**
     * 是否为论坛详情的专区
     */
    @JavascriptInterface
    fun isForumZone(msg: Any): Boolean {
        return !mBbsId.isNullOrEmpty()
    }

    /**
     * 打开论坛搜索页
     * 如果用户是从 webView跳转到论坛搜索页，则sourceEntrance为空
     */
    @JavascriptInterface
    fun openForumSearch(msg: Any) {
        runOnUiThread {
            DirectUtils.directToForumOrUserSearch(
                context,
                mBbsId ?: "",
                entrance.ifBlank { "内部网页" },
                SOURCE_ENTRANCE,
                mForumName ?: ""
            )
        }
    }

    @JavascriptInterface
    fun exitWebView(msg: Any) {
        runOnUiThread { (context as Activity).finish() }
    }

    @JavascriptInterface
    fun updateRegulationTestStatus(msg: Any) {
        if (msg.toString().toLowerCase(Locale.getDefault()) == "pass") {
            SPUtils.setString(Constants.SP_REGULATION_TEST_PASS_STATUS, "pass")
        }
    }

    @JavascriptInterface
    fun getStatusBarHeight(msg: Any): String {
        val statusBarHeight = DisplayUtils.getStatusBarHeight(context.resources)
        return "$statusBarHeight"
    }

    @JavascriptInterface
    fun getGid(msg: Any): String {
        return HaloApp.getInstance().gid
    }

    @JavascriptInterface
    fun getOaid(msg: Any): String {
        return HaloApp.getInstance().oaid
    }

    @JavascriptInterface
    fun getPushId(): String {
        val pushProvider = TheRouter.get(IPushProvider::class.java)
        return pushProvider?.getRegistrationId(HaloApp.getInstance()) ?: "unknown"
    }

    @JavascriptInterface
    fun showIncompatibleVersionDialog(msg: Any) {
        DialogHelper.showUpgradeDialog(context)
    }

    @JavascriptInterface
    fun shareBase64Image(event: Any) {
        val imageShareEvent = event.toString().toObject() ?: ImageShareEvent()
        val context = CurrentActivityHolder.getCurrentActivity()
        ImageViewerActivity.base64Image = imageShareEvent.image.run {
            if (this.startsWith("data:image/png;base64")) this.split(",")[1] else this
        }
        MessageShareUtils.getInstance(context).shareFromWeb(context, imageShareEvent.type)
    }

    @JavascriptInterface
    fun inviteFriends(event: Any) {
        val inviteEvent = event.toString().toObject() ?: InviteFriendsEvent()
        val context = CurrentActivityHolder.getCurrentActivity()
        if ("poster" == inviteEvent.type) {
            ImageViewerActivity.base64Image = inviteEvent.poster.run {
                if (this.startsWith("data:image/png;base64")) this.split(",")[1] else this
            }
            MessageShareUtils.getInstance(context).shareInviteFriends(context, inviteEvent.way)
        } else {
            ShareUtils.getInstance(context).shareInviteFriends(context, inviteEvent.url, inviteEvent.way)
        }
    }

    @JavascriptInterface
    fun bindPhone(msg: Any) {
        val intent = SettingBridge.getBindPhoneNormalIntent(context, false)
        context.startActivity(intent)
    }

    @JavascriptInterface
    fun updateTitle(msg: Any) {
        if (context is WebActivity) {
            runOnUiThread { (context as WebActivity).setNavigationTitle(msg.toString()) }
        }
    }

    @JavascriptInterface
    fun logoutExitWebViewAndRedirectToLogin() {
        UserRepository.getInstance().logout()
        if (context is Activity) {
            AppExecutor.uiExecutor.executeWithDelay(Runnable {
                context.ifLogin("内部网页")
                (context as Activity).finish()
            }, 100)
        }
    }

    @JavascriptInterface
    fun openInNewWebview(url: Any) {
        runOnUiThread { DirectUtils.directToWebView(context, url.toString(), entrance.ifBlank { "内部网页" }) }
    }

    @JavascriptInterface
    fun postWearBadgeTask(msg: Any) {
        // do nothing
    }

    @JavascriptInterface
    fun startEnergyCenter(msg: Any) {
        // do nothing
    }

    @JavascriptInterface
    fun startEnergyHouse(msg: Any) {
        // do nothing
    }

    @JavascriptInterface
    fun showQaFeedbackDialog(msg: Any) {
        val mHelpAndFeedbackHelp = TheRouter.get(IHelpAndFeedbackProvider::class.java)
        mHelpAndFeedbackHelp?.showQaFeedbackDialogFragment(context as AppCompatActivity, msg.toString())
    }

    @JavascriptInterface
    fun getMetaObject(msg: Any): String {
        return LogUtils.getMetaObject().toString()
    }

    @JavascriptInterface
    fun getLaunchId(msg: Any): String {
        return Tracker.launchId
    }

    @JavascriptInterface
    fun getSessionId(msg: Any): String {
        return Tracker.sessionId
    }

    @JavascriptInterface
    fun postLogEvent(event: Any) {
        val logEvent = event.toString().toObject() ?: LogEvent()
        debugOnly {
            Utils.log("LogUtils->${logEvent.jsonString}")
        }
        LoghubUtils.log(logEvent.jsonString, logEvent.logStore, false)
    }

    @JavascriptInterface
    fun startAvatarBorderPage(msg: Any) {
        context.startActivity(AvatarBorderActivity.getIntent(context, msg.toString()))
    }

    @JavascriptInterface
    fun isNetworkConnected(): Boolean {
        return NetworkUtils.isNetworkConnected(context)
    }

    @JavascriptInterface
    fun isWifiConnected(): Boolean {
        return NetworkUtils.isWifiConnected(context)
    }

    @JavascriptInterface
    fun enableBackToActivity(msg: Any) {
        FloatingBackViewManager.enableBackView(FloatingBackViewManager.TYPE_ACTIVITY, msg.toString())
    }

    @JavascriptInterface
    fun saveBase64ImageToGallery(msg: Any) {
        val base64StringData = msg.toString()
        runOnUiThread {
            (context as? FragmentActivity)?.checkStoragePermissionBeforeAction {
                runOnIoThread {
                    val base64String = base64StringData.replace("data:image/png;base64", "")
                    tryWithDefaultCatch {
                        val imageFile =
                            File(HaloApp.getInstance().cacheDir.absolutePath + File.separator + System.currentTimeMillis() + ".png")
                        val decodedString = Base64.decode(base64String, Base64.DEFAULT)
                        val bos = BufferedOutputStream(FileOutputStream(imageFile))
                        bos.write(decodedString)
                        bos.flush()
                        bos.close()

                        ImageUtils.saveImageToFile(imageFile, "", true)
                    }
                }
            }
        }
    }

    @JavascriptInterface
    fun saveWechatQRCode(msg: Any) {
        val base64StringData = msg.toString()
        runOnUiThread {
            (context as? FragmentActivity)?.checkStoragePermissionBeforeAction {
                runOnIoThread {
                    val base64String = base64StringData.replace("data:image/png;base64", "")
                    tryWithDefaultCatch {
                        val imageFile =
                            File(HaloApp.getInstance().cacheDir.absolutePath + File.separator + System.currentTimeMillis() + ".png")
                        val decodedString = Base64.decode(base64String, Base64.DEFAULT)
                        val bos = BufferedOutputStream(FileOutputStream(imageFile))
                        bos.write(decodedString)
                        bos.flush()
                        bos.close()

                        ImageUtils.saveImageToFile(imageFile, "", true) {
                            // 这里是 ui 线程
                            // 保存微信二维码成功，1s 以后跳转微信
                            if (mFragment != null && mFragment.lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
                                handler.removeCallbacksAndMessages(null)
                                handler.postDelayed({
                                    val wechatPkgName = "com.tencent.mm"
                                    if (!PackageUtils.isInstalled(context, wechatPkgName)) {
                                        ToastUtils.showToast(R.string.wechat_app_not_install_tips.toResString())
                                        return@postDelayed
                                    }
                                    PackageLauncher.launchApp(context, packageName = wechatPkgName)
                                }, 1000)
                            }

                        }
                    }
                }
            }
        }
    }

    @JavascriptInterface
    fun loginWithCallback(msg: Any, handler: CompletionHandler<Any>) {
        mLoginHandler = handler
        login(msg)
    }

    fun onLogin() {
        mLoginHandler?.complete(true)
        mLoginHandler = null
    }

    @JavascriptInterface
    fun openInNewFullWebview(url: Any) {
        runOnUiThread { DirectUtils.directToFullScreenWebPage(context, url.toString(), true, entrance) }
    }

    @JavascriptInterface
    fun checkUpdateGhzs(msg: Any) {
        context.startActivity(SettingBridge.getAboutIntent(context, true))
    }

    @JavascriptInterface
    public fun clickGameActivityDownloadBtn(event: Any) {
        val gameActivityEvent = event.toString().toObject() ?: GameActivityEvent()
        GameActivityDownloadHelper.start(context, gameActivityEvent)
    }

    @JavascriptInterface
    fun isGameActivityTaskCompleted(event: Any, handler: CompletionHandler<Any>) {
        val gameActivityEvent = event.toString().toObject() ?: GameActivityEvent()
        GameActivityDownloadHelper.checkTaskComplete(context, gameActivityEvent, handler)
    }

    @JavascriptInterface
    fun postGameActivityExposureEvent(event: Any) {
        val gameActivityEvent = event.toString().toObject() ?: GameActivityEvent()
        GameActivityDownloadHelper.postExposureEvent(gameActivityEvent)
    }

    @JavascriptInterface
    fun getEntrance(msg: Any): String {
        return when {
            entrance.contains("论坛-活动") -> "社区-活动tab-活动banner"
            entrance.contains("启动弹窗") -> "首页_弹窗"
            entrance.contains("新首页-轮播图") -> "首页banner"
            entrance.contains("论坛banner") -> "社区banner"
            entrance.contains("启动广告") -> "app_开屏文案"
//            entrance.contains("资讯广场-轮播图") -> "资讯_活动banner"
            entrance.contains("通用链接合集") -> "资讯_活动banner"
            entrance.contains("视频流广告位") -> "视频流_广告位"
            entrance.contains("我的光环banner") -> "我的光环_banner"
            entrance.contains("论坛详情页置顶栏") -> "社区_论坛置顶"

            else -> entrance
        }
    }

    @JavascriptInterface
    fun getInstallStatus(event: Any): String {
        val localInstalledPackageList = PackageHelper.getInstalledPackageNameList(HaloApp.getInstance().application, 0)
        val packageNameList: ArrayList<String> = event.toString().toObject() ?: ArrayList()
        val installStatusMap: HashMap<String, Boolean> = hashMapOf()

        for (packageName in packageNameList) {
            installStatusMap[packageName] =
                localInstalledPackageList.contains(packageName) || VHelper.isInstalled(packageName)
        }

        return installStatusMap.toJson()
    }

    @JavascriptInterface
    fun installDownloadedGame(event: Any) {
        val url = event.toString()

        val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(url, null)
            ?: DownloadManager.getInstance().getDownloadEntitySnapshot(url, null)

        NewFlatLogUtils.logGameInstall(
            gameId = downloadEntity?.gameId ?: "",
            gameName = downloadEntity?.name ?: "",
            trigger = "主动安装"
        )

        SensorsBridge.trackInstallGameClick(
            gameId = downloadEntity?.gameId ?: "",
            gameName = downloadEntity?.name ?: "",
            action = "主动安装"
        )

        downloadEntity?.let {
            PackageInstaller.install(context, it, showUnzipToast = false, ignoreAsVGame = false)
        }
    }

    @JavascriptInterface
    fun registerDownloadCallback(msg: Any, handler: CompletionHandler<Any>) {
        val downloadUrlSet: HashSet<String> = msg.toString().toObject() ?: return

        mDownloadHandler = handler
        mDownloadUrlSet = downloadUrlSet

        if (mDownloadWatcher == null) {
            mDownloadWatcher = object : DataWatcher() {
                override fun onDataInit(downloadEntity: DownloadEntity) {
                    onDataChanged(downloadEntity)
                }

                override fun onDataChanged(downloadEntity: DownloadEntity?) {
                    val url = VHelper.getOriginalUrl(downloadEntity?.url)

                    if (downloadEntity != null && mDownloadUrlSet?.contains(url) == true) {
                        mDownloadHandler?.setProgressData(
                            SimpleDownloadEntity.fromDownloadEntity(downloadEntity).toJson()
                        )
                    }
                }
            }
            DownloadManager.getInstance().addObserver(mDownloadWatcher)
        }
    }

    @JavascriptInterface
    fun registerPackageChangesCallback(msg: Any, handler: CompletionHandler<Any>) {
        PackageObserver.registerPackageChangeChangeListener(object : PackageObserver.PackageChangeListener {
            override fun onChanged(data: EBPackage) {
                handler.setProgressData(data.toJson())
            }
        })
    }

    @JavascriptInterface
    fun startDownload(msg: Any) {
        val gameEntity: GameEntity? = msg.toString().toObject()

        if (gameEntity == null) {
            ToastUtils.toast("下载异常，请稍后重试")
            return
        }

        runOnUiThread {
            // 用一个假的 view 来当 downloadView
            val stubView = View(context)
            DownloadItemUtils.setOnClickListener(
                position = 0,
                context = context,
                downloadBtn = stubView,
                gameEntity = gameEntity,
                adapter = null,
                entrance = "(网页活动)",
                location = "",
                traceEvent = null,
                clickCallback = null,
                refreshCallback = null,
                allStateClickCallback = null
            )

            stubView.performClick()
        }
    }

    @JavascriptInterface
    fun resumeDownload(msg: Any) {
        val url = msg.toString()

        DownloadManager.getInstance().resumeDownload(url)
    }

    @JavascriptInterface
    fun pauseDownload(msg: Any) {
        val url = msg.toString()

        DownloadManager.getInstance().pause(url)
    }

    @JavascriptInterface
    fun shareText(event: Any) {
        val textShareEvent = event.toString().toObject() ?: TextShareEvent()
        if (textShareEvent.text.isNotEmpty() && textShareEvent.type.isNotEmpty()) {
            val activity = CurrentActivityHolder.getCurrentActivity()
            MessageShareUtils.getInstance(activity).shareTextFromWeb(activity, textShareEvent.text, textShareEvent.type)
        }
    }

    @JavascriptInterface
    fun logExposure(event: Any) {
        val simpleExposureEvent = event.toString().toObject() ?: SimpleExposureEvent()
        if (simpleExposureEvent.id.isNotEmpty()) {
            val sourceKey = if (mOriginUrl?.contains(Constants.URL_QUERY_FROM_FLOATING_WINDOW) == true) {
                "落地页"
            } else {
                "游戏活动"
            }

            val exposureSource = ExposureSource(sourceKey, "${simpleExposureEvent.title}+${simpleExposureEvent.id}")
            mExposureEvent = ExposureEvent.createEvent(
                gameEntity = null,
                source = arrayListOf(exposureSource),
            )
            ExposureManager.log(mExposureEvent!!)
            ExposureManager.commitSavedExposureEvents(true)
        }
    }

    @JavascriptInterface
    fun preOrderWithAli(json: Any) {
        val order = json.toString().toObject<OrderEntity>() ?: return
        trackMemberPaymentButtonClick(order, PAYMENT_TYPE_ALIPAY)
        listener?.onPreOrderWithAli(order)
    }

    @JavascriptInterface
    fun preOrderWithWechat(json: Any) {
        val order = json.toString().toObject<OrderEntity>() ?: return
        trackMemberPaymentButtonClick(order, PAYMENT_TYPE_WECHAT)
        listener?.onPreOrderWithWechat(order)
    }

    private fun trackMemberPaymentButtonClick(order: OrderEntity, paymentType: String) {
        val isFirstTime = SPUtils.getBoolean(SP_MEMBER_PAYMENT_BUTTON_CLICK, true)
        SPUtils.setBoolean(SP_MEMBER_PAYMENT_BUTTON_CLICK, false)
        SensorsBridge.trackMemberPaymentButtonClick(
            isFirstTime,
            paymentType,
            order.setMenuName,
            order.paymentAmount
        )
    }

    @JavascriptInterface
    fun startGameAccelerate(acctJson: Any) {
        if (acctJson is String) {
            val acctRecord = GsonUtils.fromJson(acctJson, AcctRecordEntity::class.java)
            val accInfo = acctRecord.accInfo
            listener?.onStartGameAccelerate(accInfo)
        }
    }

    @JavascriptInterface
    fun getCurAcctGameId(): String {
        return AcceleratorDataHolder.instance.getAcceleratingGameId()
    }

    @JavascriptInterface
    fun stopGameAccelerate() {
        listener?.onStopGameAccelerate()
    }

    @JavascriptInterface
    fun getDurationRemainingTime(msg: Any, handler: CompletionHandler<Any>) {
        TheRouter.get(IAcceleratorProvider::class.java)?.loadQyUserPermissionData {
            val durationExpiredMinute = AcceleratorDataHolder.instance.vipEntity?.durationExpiredTime ?: 0L
            handler.complete(durationExpiredMinute)
        }
    }

    @JavascriptInterface
    fun refreshToken(token: Any, handler: CompletionHandler<Any>) {
        val accessToken = token.toString()
        UserManager.getInstance().refreshToken(accessToken, object : UserManager.refreshCallBack {
            override fun onLogin() {
                handler.complete(true)
            }

            override fun onLoginFailure(errorMessage: String?) {
                handler.complete(false)
            }

        })
    }

    @JavascriptInterface
    fun trackSensorsAnalytics(json: Any) {
        val hashMap = json.toString().toObject<HashMap<String, Any>>() ?: return
        val eventName = hashMap.remove(EVENT_NAME) ?: return
        when (eventName) {
            EVENT_MEMBER_RECHARGE_BUTTON_CLICK -> {
                hashMap[KEY_IS_FIRST_TIME] = SPUtils.getBoolean(SP_MEMBER_RECHARGE_BUTTON_CLICK, true)
                SPUtils.setBoolean(SP_MEMBER_RECHARGE_BUTTON_CLICK, false)
            }
        }
        SensorsBridge.trackSensorsAnalyticsFromWeb(eventName.toString(), hashMap)
    }

    /**
     * 获取 ExposureEvent，可能为空
     */
    fun getExposureEvent(): ExposureEvent? {
        return mExposureEvent
    }

    private fun autoUnregisterDownloadObserverIfNeeded(fragment: Fragment?) {
        fragment?.parentFragmentManager?.registerFragmentLifecycleCallbacks(
            object : FragmentManager.FragmentLifecycleCallbacks() {
                override fun onFragmentViewDestroyed(fm: FragmentManager, f: Fragment) {
                    super.onFragmentViewDestroyed(fm, f)
                    if (f === fragment) {
                        fragment.parentFragmentManager.unregisterFragmentLifecycleCallbacks(this)

                        if (mDownloadWatcher != null) {
                            DownloadManager.getInstance().removeObserver(mDownloadWatcher)
                        }

                        EventBus.getDefault().unregister(this@DefaultJsApi)

                        handler.removeCallbacksAndMessages(null)
                    }
                }

                override fun onFragmentResumed(fm: FragmentManager, f: Fragment) {
                    super.onFragmentResumed(fm, f)

                    if (f === fragment && mDownloadWatcher != null) {
                        DownloadManager.getInstance().addObserver(mDownloadWatcher)
                    }
                }

                override fun onFragmentPaused(fm: FragmentManager, f: Fragment) {
                    super.onFragmentPaused(fm, f)

                    if (f === fragment && mDownloadWatcher != null) {
                        DownloadManager.getInstance().removeObserver(mDownloadWatcher)
                    }
                }
            }, false
        )
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(status: EBDownloadStatus) {
        // 将下载任务删除事件回调给网页
        if (mDownloadHandler != null && "delete" == status.status) {
            mDownloadHandler?.setProgressData(SimpleDownloadEntity(status.url, 0F, "UNKNOWN").toJson())
        }
    }

    @Keep
    internal class ImageEvent(var imageList: ArrayList<String> = arrayListOf(), var position: Int = 0)

    @Keep
    internal class ImageShareEvent(var image: String = "", var type: String = "")

    @Keep
    internal class TextShareEvent(var text: String = "", var type: String = "")

    @Keep
    internal class SimpleExposureEvent(var title: String = "", var id: String = "")

    @Keep
    internal class InviteFriendsEvent(
        var type: String = "",
        var way: String = "",
        var url: String = "",
        var poster: String = ""
    )

    @Keep
    internal class LogEvent(var jsonString: String = "", var logStore: String = "")

    @Keep
    class GameActivityEvent(
        var gameId: String = "",
        var activityTitle: String = "",
        var activityId: String = "",
        var platform: String = ""
    )

    @Keep
    class SimpleDownloadEntity(
        var url: String = "",
        var progress: Float = 0F,
        var status: String = "" // DOWNLOADING, PAUSED, DOWNLOADED, ERROR, UNKNOWN
    ) {
        companion object {

            fun fromDownloadEntity(downloadEntity: DownloadEntity): SimpleDownloadEntity {
                val status: String = when (downloadEntity.status) {
                    add,
                    download,
                    downloading -> "DOWNLOADING"

                    done -> "DOWNLOADED"

                    pause,
                    resume,
                    subscribe,
                    waiting -> "PAUSED"

                    cancel,
                    delete -> "UNKNOWN"

                    else -> "ERROR"
                }

                return SimpleDownloadEntity(
                    url = VHelper.getOriginalUrl(downloadEntity.url),
                    progress = downloadEntity.percent.toFloat(),
                    status = status
                )
            }
        }
    }

    interface OnWebClickListener {

        fun onPreOrderWithAli(order: OrderEntity)

        fun onPreOrderWithWechat(order: OrderEntity)

        fun onStartGameAccelerate(accInfo: AcctRecordEntity.AccInfo)

        fun onStopGameAccelerate()
    }
}
