package com.ads.cal.calculator.ad;

import static com.ads.cal.calculator.utils.EventIdUtils.AD_OPEN_CLK;
import static com.ads.cal.calculator.utils.EventIdUtils.AD_OPEN_CLOSE;
import static com.ads.cal.calculator.utils.EventIdUtils.AD_OPEN_EXP;
import static com.ads.cal.calculator.utils.EventIdUtils.AD_OPEN_LOAD_FAILED;
import static com.ads.cal.calculator.utils.EventIdUtils.AD_OPEN_LOAD_SUCCESS;
import static com.ads.cal.calculator.utils.EventIdUtils.AD_OPEN_SHOW_FAILED;
import static com.ads.cal.calculator.utils.EventIdUtils.AD_OPEN_START_LOAD;

import android.app.Activity;

import androidx.annotation.NonNull;

import com.ads.cal.calculator.MyApplication;
import com.ads.cal.calculator.utils.FireBaseAnalyticsUtils;
import com.ads.cal.calculator.utils.LogUtils;
import com.google.android.gms.ads.AdError;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.FullScreenContentCallback;
import com.google.android.gms.ads.LoadAdError;
import com.google.android.gms.ads.appopen.AppOpenAd;

import java.util.Date;

public class AppOpenAdManager {

    private static final String LOG_TAG = "AppOpenAdManager";
//    private static final String AD_UNIT_ID = "ca-app-pub-3940256099942544/3419835294";

    private AppOpenAd appOpenAd = null;
    private boolean isLoadingAd = false;
    private boolean isShowingAd = false;

    private OnLoadAdCompleteListener onLoadAdCompleteListener;
    private OnShowAdCompleteListener onShowAdCompleteListener;

    public boolean isShowingAd() {
        return isShowingAd;
    }

    /**
     * Keep track of the time an app open ad is loaded to ensure you don't show an expired ad.
     */
    private long loadTime = 0;

    /**
     * Constructor.
     */
    public AppOpenAdManager() {
    }


    /**
     * Load an ad.
     *
     */
    public void loadAd() {
        // Do not load ad if there is an unused ad or one is already loading.
        if (isLoadingAd || isAdAvailable()) {
            return;
        }

        isLoadingAd = true;
        AdRequest request = new AdRequest.Builder().build();
        AppOpenAd.load(
                MyApplication.getApplication(),
                "",
                request,
                new AppOpenAd.AppOpenAdLoadCallback() {
                    /**
                     * Called when an app open ad has loaded.
                     *
                     * @param ad the loaded app open ad.
                     */
                    @Override
                    public void onAdLoaded(AppOpenAd ad) {
                        appOpenAd = ad;
                        isLoadingAd = false;
                        loadTime = (new Date()).getTime();
                        if (null != onLoadAdCompleteListener) {
                            onLoadAdCompleteListener.onLoadAdComplete();
                            onLoadAdCompleteListener = null;
                        }

                        LogUtils.log(LOG_TAG, "onAdLoaded.");
                        FireBaseAnalyticsUtils.init().send(AD_OPEN_LOAD_SUCCESS);
                    }

                    /**
                     * Called when an app open ad has failed to load.
                     *
                     * @param loadAdError the error.
                     */
                    @Override
                    public void onAdFailedToLoad(LoadAdError loadAdError) {
                        isLoadingAd = false;
                        if (null != onLoadAdCompleteListener) {
                            onLoadAdCompleteListener.onLoadAdFailed(loadAdError.getMessage());
                            onLoadAdCompleteListener = null;
                        }
                        LogUtils.log(LOG_TAG, "onAdFailedToLoad: " + loadAdError.getMessage());
                        FireBaseAnalyticsUtils.init().send(AD_OPEN_LOAD_FAILED);
                    }
                });
        FireBaseAnalyticsUtils.init().send(AD_OPEN_START_LOAD);
    }

    /**
     * Check if ad was loaded more than n hours ago.
     */
    private boolean wasLoadTimeLessThanNHoursAgo(long numHours) {
        long dateDifference = (new Date()).getTime() - loadTime;
        long numMilliSecondsPerHour = 3600000;
        return (dateDifference < (numMilliSecondsPerHour * numHours));
    }

    /**
     * Check if ad exists and can be shown.
     */
    public boolean isAdAvailable() {
        // Ad references in the app open beta will time out after four hours, but this time limit
        // may change in future beta versions. For details, see:
        // https://support.google.com/admob/answer/9341964?hl=en
        return appOpenAd != null && wasLoadTimeLessThanNHoursAgo(4);
    }



    /**
     * Show the ad if one isn't already showing.
     *
     * @param activity                 the activity that shows the app open ad
     */
    public boolean showAdIfAvailable(
            @NonNull Activity activity) {
        // If the app open ad is already showing, do not show the ad again.
        if (isShowingAd) {
            LogUtils.log(LOG_TAG, "The app open ad is already showing.");
            return false;
        }

        // If the app open ad is not available yet, invoke the callback then load the ad.
        if (!isAdAvailable()) {
            LogUtils.log(LOG_TAG, "The app open ad is not ready yet.");
            loadAd();
            return false;
        }

        LogUtils.log(LOG_TAG, "Will show ad.");

        appOpenAd.setFullScreenContentCallback(
                new FullScreenContentCallback() {
                    /** Called when full screen content is dismissed. */
                    @Override
                    public void onAdDismissedFullScreenContent() {
                        // Set the reference to null so isAdAvailable() returns false.
                        appOpenAd = null;
                        isShowingAd = false;

                        LogUtils.log(LOG_TAG, "onAdDismissedFullScreenContent.");
                        if (null != onShowAdCompleteListener) {
                            onShowAdCompleteListener.onShowAdComplete();
                            onShowAdCompleteListener = null;
                        }
                        loadAd();
                        FireBaseAnalyticsUtils.init().send(AD_OPEN_CLOSE);
                    }

                    /** Called when fullscreen content failed to show. */
                    @Override
                    public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) {
                        appOpenAd = null;
                        isShowingAd = false;

                        LogUtils.log(LOG_TAG, "onAdFailedToShowFullScreenContent: " + adError.getMessage());
                        if (null != onShowAdCompleteListener) {
                            onShowAdCompleteListener.onShowAdFailed(adError.getMessage());
                            onShowAdCompleteListener = null;
                        }
                        loadAd();
                        FireBaseAnalyticsUtils.init().send(AD_OPEN_SHOW_FAILED);
                    }

                    /** Called when fullscreen content is shown. */
                    @Override
                    public void onAdShowedFullScreenContent() {
                        LogUtils.log(LOG_TAG, "onAdShowedFullScreenContent.");
                    }

                    @Override
                    public void onAdImpression() {
                        super.onAdImpression();
                        LogUtils.log(LOG_TAG, "onAdImpression.");
                        FireBaseAnalyticsUtils.init().send(AD_OPEN_EXP);
                    }

                    @Override
                    public void onAdClicked() {
                        super.onAdClicked();
                        FireBaseAnalyticsUtils.init().send(AD_OPEN_CLK);
                    }
                });

        isShowingAd = true;
        appOpenAd.show(activity);
        return true;
    }

    public interface OnShowAdCompleteListener {
        void onShowAdComplete();

        void onShowAdFailed(String errorMsg);
    }

    public interface OnLoadAdCompleteListener {
        void onLoadAdComplete();

        void onLoadAdFailed(String errorMsg);
    }

    public void setOnLoadAdCompleteListener(OnLoadAdCompleteListener onLoadAdCompleteListener) {
        this.onLoadAdCompleteListener = onLoadAdCompleteListener;
    }

    public void setOnShowAdCompleteListener(OnShowAdCompleteListener onShowAdCompleteListener) {
        this.onShowAdCompleteListener = onShowAdCompleteListener;
    }
}
