package com.datarecovery.master.sdk.gravity;

import android.app.Application;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;

import androidx.annotation.NonNull;

import com.atmob.common.logging.AtmobLog;
import com.atmob.common.runtime.ContextUtil;
import com.atmob.common.runtime.ProcessUtil;
import com.atmob.user.AtmobUser;
import com.datarecovery.master.BuildConfig;

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

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import atmob.reactivex.rxjava3.core.Completable;
import atmob.reactivex.rxjava3.core.CompletableObserver;
import atmob.reactivex.rxjava3.disposables.Disposable;
import atmob.rxjava.utils.RxJavaUtil;
import cn.gravity.android.GEConfig;
import cn.gravity.android.GravityEngineSDK;
import cn.gravity.android.RegisterCallback;

public class GravityHelper {
    private static final String TAG = GravityHelper.class.getSimpleName();

    private static final String accessToken = BuildConfig.GRAVITY_ACCESS_TOKEN;
    private static Disposable registerDisposable;
    private static GravityEngineSDK gravityEngineSDKInstance;
    private static final Handler handler = new Handler(Looper.getMainLooper());
    private static Boolean attributed;
    private static final List<AttributionResultCallback> callbacks = new ArrayList<>(5);

    public static void init(Application application) {
        if (!ProcessUtil.isMainProcess(application)) {
            return;
        }
        onPrivacyAgreed(application);
    }

    public static void onPrivacyAgreed(Context context) {
        GEConfig config = GEConfig.getInstance(context, accessToken);
        config.setMode(BuildConfig.DEBUG ? GEConfig.ModeEnum.DEBUG : GEConfig.ModeEnum.NORMAL);
        gravityEngineSDKInstance = GravityEngineSDK.sharedInstance(config);
        reportRegister();
    }

    private static boolean isAttribution(String adPlatform) {
        return !TextUtils.isEmpty(adPlatform) && !"natural".equals(adPlatform);
    }

    public static void reportRegister() {
        if (registerDisposable != null || gravityEngineSDKInstance == null) {
            return;
        }
        Completable.create(emitter -> {
                    try {
                        gravityEngineSDKInstance.register(accessToken, AtmobUser.getAtmobChannel(),
                                new RegisterCallback() {
                                    @Override
                                    public void onFailed(String errorMsg, JSONObject jsonObject) {
                                        AtmobLog.d(TAG, "GravityEngine register onFailed jsonObject--" + jsonObject);
                                        emitter.onError(new Exception(errorMsg));
                                    }

                                    @Override
                                    public void onSuccess(JSONObject jsonObject1, JSONObject jsonObject2) {
                                        AtmobLog.d(TAG, "GravityEngine register onSuccess jsonObject1--" + jsonObject1);
                                        AtmobLog.d(TAG, "GravityEngine register onSuccess jsonObject2--" + jsonObject2);
                                        parseGravityJson(jsonObject1);
                                        emitter.onComplete();
                                    }
                                }, true);
                    } catch (Exception e) {
                        emitter.onError(e);
                    }
                })
                .retryWhen(RxJavaUtil.retryWhen(null, 5, 1000, TimeUnit.MILLISECONDS))
                .compose(RxJavaUtil.CompletableSchedule.ioOnly())
                .subscribe(new CompletableObserver() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        registerDisposable = d;
                    }

                    @Override
                    public void onComplete() {
                        AtmobLog.d(TAG, "GravityEngine register success");
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        AtmobLog.e(TAG, "GravityEngine register failed, " + e.getMessage());
                        e.printStackTrace();
                    }
                });
    }

    private static void parseGravityJson(JSONObject jsonObject) {
        if (jsonObject == null || jsonObject.isNull("click_company")) {
            return;
        }
        try {
            String click_company = jsonObject.getString("click_company");
            onAttributionResult(isAttribution(click_company));
        } catch (JSONException ignored) {

        }
    }


    public static void reportPay(int payAmount, String order_no, String product, String payWay) {
        if (gravityEngineSDKInstance != null)
            gravityEngineSDKInstance.trackPayEvent(payAmount, "CNY", order_no, product, payWay);
    }

    public static void report(String eventId) {
        report(eventId, null);
    }

    public static void report(String eventId, Map<String, Object> params) {
        if (gravityEngineSDKInstance != null) {
            JSONObject jsonObject = null;
            if (params != null) {
                jsonObject = new JSONObject(params);
            }
            gravityEngineSDKInstance.track(eventId, jsonObject);
        }
    }

    public static void timeEvent(String eventId) {
        if (gravityEngineSDKInstance != null) {
            gravityEngineSDKInstance.timeEvent(eventId);
        }
    }

    public static String getAccessToken() {
        return accessToken;
    }


    private static void onAttributionResult(boolean result) {
        synchronized (GravityHelper.class) {
            attributed = result;
            Iterator<AttributionResultCallback> iterator = callbacks.iterator();
            while (iterator.hasNext()) {
                AttributionResultCallback callback = iterator.next();
                if (callback == null) {
                    iterator.remove();
                    continue;
                }
                handler.post(() -> callback.onResult(attributed));
                iterator.remove();
            }
        }
    }

    public static void registerAttributionResultCallback(AttributionResultCallback callback) {
        if (!ProcessUtil.isMainProcess(ContextUtil.getContext())) {
            return;
        }
        if (callback == null) {
            return;
        }
        if (attributed != null) {
            callback.onResult(attributed);
            return;
        }
        synchronized (GravityHelper.class) {
            if (attributed != null) {
                callback.onResult(attributed);
                return;
            }
            callbacks.add(callback);
        }
    }

    public static void unregisterAttributionResultCallback(AttributionResultCallback callback) {
        if (!ProcessUtil.isMainProcess(ContextUtil.getContext())) {
            return;
        }
        if (callback == null) {
            return;
        }
        synchronized (GravityHelper.class) {
            callbacks.remove(callback);
        }
    }


    @FunctionalInterface
    public interface AttributionResultCallback {
        void onResult(boolean attributed);
    }
}