package com.zxdemo.admob

import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.ViewGroup
import android.view.ViewTreeObserver
import com.applovin.mediation.MaxAd
import com.applovin.mediation.MaxAdListener
import com.applovin.mediation.MaxAdViewAdListener
import com.applovin.mediation.MaxError
import com.applovin.mediation.ads.MaxAdView
import com.applovin.mediation.ads.MaxAppOpenAd
import com.applovin.mediation.ads.MaxInterstitialAd
import com.applovin.mediation.nativeAds.MaxNativeAdListener
import com.applovin.mediation.nativeAds.MaxNativeAdLoader
import com.applovin.mediation.nativeAds.MaxNativeAdView
import com.applovin.sdk.AppLovinMediationProvider
import com.applovin.sdk.AppLovinSdk
import com.applovin.sdk.AppLovinSdkInitializationConfiguration
import com.google.ads.mediation.admob.AdMobAdapter
import com.google.android.gms.ads.AdError
import com.google.android.gms.ads.AdListener
import com.google.android.gms.ads.AdLoader
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.AdSize
import com.google.android.gms.ads.AdView
import com.google.android.gms.ads.FullScreenContentCallback
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.MobileAds
import com.google.android.gms.ads.appopen.AppOpenAd
import com.google.android.gms.ads.interstitial.InterstitialAd
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.nativead.NativeAdOptions
import com.zxdemo.admob.AdDialog.showAdPreparingDialog
import com.zxdemo.utils.SpUtils
import java.util.Calendar
import java.util.UUID

object AdmobHelper {


    private const val APP_OPEN_AD_UNIT_ID = "ca-app-pub-3940256099942544/9257395921"
    private const val INTERSTITIAL_AD_UNIT_ID = "ca-app-pub-3940256099942544/1033173712"
    private const val BANNER_AD_UNIT_ID = "ca-app-pub-3940256099942544/9214589741"
    private const val NATIVE_AD_UNIT_ID = "ca-app-pub-3940256099942544/2247696110"

    private const val MAX_SDK_KEY =
        "GGPreND6SRmCt1zJgn5faiLGD8c2PVGPLgPpSg7cHanVTud1DhtuI9MmteTqlEviaJ57WnxW68kQDaATJ5z3cW"
    private const val MAX_OPEN_AD_UNIT_ID = "d1d943cdd3127c90"
    private const val MAX_INTERSTITIAL_AD_UNIT_ID = "b31e7f6d11ee659e"
    private const val MAX_BANNER_AD_UNIT_ID = "ca-app-pub-3940256099942544/9214589741"
    private const val MAX_NATIVE_AD_UNIT_ID = "96e8fe78b0efc5d1"

    private const val APP_OPEN_AD_UNIT = "openAd"
    private const val INTERSTITIAL_AD_UNIT = "interAd"
    private const val NATIVE_AD_UNIT = "nativeAd"
    private const val NO_AD = "no_ad"

    private const val KEY_AD_INTERVAL = "adInterval"
    private const val KEY_AD_REQUEST = "adRequest"
    private const val KEY_AD_CLICK = "adClick"
    private const val KEY_AD_SHOW = "adShow"

    private const val KEY_IS_SHOW_AD_BANNER = "isShowAdBanner"
    private const val KEY_IS_SHOW_AD_NATIVE = "isShowAdNative"
    private const val KEY_IS_SHOW_AD_INTER = "isShowAdInter"
    private const val KEY_IS_SHOW_AD_BACK_INTER = "isShowAdBackInter"

    private const val DEFAULT_AD_INTERVAL = 30 * 1000
    private const val DEFAULT_AD_REQUEST = 100
    private const val DEFAULT_AD_CLICK = 10
    private const val DEFAULT_AD_SHOW = 45
    var blacklist = 1

    private const val KEY_DISPLAY_NUMBER = "key_display_number"
    private const val KEY_REQUEST_NUMBER = "key_request_number"
    private const val KEY_CLICK_NUMBER = "key_click_number"
    private const val KEY_LAST_DISPLAY_TIME = "key_last_display_time"

    private const val EVENT_BLACKLIST = "blacklist"
    private const val EVENT_SHOW_DISPLAYS = "showDisPlays"
    private const val EVENT_SHOW_REQUESTS = "showRequests"
    private const val EVENT_SHOW_CLICKS = "showClicks"
    private const val EVENT_SHOW_INTERVAL_TIME = "showIntervalTime"

    //
    private const val TAG = "AdmobManager"

    private var appOpenAd: AppOpenAd? = null
    private var appOpenMaxAd: MaxAppOpenAd? = null
    private var appOpenAdLoadTime: Long = 0

    private var interstitialAd: InterstitialAd? = null
    private var interstitialMaxAd: MaxInterstitialAd? = null
    private var interstitialAdLoadTime: Long = 0

    var isLoadingAppOpenAd = false
    var isLoadingInterstitialAd = false

    inline var useAdmob
        get() = SpUtils.getInstance().getBoolean("sAd", true)
        set(value) = SpUtils.getInstance().putBoolean("sAd", value)


    fun init(
        context: Context,
        loaded: (Int) -> Unit,
        failed: () -> Unit,
    ) {
        if (useAdmob) {
            MobileAds.initialize(context) {
            }
//            if (isAppOpenAdAvailable()) {
//                loaded.invoke(0)
//                return
//            }
//            if (isInterstitialAdAvailable()) {
//                loaded.invoke(1)
//                loadAppOpenAd(context)
//                return
//            }
//            loadAppOpenAd(context, { loaded.invoke(0) }, { failed.invoke() })
//            loadInterstitialAd(context)
        } else {
            val initConfig = AppLovinSdkInitializationConfiguration.builder(
                MAX_SDK_KEY, context
            ).setMediationProvider(AppLovinMediationProvider.MAX).build()
            AppLovinSdk.getInstance(context).initialize(initConfig) {
                if (isAppOpenAdAvailable()) {
                    loaded.invoke(0)
                    return@initialize
                }
                if (isInterstitialAdAvailable()) {
                    loaded.invoke(1)
                    loadAppOpenAd(context)
                    return@initialize
                }
                loadAppOpenAd(context, { loaded.invoke(0) }, { failed.invoke() })
                loadInterstitialAd(context)
            }
        }
    }

    fun loadAppOpenAd(
        context: Context,
        loaded: (() -> Unit?)? = null,
        failed: (() -> Unit?)? = null,
    ) {
//        if (!checkAvailable(APP_OPEN_AD_UNIT, true)) {
//            failed?.invoke()
//            return
//        }
//        if (isLoadingAppOpenAd) {
//            failed?.invoke()
//            return
//        }
        isLoadingAppOpenAd = true
        Log.d(TAG, "app open Ad load.")
        val reqId = UUID.randomUUID().toString()
        ReportAdUtils.pullStartAd(reqId, (context as Activity).javaClass.simpleName)
        if (useAdmob) {
            val adRequest = AdRequest.Builder().build()
            AppOpenAd.load(
                context,
                APP_OPEN_AD_UNIT_ID,
                adRequest,
                object : AppOpenAd.AppOpenAdLoadCallback() {
                    override fun onAdFailedToLoad(loadAdError: LoadAdError) {
                        Log.e(TAG, "app open failed to load: ${loadAdError.message}")
                        failed?.invoke()
                        ReportAdUtils.pullAd(
                            loadAdError.responseInfo,
                            APP_OPEN_AD_UNIT,
                            loadAdError.message,
                            reqId
                        )
                        isLoadingAppOpenAd = false
                    }

                    override fun onAdLoaded(ad: AppOpenAd) {
                        Log.e(TAG, "app open Ad was loaded.")
                        appOpenAd = ad
                        appOpenAdLoadTime = System.currentTimeMillis()
                        loaded?.invoke()
                        calculate(KEY_REQUEST_NUMBER)
                        ReportAdUtils.pullAd(ad.responseInfo, APP_OPEN_AD_UNIT, reqId = reqId)
                        ad.onPaidEventListener = ReportAdUtils.EventOnPaidEventListener(ad)
                        isLoadingAppOpenAd = false
                    }
                })
        } else {
            appOpenMaxAd = MaxAppOpenAd(MAX_OPEN_AD_UNIT_ID, context)
            appOpenMaxAd?.setListener(object : MaxAdListener {
                override fun onAdLoaded(ad: MaxAd) {
                    Log.d(TAG, "app open Ad Max was loaded.")
                    appOpenAdLoadTime = System.currentTimeMillis()
                    loaded?.invoke()
                    calculate(KEY_REQUEST_NUMBER)
                    //com.zxdemo.admob.ReportAdUtils.pullAd(ad.responseInfo, APP_OPEN_AD_UNIT, reqId = reqId)
                    // appOpenMaxAd.onPaidEventListener = com.zxdemo.admob.ReportAdUtils.EventOnPaidEventListener(ad)
                    isLoadingAppOpenAd = false
                }

                override fun onAdDisplayed(p0: MaxAd) {
                }

                override fun onAdHidden(p0: MaxAd) {
                }

                override fun onAdClicked(p0: MaxAd) {
                }

                override fun onAdLoadFailed(p0: String, p1: MaxError) {
                    Log.d(TAG, "app open Max failed to load: $p0 ${p1.message}")
                    failed?.invoke()
//                com.zxdemo.admob.ReportAdUtils.pullAd(
//                    loadAdError.responseInfo,
//                    APP_OPEN_AD_UNIT,
//                    loadAdError.message,
//                    reqId
//                )
                    isLoadingAppOpenAd = false
                }

                override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
                }

            })
            appOpenMaxAd?.loadAd()
        }
    }

    fun loadInterstitialAd(
        context: Context,
        loaded: (() -> Unit?)? = null,
        failed: (() -> Unit?)? = null,
    ) {
//        if (!checkAvailable(INTERSTITIAL_AD_UNIT, true)) {
//            failed?.invoke()
//            return
//        }
//        if (isLoadingInterstitialAd) {
//            failed?.invoke()
//            return
//        }
        isLoadingInterstitialAd = true
        Log.d(TAG, "interstitial Ad load.")
        val reqId = UUID.randomUUID().toString()
        ReportAdUtils.pullStartAd(reqId, (context as Activity).javaClass.simpleName)
        if (useAdmob) {
            val adRequest = AdRequest.Builder().build()
            InterstitialAd.load(
                context,
                INTERSTITIAL_AD_UNIT_ID,
                adRequest,
                object : InterstitialAdLoadCallback() {
                    override fun onAdFailedToLoad(loadAdError: LoadAdError) {
                        Log.d(TAG, "interstitial Ad failed to load: ${loadAdError.message}")
                        interstitialAd = null
                        failed?.invoke()
                        ReportAdUtils.pullAd(
                            loadAdError.responseInfo,
                            INTERSTITIAL_AD_UNIT,
                            loadAdError.message,
                            reqId
                        )
                        isLoadingInterstitialAd = false
                    }

                    override fun onAdLoaded(ad: InterstitialAd) {
                        Log.d(TAG, "interstitial Ad was loaded.")
                        interstitialAd = ad
                        interstitialAdLoadTime = System.currentTimeMillis()
                        loaded?.invoke()
                        calculate(KEY_REQUEST_NUMBER)
                        ReportAdUtils.pullAd(ad.responseInfo, INTERSTITIAL_AD_UNIT, reqId = reqId)
                        ad.onPaidEventListener = ReportAdUtils.EventOnPaidEventListener(ad)
                        isLoadingInterstitialAd = false
                    }
                })
        } else {
            interstitialMaxAd = MaxInterstitialAd(MAX_INTERSTITIAL_AD_UNIT_ID, context)
            interstitialMaxAd?.setListener(object : MaxAdListener {
                override fun onAdLoaded(p0: MaxAd) {
                    Log.d(TAG, "interstitial Ad Max was loaded.")
                    interstitialAdLoadTime = System.currentTimeMillis()
                    loaded?.invoke()
                    calculate(KEY_REQUEST_NUMBER)
                    // com.zxdemo.admob.ReportAdUtils.pullAd(ad.responseInfo, INTERSTITIAL_AD_UNIT, reqId = reqId)
                    // ad.onPaidEventListener = com.zxdemo.admob.ReportAdUtils.EventOnPaidEventListener(ad)
                    isLoadingInterstitialAd = false
                }

                override fun onAdDisplayed(p0: MaxAd) {
                }

                override fun onAdHidden(p0: MaxAd) {
                }

                override fun onAdClicked(p0: MaxAd) {
                }

                override fun onAdLoadFailed(p0: String, p1: MaxError) {
                    Log.d(TAG, "interstitial Ad failed to load: ${p1.message}")
                    interstitialMaxAd = null
                    failed?.invoke()
//                    com.zxdemo.admob.ReportAdUtils.pullAd(
//                        loadAdError.responseInfo,
//                        INTERSTITIAL_AD_UNIT,
//                        loadAdError.message,
//                        reqId
//                    )
                    isLoadingInterstitialAd = false
                }

                override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
                }

            })
            interstitialMaxAd?.loadAd()
        }
    }

    fun showAppOpenAd(
        activity: Activity,
        dismissed: (() -> Unit?)? = null,
        completed: (() -> Unit?)? = null,
        failed: (() -> Unit?)? = null
    ) {
        if (activity.isFinishing || activity.isDestroyed) return

        ReportAdUtils.showPrepareAd(APP_OPEN_AD_UNIT)
//        if (!checkAvailable(APP_OPEN_AD_UNIT)) {
//            failed?.invoke()
//            return
//        }

        if (!isAppOpenAdAvailable()) {
            Log.d(TAG, "The app open ad is not ready yet.")
            ReportAdUtils.showErrorAd(NO_AD, APP_OPEN_AD_UNIT)
            loadAppOpenAd(activity, {
                showAppOpenAd(activity, dismissed, completed, failed)
            }, {
                failed?.invoke()
            })
            return
        }
        if (useAdmob) {
            appOpenAd?.fullScreenContentCallback = object : FullScreenContentCallback() {
                override fun onAdClicked() {
                    Log.d(TAG, "app open Ad was clicked")
                    calculate(KEY_CLICK_NUMBER)
                    ReportAdUtils.clickAd(appOpenAd?.responseInfo, APP_OPEN_AD_UNIT)
                }

                override fun onAdDismissedFullScreenContent() {
                    Log.d(TAG, "app open Ad dismissed fullscreen content.")
                    dismissed?.invoke()
                }

                override fun onAdFailedToShowFullScreenContent(adError: AdError) {
                    Log.d(TAG, "app open failed to show: ${adError.message}")
                    appOpenAd = null
                    loadAppOpenAd(activity)
                    failed?.invoke()
                    ReportAdUtils.showErrorAd(adError.message, APP_OPEN_AD_UNIT)
                }

                override fun onAdShowedFullScreenContent() {
                    Log.d(TAG, "app open Ad showed fullscreen content.")
                    completed?.invoke()
                    SpUtils.getInstance().putLong(KEY_LAST_DISPLAY_TIME, System.currentTimeMillis())
                    calculate(KEY_DISPLAY_NUMBER)
                    ReportAdUtils.showAd(appOpenAd?.responseInfo, APP_OPEN_AD_UNIT, activity)
                    appOpenAd = null
                    loadAppOpenAd(activity)
                }
            }
            appOpenAd?.show(activity)
        } else {
            appOpenMaxAd?.setListener(object : MaxAdListener {
                override fun onAdLoaded(ad: MaxAd) {

                }

                override fun onAdDisplayed(p0: MaxAd) {
                    Log.d(TAG, "app open Ad Max showed fullscreen content.")
                    completed?.invoke()
                    SpUtils.getInstance().putLong(KEY_LAST_DISPLAY_TIME, System.currentTimeMillis())
                    calculate(KEY_DISPLAY_NUMBER)
                    ReportAdUtils.showAd(appOpenAd?.responseInfo, APP_OPEN_AD_UNIT, activity)
                    appOpenMaxAd = null
                    loadAppOpenAd(activity)
                }

                override fun onAdHidden(p0: MaxAd) {
                    Log.d(TAG, "app open Ad Max dismissed fullscreen content.")
                    dismissed?.invoke()
                }

                override fun onAdClicked(p0: MaxAd) {
                    Log.d(TAG, "app open Ad Max was clicked")
                    calculate(KEY_CLICK_NUMBER)
                    ReportAdUtils.clickAd(appOpenAd?.responseInfo, APP_OPEN_AD_UNIT)
                }

                override fun onAdLoadFailed(p0: String, p1: MaxError) {
                }

                override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
                    Log.d(TAG, "app open Max failed to show: ${p1.message}")
                    appOpenMaxAd = null
                    loadAppOpenAd(activity)
                    failed?.invoke()
                    ReportAdUtils.showErrorAd(p1.message, APP_OPEN_AD_UNIT)
                }

            })
            appOpenMaxAd?.showAd()
        }
    }

    private var adDialog: Dialog? = null
    fun showInterstitialAd(
        activity: Activity,
        dismissed: (() -> Unit?)? = null,
        completed: (() -> Unit?)? = null,
        failed: (() -> Unit?)? = null
    ) {
        if (activity.isFinishing || activity.isDestroyed) return

        ReportAdUtils.showPrepareAd(INTERSTITIAL_AD_UNIT)
//        if (!checkAvailable(INTERSTITIAL_AD_UNIT)) {
//            failed?.invoke()
//            return
//        }
        if (adDialog == null) {
            adDialog = activity.showAdPreparingDialog()
        }

        if (!isInterstitialAdAvailable()) {
            loadInterstitialAd(activity, {
                showInterstitialAd(activity, dismissed, completed, failed)
            }, {
                adDialog?.dismiss()
                adDialog = null
                failed?.invoke()
            })
            return
        }

        if (useAdmob) {
            interstitialAd?.fullScreenContentCallback = object : FullScreenContentCallback() {
                override fun onAdClicked() {
                    Log.d(TAG, "interstitial Ad was clicked")
                    calculate(KEY_CLICK_NUMBER)
                    ReportAdUtils.clickAd(interstitialAd?.responseInfo, INTERSTITIAL_AD_UNIT)
                }

                override fun onAdDismissedFullScreenContent() {
                    Log.d(TAG, "interstitial Ad was dismissed.")
                    dismissed?.invoke()
                }

                override fun onAdFailedToShowFullScreenContent(adError: AdError) {
                    Log.d(TAG, "interstitial Ad failed to show: ${adError.message}")
                    adDialog?.dismiss()
                    adDialog = null
                    interstitialAd = null
                    loadInterstitialAd(activity)
                    failed?.invoke()
                    ReportAdUtils.showErrorAd(adError.message, INTERSTITIAL_AD_UNIT)
                }

                override fun onAdShowedFullScreenContent() {
                    adDialog?.dismiss()
                    adDialog = null
                    Log.d(TAG, "interstitial Ad showed fullscreen content.")
                    completed?.invoke()
                    calculate(KEY_DISPLAY_NUMBER)
                    SpUtils.getInstance().putLong(KEY_LAST_DISPLAY_TIME, System.currentTimeMillis())
                    ReportAdUtils.showAd(
                        interstitialAd?.responseInfo,
                        INTERSTITIAL_AD_UNIT,
                        activity
                    )
                    interstitialAd = null
                    loadInterstitialAd(activity)
                }
            }
            interstitialAd?.show(activity)
        } else {
            interstitialMaxAd?.setListener(object : MaxAdListener {
                override fun onAdLoaded(p0: MaxAd) {

                }

                override fun onAdDisplayed(p0: MaxAd) {
                    Log.d(TAG, "interstitial Ad Max showed fullscreen content.")
                    completed?.invoke()
                    calculate(KEY_DISPLAY_NUMBER)
                    SpUtils.getInstance().putLong(KEY_LAST_DISPLAY_TIME, System.currentTimeMillis())
//                    com.zxdemo.admob.ReportAdUtils.showAd(
//                        interstitialAd?.responseInfo,
//                        INTERSTITIAL_AD_UNIT,
//                        activity
//                    )
                    interstitialMaxAd = null
                    loadInterstitialAd(activity)
                }

                override fun onAdHidden(p0: MaxAd) {
                    Log.d(TAG, "interstitial Ad Max was dismissed.")
                    dismissed?.invoke()
                }

                override fun onAdClicked(p0: MaxAd) {
                    Log.d(TAG, "interstitial Ad Max was clicked")
                    calculate(KEY_CLICK_NUMBER)
                    //com.zxdemo.admob.ReportAdUtils.clickAd(interstitialAd?.responseInfo, INTERSTITIAL_AD_UNIT)
                }

                override fun onAdLoadFailed(p0: String, p1: MaxError) {

                }

                override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
                    Log.d(TAG, "interstitial Ad MaX failed to show: ${p1.message}")
                    interstitialMaxAd = null
                    loadInterstitialAd(activity)
                    failed?.invoke()
                    ReportAdUtils.showErrorAd(p1.message, INTERSTITIAL_AD_UNIT)
                }

            })
            interstitialMaxAd?.showAd(activity)
        }
    }

    fun showNativeAd(
        activity: Activity,
        completed: ((nativeAd: NativeAd) -> Unit)? = null,
        maxCompleted: ((nativeAdLoader: MaxNativeAdLoader, nativeMaxAd: MaxAd) -> Unit)? = null,
        failed: (() -> Unit?)? = null
    ) {
//        if (!isShowAdNative() || isBlacklist()) {
//            failed?.invoke()
//            return
//        }
        Log.e(TAG, "showNativeAd")
        if (useAdmob) {
            var nativeAd: NativeAd? = null
            val adLoader = AdLoader.Builder(activity, NATIVE_AD_UNIT_ID)
                .forNativeAd { ad: NativeAd ->
                    Log.e(TAG, "forNativeAd")
                    ReportAdUtils.showAd(ad.responseInfo, NATIVE_AD_UNIT, activity)
                    ad.setOnPaidEventListener(ReportAdUtils.EventOnPaidEventListener(ad))
                    nativeAd = ad
                    completed?.invoke(ad)
                }
                .withAdListener(object : AdListener() {
                    override fun onAdClicked() {
                        Log.e(TAG, "native Ad clicked.")
                        ReportAdUtils.clickAd(nativeAd?.responseInfo, NATIVE_AD_UNIT)
                    }

                    override fun onAdFailedToLoad(loadAdError: LoadAdError) {
                        Log.e(TAG, "native Ad failed to load. ${loadAdError.message}")
                        failed?.invoke()
                    }

                    override fun onAdLoaded() {
                        Log.e(TAG, "native Ad loaded.")
                    }
                })
                .withNativeAdOptions(NativeAdOptions.Builder().build())
                .build()
            adLoader.loadAd(AdRequest.Builder().build())
        } else {
            val nativeAdLoader = MaxNativeAdLoader(MAX_NATIVE_AD_UNIT_ID, activity)
            nativeAdLoader.setNativeAdListener(object : MaxNativeAdListener() {

                override fun onNativeAdLoaded(nativeAdView: MaxNativeAdView?, ad: MaxAd) {
                    Log.d(TAG, "native Ad Max loaded.")
                    maxCompleted?.invoke(nativeAdLoader, ad)
                    // com.zxdemo.admob.ReportAdUtils.showAd(ad.responseInfo, NATIVE_AD_UNIT, activity)
                    // ad.setOnPaidEventListener(com.zxdemo.admob.ReportAdUtils.EventOnPaidEventListener(ad))
                    // nativeAd = ad
                }

                override fun onNativeAdLoadFailed(adUnitId: String, error: MaxError) {
                    Log.d(TAG, "native Ad Max failed to load. ${error.message}")
                    failed?.invoke()
                }

                override fun onNativeAdClicked(ad: MaxAd) {
                    Log.d(TAG, "native Ad Max clicked.")
                    // com.zxdemo.admob.ReportAdUtils.clickAd(nativeAd?.responseInfo, NATIVE_AD_UNIT)
                }
            })
            nativeAdLoader.loadAd()
        }
    }

    fun showBannerAd(
        context: Context,
        adViewContainer: ViewGroup,
        collapsible: String? = "bottom",
        completed: (() -> Unit?)? = null,
        failed: (() -> Unit?)? = null
    ) {
//        if (useAdmob) {
        // Use the fragment width as the ad width when layout is finished.
        adViewContainer.viewTreeObserver.addOnGlobalLayoutListener(object :
            ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {

                val screenPixelDensity = context.resources.displayMetrics.density
                val adWidth = (adViewContainer.width / screenPixelDensity).toInt()
                val adSize =
                    AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(context, adWidth)
                showBannerAd(context, adViewContainer, adSize, collapsible, completed, failed)

                adViewContainer.viewTreeObserver.removeOnGlobalLayoutListener(this)
            }
        })
//        } else {
//            showBannerAd(context, adViewContainer, completed, failed)
//        }
    }

    fun showBannerAd(
        context: Context,
        adViewContainer: ViewGroup,
        adSize: AdSize,
        collapsible: String? = "bottom",
        completed: (() -> Unit?)? = null,
        failed: (() -> Unit?)? = null
    ) {
//        if (!isShowAdBanner() || isBlacklist()) {
//            failed?.invoke()
//            return
//        }

        Log.d(TAG, "banner Ad load.")
        val adView = AdView(context)
        adView.adUnitId = BANNER_AD_UNIT_ID
        adView.setAdSize(adSize)
        val extras = Bundle()
        extras.putString("collapsible", collapsible)
        val adRequest = AdRequest.Builder()
            .addNetworkExtrasBundle(AdMobAdapter::class.java, extras)
            .build()
        adView.loadAd(adRequest)
        adView.adListener = object : AdListener() {
            override fun onAdClicked() {
                Log.d(TAG, "banner Ad clicked.")
            }

            override fun onAdFailedToLoad(loadAdError: LoadAdError) {
                Log.d(TAG, "banner Ad failed to load: ${loadAdError.message}")
                failed?.invoke()
            }

            override fun onAdLoaded() {
                Log.d(TAG, "banner Ad loaded.")
                completed?.invoke()
            }
        }
        adViewContainer.removeAllViews()
        adViewContainer.addView(adView)

    }

    private fun showBannerAd(
        context: Context,
        adViewContainer: ViewGroup,
        completed: (() -> Unit?)? = null,
        failed: (() -> Unit?)? = null
    ) {
        if (!isShowAdBanner() || isBlacklist()) {
            failed?.invoke()
            return
        }

        Log.d(TAG, "banner Ad Max load.")

        val adView = MaxAdView(MAX_BANNER_AD_UNIT_ID, context)
        adView.setListener(object : MaxAdViewAdListener {
            override fun onAdLoaded(p0: MaxAd) {
                Log.d(TAG, "banner Ad Max loaded.")
                completed?.invoke()
            }

            override fun onAdDisplayed(p0: MaxAd) {
            }

            override fun onAdHidden(p0: MaxAd) {

            }

            override fun onAdClicked(p0: MaxAd) {
                Log.d(TAG, "banner Ad Max clicked.")
            }

            override fun onAdLoadFailed(p0: String, p1: MaxError) {
                Log.d(TAG, "banner Ad Max failed to load: ${p1.message}")
                failed?.invoke()
            }

            override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {

            }

            override fun onAdExpanded(p0: MaxAd) {

            }

            override fun onAdCollapsed(p0: MaxAd) {

            }

        })
        adViewContainer.removeAllViews()
        adViewContainer.addView(adView)
        adView.loadAd()

    }

    fun isShowAdBanner(): Boolean {
        val isShowAdBanner = SpUtils.getInstance().getInt(KEY_IS_SHOW_AD_BANNER)
        return isShowAdBanner == 1
    }

    fun isShowAdNative(): Boolean {
        val isShowAdNative = SpUtils.getInstance().getInt(KEY_IS_SHOW_AD_NATIVE)
        return isShowAdNative == 1
    }

    fun isShowAdInter(): Boolean {
        val isShowAdInter = SpUtils.getInstance().getInt(KEY_IS_SHOW_AD_INTER)
        return isShowAdInter == 1
    }

    fun isShowAdBackInter(): Boolean {
        val isShowAdBackInter = SpUtils.getInstance().getInt(KEY_IS_SHOW_AD_BACK_INTER)
        return isShowAdBackInter == 1
    }

    fun isAppOpenAdAvailable(): Boolean {
        return (if (useAdmob) appOpenAd != null else appOpenMaxAd?.isReady == true) && wasLoadTimeLessThanNHoursAgo(
            4,
            appOpenAdLoadTime
        )
    }

    fun isInterstitialAdAvailable(): Boolean {
        return (if (useAdmob) interstitialAd != null else interstitialMaxAd?.isReady == true) && wasLoadTimeLessThanNHoursAgo(
            1,
            interstitialAdLoadTime
        )
    }

    private fun wasLoadTimeLessThanNHoursAgo(numHours: Long, time: Long): Boolean {
        val dateDifference: Long = System.currentTimeMillis() - time
        val numMilliSecondsPerHour: Long = 3600000
        return dateDifference < numMilliSecondsPerHour * numHours
    }

    private fun isBlacklist(): Boolean {
        return blacklist != 1
    }

    private fun checkAvailable(adUnit: String, notCheckIntervalTime: Boolean = false): Boolean {
        if (isBlacklist()) {
            ReportAdUtils.showErrorAd(EVENT_BLACKLIST, adUnit)
            return false
        }
        val currentTime = System.currentTimeMillis()
        var lastDisplayTime = SpUtils.getInstance().getLong(KEY_LAST_DISPLAY_TIME)
        if (lastDisplayTime.toInt() != 0 && !areTimestampsSameDay(currentTime, lastDisplayTime)) {
            SpUtils.getInstance().putInt(KEY_DISPLAY_NUMBER, 0)
            SpUtils.getInstance().putInt(KEY_REQUEST_NUMBER, 0)
            SpUtils.getInstance().putInt(KEY_CLICK_NUMBER, 0)
            SpUtils.getInstance().putLong(KEY_LAST_DISPLAY_TIME, currentTime)
            lastDisplayTime = 0
        }
        val displayNumber = SpUtils.getInstance().getInt(KEY_DISPLAY_NUMBER)
        val requestNumber = SpUtils.getInstance().getInt(KEY_REQUEST_NUMBER)
        val clickNumber = SpUtils.getInstance().getInt(KEY_CLICK_NUMBER)
        val adShow = SpUtils.getInstance().getInt(KEY_AD_SHOW, DEFAULT_AD_SHOW)
        val adRequest = SpUtils.getInstance().getInt(KEY_AD_REQUEST, DEFAULT_AD_REQUEST)
        val adClick = SpUtils.getInstance().getInt(KEY_AD_CLICK, DEFAULT_AD_CLICK)
        if (displayNumber >= adShow) {
            ReportAdUtils.showErrorAd(EVENT_SHOW_DISPLAYS, adUnit)
            return false
        }
        if (requestNumber >= adRequest) {
            ReportAdUtils.showErrorAd(EVENT_SHOW_REQUESTS, adUnit)
            return false
        }
        if (clickNumber >= adClick) {
            ReportAdUtils.showErrorAd(EVENT_SHOW_CLICKS, adUnit)
            return false
        }
        if (notCheckIntervalTime || lastDisplayTime.toInt() == 0) return true

        val interval = SpUtils.getInstance().getInt(KEY_AD_INTERVAL, DEFAULT_AD_INTERVAL)
        val flag = currentTime - lastDisplayTime > interval
        if (!flag) {
            ReportAdUtils.showErrorAd(EVENT_SHOW_INTERVAL_TIME, adUnit)
        }
        return flag
    }

    fun areTimestampsSameDay(timestamp1: Long, timestamp2: Long): Boolean {
        val calendar1 = Calendar.getInstance().apply { timeInMillis = timestamp1 }
        val calendar2 = Calendar.getInstance().apply { timeInMillis = timestamp2 }

        // 比较年、月、日是否相同
        return calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR) &&
                calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH) &&
                calendar1.get(Calendar.DAY_OF_MONTH) == calendar2.get(Calendar.DAY_OF_MONTH)
    }

    fun calculate(key: String) {
        val value = SpUtils.getInstance().getInt(key)
        SpUtils.getInstance().putInt(key, value + 1)
    }
}