package com.reactnativebluestackmodule;

import com.reactnativebluestackmodule.common.ReactNativeModule;
import com.reactnativebluestackmodule.common.BluestackAdsCommon;

import android.util.Log;
import android.app.Activity;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.mngads.MNGAdsFactory;
import com.mngads.MAdvertiseRewardedVideo;
import com.mngads.listener.MAdvertiseRewardedVideoListener;
import com.mngads.models.MAdvertiseVideoReward;
import com.mngads.util.MNGPreference;
import com.mngads.util.MNGGender;
import android.location.Location;

import org.json.JSONException;
import org.json.JSONObject;

public class BluestackRewardedAdManager extends ReactNativeModule
        implements LifecycleEventListener, MAdvertiseRewardedVideoListener {

    private static final String TAG = "BluestackRewardedAdManager Bridge";
    private static final String REACT_CLASS = "BluestackRewardedAdManager";
    private static final String EVENT_LOADED_AD = "onAdLoaded";
    private static final String EVENT_DISAPPEAR_AD = "onAdDismissed";
    private static final String EVENT_DID_SHOWN_AD = "onAdDisplayed";
    private static final String EVENT_AD_CLICKED = "onAdClicked";
    private static final String EVENT_REWARD_EARNED = "onRewardEarned";
    private static final String EVENT_REWARD_TYPE_KEY = "rewardType";
    private static final String EVENT_REWARD_AMOUNT_KEY = "rewardAmount";
    private static final String EVENT_AD_ERROR = "onAdFailedError";
    private static final String EVENT_AD_MESSAGE_ERROR_KEY = "errorMessage";

    private static final String EVENT_KEY = "rewardedEvent";
    private static final String EVENT_NAME = "RewardedAdEvent";

    private MAdvertiseRewardedVideo rewardedAdsFactory;
    private MNGPreference mMNGPreference;

    public BluestackRewardedAdManager(ReactApplicationContext reactContext) {
        super(reactContext, TAG);
        reactContext.addLifecycleEventListener(this);
    }

    @ReactMethod
    public void loadAd(String placementId, boolean autoDisplay, String jsonPreference) {

        // instantiate mng Ads Factory
        if (rewardedAdsFactory == null) {
            rewardedAdsFactory = new MAdvertiseRewardedVideo(getActivity());
        }

        // set MNG placement Id
        rewardedAdsFactory.setPlacementId(placementId);

        // set event listener
        rewardedAdsFactory.setRewardedVideoListener(this);

        mMNGPreference = BluestackAdsCommon.getMNGPreference(jsonPreference, getApplicationContext());

        try {
            Activity currentActivity = getActivity();

            if (currentActivity == null) {
                Log.d(TAG, "Load Rewarded attempted but the current Activity was null.");
                return;
            }
            currentActivity.runOnUiThread(
                    () -> rewardedAdsFactory.loadRewardedVideo(mMNGPreference));
        } catch (Exception e) {
            Log.d(TAG, "Load Rewarded failed with exception: " + e.toString());
        }
    }

    @ReactMethod
    public void displayAd() {
        if (rewardedAdsFactory.isRewardedVideoReady()) {

            try {
                Activity currentActivity = getActivity();

                if (currentActivity == null) {
                    Log.d(TAG, "display Rewarded attempted but the current Activity was null.");
                    return;
                }
                currentActivity.runOnUiThread(
                        () -> rewardedAdsFactory.showRewardedVideo());
            } catch (Exception e) {
                Log.d(TAG, "display Rewarded failed with exception: " + e.toString());
            }

        } else {
            WritableMap params = Arguments.createMap();
            params.putString(EVENT_KEY, EVENT_AD_ERROR);
            params.putString(EVENT_AD_MESSAGE_ERROR_KEY, "Rewarded Ad is not loaded");
            sendEvent(getContext(), params);
        }
    }

    @Override
    public void onRewardedVideoLoaded() {
        // Log.d(TAG, "onRewardedVideoLoaded");
        WritableMap params = Arguments.createMap();
        params.putString(EVENT_KEY, EVENT_LOADED_AD);
        sendEvent(getContext(), params);
    }

    @Override
    public void onRewardedVideoError(Exception e) {
        Log.d(TAG, "RewardedVideoError: " + e.getMessage());
        WritableMap params = Arguments.createMap();
        params.putString(EVENT_KEY, EVENT_AD_ERROR);
        params.putString(EVENT_AD_MESSAGE_ERROR_KEY, "onRewardedVideoError: error code = " + e.hashCode()
                + ", message = " + e.getMessage());
        sendEvent(getContext(), params);
    }

    @Override
    public void onRewardedVideoClosed() {
        // Log.d(TAG, "onRewardedVideoClosed");
        WritableMap params = Arguments.createMap();
        params.putString(EVENT_KEY, EVENT_DISAPPEAR_AD);
        sendEvent(getContext(), params);
    }

    @Override
    public void onRewardedVideoAppeared() {
        // Log.d(TAG, "onRewardedVideoAppeared");
        WritableMap params = Arguments.createMap();
        params.putString(EVENT_KEY, EVENT_DID_SHOWN_AD);
        sendEvent(getContext(), params);
    }

    @Override
    public void onUserRewardEarned(MAdvertiseVideoReward mAdvertiseVideoReward) {
        // Log.d(TAG, "onUserRewardEarned");
        WritableMap params = Arguments.createMap();
        params.putString(EVENT_KEY, EVENT_REWARD_EARNED);
        params.putString(EVENT_REWARD_TYPE_KEY, mAdvertiseVideoReward.getType());
        params.putDouble(EVENT_REWARD_AMOUNT_KEY, mAdvertiseVideoReward.getAmount());
        sendEvent(getContext(), params);
    }

    @Override
    public void onRewardedVideoClicked() {
        // Log.d(TAG, "onRewardedVideoClicked");
        WritableMap params = Arguments.createMap();
        params.putString(EVENT_KEY, EVENT_AD_CLICKED);
        sendEvent(getContext(), params);
    }

    @NonNull
    @Override
    public String getName() {
        return REACT_CLASS;
    }

    @Override
    public void initialize() {
        super.initialize();
    }

    @Override
    public void onHostResume() {

    }

    @Override
    public void onHostPause() {

    }

    @Override
    public void onHostDestroy() {
        if (rewardedAdsFactory != null) {
            rewardedAdsFactory.releaseMemory();
            rewardedAdsFactory = null;
        }
    }

    private void sendEvent(ReactContext reactContext, @Nullable WritableMap params) {
        reactContext
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit(EVENT_NAME, params);
    }

    @ReactMethod
    public void addListener(String eventName) {
        // Set up any upstream listeners or background tasks as necessary
    }

    @ReactMethod
    public void removeListeners(Integer count) {
        // Remove upstream listeners, stop unnecessary background tasks
    }

}
