package com.moonmiles.bridge.apm;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.moonmiles.apmservices.model.APMAction;
import com.moonmiles.apmservices.model.APMEarn;
import com.moonmiles.apmservices.model.APMUser;
import com.moonmiles.apmservices.model.challenge.APMChallenge;
import com.moonmiles.apmservices.model.status.APMUserStatus;
import com.moonmiles.apmservices.model.trophy.APMTrophy;
import com.moonmiles.apmservices.sdk.APMServicesListener;
import com.moonmiles.apmservices.sdk.APMServicesUserListener;
import com.moonmiles.bridge.apm.abs.APMReactContextBaseJavaModule;
import com.moonmiles.bridge.apm.utils.APMBridgeUtils;

import org.json.JSONException;

import java.util.HashMap;
import java.util.Map;

public class APMServicesModule extends APMReactContextBaseJavaModule implements APMServicesListener, APMServicesUserListener
{
    private static final String EVENT_SERVICES_ON_LOADING         = "servicesOnLoading";
    private static final String EVENT_SERVICES_READY              = "servicesReady";
    private static final String EVENT_SERVICES_DISABLE            = "servicesDisable";
    private static final String EVENT_SERVICES_USER_WIN_POINTS    = "servicesUserWinPoints";
    private static final String EVENT_SERVICES_USER_WIN_CHALLENGE = "servicesUserWinChallenge";
    private static final String EVENT_SERVICES_USER_WIN_TROPHY    = "servicesUserWinTrophy";
    private static final String EVENT_SERVICES_USER_WIN_LEVEL     = "servicesUserWinLevel";

    private static final String EVENT_SERVICES_USER_CHANGED     = "servicesUserChanged";

    public APMServicesModule(ReactApplicationContext reactContext)
    {
        super(reactContext);
    }

    @Override
    public String getName() { return "APMServicesModule"; }

    @Override
    public Map<String, Object> getConstants()
    {
        final Map<String, Object> constants = new HashMap<>();
        return constants;
    }

    //APMServicesListener
    //*******************//
    @Override
    public void apmServicesOnLoading()
    {
        APMBridgeUtils.sendEvent(getReactApplicationContext(), EVENT_SERVICES_ON_LOADING, null);
    }

    @Override
    public void apmServicesReady(boolean newInfos)
    {
        WritableMap params = Arguments.createMap();
        params.putBoolean("newInfos", newInfos);
        APMBridgeUtils.sendEvent(getReactApplicationContext(), EVENT_SERVICES_READY, params);
    }

    @Override
    public void apmServicesDisable()
    {
        APMBridgeUtils.sendEvent(getReactApplicationContext(), EVENT_SERVICES_DISABLE, null);
    }

    @Override
    public void apmServicesUserWinPoints(APMEarn earn, APMUser user)
    {
        try
        {
            WritableMap params = Arguments.createMap();
            params.putMap("earn", APMBridgeUtils.convertObjectToMap(earn));
            params.putMap("user", APMBridgeUtils.convertObjectToMap(user));
            APMBridgeUtils.sendEvent(getReactApplicationContext(), EVENT_SERVICES_USER_WIN_POINTS, params);
        }
        catch(JSONException e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public void apmServicesUserWinChallenge(APMChallenge challenge, APMUser user)
    {
        try
        {
            WritableMap params = Arguments.createMap();
            params.putMap("challenge", APMBridgeUtils.convertObjectToMap(challenge));
            params.putMap("user", APMBridgeUtils.convertObjectToMap(user));
            APMBridgeUtils.sendEvent(getReactApplicationContext(), EVENT_SERVICES_USER_WIN_CHALLENGE, params);
        }
        catch(JSONException e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public void apmServicesUserWinTrophy(APMTrophy trophy, APMUser user)
    {
        try
        {
            WritableMap params = Arguments.createMap();
            params.putMap("trophy", APMBridgeUtils.convertObjectToMap(trophy));
            params.putMap("user", APMBridgeUtils.convertObjectToMap(user));
            APMBridgeUtils.sendEvent(getReactApplicationContext(), EVENT_SERVICES_USER_WIN_TROPHY, params);
        }
        catch(JSONException e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public void apmServicesUserWinLevel(APMUserStatus userStatus, APMUser user)
    {
        try
        {
            WritableMap params = Arguments.createMap();
            params.putMap("userStatus", APMBridgeUtils.convertObjectToMap(userStatus));
            params.putMap("user", APMBridgeUtils.convertObjectToMap(user));
            APMBridgeUtils.sendEvent(getReactApplicationContext(), EVENT_SERVICES_USER_WIN_LEVEL, params);
        }
        catch(JSONException e)
        {
            e.printStackTrace();
        }
    }
    //*******************//

    //APMServicesUserListener
    //*******************//
    @Override
    public void apmServicesUserChanged(APMUser user)
    {
        try
        {
            APMBridgeUtils.sendEvent(getReactApplicationContext(), EVENT_SERVICES_USER_CHANGED, APMBridgeUtils.convertObjectToMap(user));
        }
        catch(JSONException e)
        {
            e.printStackTrace();
        }
    }
    //*******************//

    //Init
    @ReactMethod
    public void initAppWithPartnerID(String partnerID, String partnerSecret)
    {
        getAPMServices().initApp(partnerID, partnerSecret);
    }

    @ReactMethod
    public void initAppWithAppID(String partnerID, String partnerSecret, String appId)
    {
        getAPMServices().initApp(partnerID, partnerSecret, appId);
    }

    //Cycle de vie
    @ReactMethod
    public void refreshSDK()
    {
        getAPMServices().onResume(APMBridgeUtils.getIntentFromActivity(getCurrentActivity()));
    }

    //Listener
    @ReactMethod
    public void setServicesListener()
    {
        getAPMServices().setServicesListener(this);
    }

    @ReactMethod
    public void setServicesUserListener()
    {
        getAPMServices().setServicesUserListener(this);
    }

    //Services
    //TODO public void registerAction(APMAction action) à finir
    //*************************************************
    @ReactMethod
    public void registerAction(ReadableMap action)
    {
        APMAction apmAction = null;
        getAPMServices().registerAction(apmAction);
    }
    //*************************************************

    @ReactMethod
    public void removeActionWithActionName(String actionName)
    {
        getAPMServices().removeAction(actionName);
    }

    @ReactMethod
    public void getActionsForClassId(String classId, Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getActionsForClassId(classId), promise);
    }

    @ReactMethod
    public void selectClassID(String classID)
    {
        getAPMServices().selectClassID(classID);
    }

    @ReactMethod
    public void triggerAction(String actionName)
    {
        getAPMServices().triggerAction(actionName);
    }

    //Getter and Setter
    @ReactMethod
    public void setBaseUrl(String baseUrl)
    {
        getAPMServices().setBaseUrl(baseUrl);
    }

    @ReactMethod
    public void getBaseUrl(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getBaseUrl(), promise);
    }

    @ReactMethod
    public void setDebugMode(boolean debugMode)
    {
        getAPMServices().setDebugMode(debugMode);
    }

    @ReactMethod
    public void isDebugMode(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).isDebugMode(), promise);
    }

    @ReactMethod
    public void setGeolocEnabled(boolean geolocEnabled)
    {
        getAPMServices().setGeolocEnabled(geolocEnabled);
    }

    @ReactMethod
    public void isGeolocEnabled(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).isGeolocEnabled(), promise);
    }

    @ReactMethod
    public void setAppID(String appID)
    {
        getAPMServices().setAppId(appID);
    }

    @ReactMethod
    public void appID(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getAppId(), promise);
    }

    @ReactMethod
    public void setPartnerID(String partnerID)
    {
        getAPMServices().setPartnerId(partnerID);
    }

    @ReactMethod
    public void partnerID(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getPartnerId(), promise);
    }

    @ReactMethod
    public void setPartnerSecret(String partnerSecret)
    {
        getAPMServices().setPartnerSecret(partnerSecret);
    }

    @ReactMethod
    public void partnerSecret(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getPartnerSecret(), promise);
    }

    @ReactMethod
    public void setApmVersionCode(String apmVersionCode)
    {
        getAPMServices().setApmVersionCode(apmVersionCode);
    }

    @ReactMethod
    public void apmVersionCode(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getApmVersionCode(), promise);
    }

    @ReactMethod
    public void setApmVersionName(String apmVersionName)
    {
        getAPMServices().setApmVersionName(apmVersionName);
    }

    @ReactMethod
    public void apmVersionName(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getApmVersionName(), promise);
    }

    @ReactMethod
    public void isInitialLevel(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).isInitialLevel(), promise);
    }

    @ReactMethod
    public void servicesIsOnError(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).servicesIsOnError(), promise);
    }

    @ReactMethod
    public void servicesIsDisabled(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).servicesIsDisabled(), promise);
    }

    @ReactMethod
    public void user(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getUser(), promise);
    }

    @ReactMethod
    public void prog(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getProg(), promise);
    }

    @ReactMethod
    public void generosity(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getGenerosity(), promise);
    }

    @ReactMethod
    public void generosities(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getGenerosities(), promise);
    }

    @ReactMethod
    public void gift(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getGift(), promise);
    }

    @ReactMethod
    public void device(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getDevice(), promise);
    }

    @ReactMethod
    public void frequencies(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getFrequencies(), promise);
    }

    @ReactMethod
    public void values(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getValues(), promise);
    }

    @ReactMethod
    public void status(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getStatus(), promise);
    }

    @ReactMethod
    public void setSdkLifeCycleEnabled(boolean sdkLifeCycleEnabled)
    {
        getAPMServices().setSdkLifeCycleEnabled(sdkLifeCycleEnabled);
    }

    @ReactMethod
    public void sdkLifeCycleEnabled(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).isSdkLifeCycleEnabled(), promise);
    }

    @ReactMethod
    public void sdkIsLoading(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).sdkIsLoading(), promise);
    }

    @ReactMethod
    public void classID(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getClassId(), promise);
    }

    @ReactMethod
    public void theme(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getTheme(), promise);
    }

    @ReactMethod
    public void setDeviceStatus(Integer deviceStatus)
    {
        getAPMServices().setDeviceStatus(deviceStatus);
    }

    @ReactMethod
    public void setDeviceOptIn(Integer optIn)
    {
        getAPMServices().setDeviceOptIn(optIn);
    }

    @ReactMethod
    public void getPendingConnectionInfo(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getPendingConnectionInfo(), promise);
    }

    @ReactMethod
    public void getVersions(Promise promise)
    {
        APMBridgeUtils.resolvePromise(getAPMServices(promise).getVersions(), promise);
    }
}
