package it.near.sdk.operation;

import android.content.Context;
import android.net.Uri;
import android.support.annotation.NonNull;

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

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import cz.msebera.android.httpclient.Header;
import cz.msebera.android.httpclient.auth.AuthenticationException;
import it.near.sdk.GlobalConfig;
import it.near.sdk.communication.Constants;
import it.near.sdk.communication.NearAsyncHttpClient;
import it.near.sdk.communication.NearJsonHttpResponseHandler;
import it.near.sdk.logging.NearLog;
import it.near.sdk.utils.NearJsonAPIUtils;

public class NearItUserDataAPI {

    private static final String TAG = "NearItUserDataAPI";
    private static final String PLUGIN_NAME = "congrego";
    private static final String PROFILE_RES_TYPE = "profiles";
    private static final String DATA_POINTS_RES_TYPE = "data_points";

    private final GlobalConfig globalConfig;
    private final NearAsyncHttpClient httpClient;
    private boolean optedOut;

    public NearItUserDataAPI(GlobalConfig globalConfig, NearAsyncHttpClient httpClient) {
        this.globalConfig = globalConfig;
        this.httpClient = httpClient;
        optedOut = globalConfig.getOptOut();
    }

    public void sendDataPoints(@NonNull final HashMap<String, String> userData, final UserDataSendListener listener) {
        if (!optedOut) {
            String profileId = globalConfig.getProfileId();
            if (!userData.isEmpty()) {
                if (profileId != null) {
                    ArrayList<HashMap<String, Object>> maps = new ArrayList<>();
                    for (Map.Entry<String, String> entry : userData.entrySet()) {
                        HashMap<String, Object> map = new HashMap<>();
                        map.put("key", entry.getKey());
                        map.put("value", entry.getValue());
                        maps.add(map);
                    }
                    String reqBody;
                    try {
                        reqBody = NearJsonAPIUtils.toJsonAPI("data_points", maps);
                    } catch (JSONException e) {
                        NearLog.d(TAG, "Error creating userdata request");
                        listener.onSendingFailure();
                        return;
                    }

                    Uri url = Uri.parse(Constants.API.PLUGINS_ROOT).buildUpon()
                            .appendPath(PLUGIN_NAME)
                            .appendPath(PROFILE_RES_TYPE)
                            .appendPath(profileId)
                            .appendPath(DATA_POINTS_RES_TYPE).build();

                    try {
                        httpClient.nearPost(url.toString(), reqBody, new NearJsonHttpResponseHandler() {
                            @Override
                            public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
                                NearLog.d(TAG, "datapoint created: " + response.toString());
                                listener.onSendingSuccess(userData);
                            }

                            @Override
                            public void onFailureUnique(int statusCode, Header[] headers, Throwable throwable, String responseString) {
                                NearLog.d(TAG, "datapoint not created, network error: " + statusCode);
                                listener.onSendingFailure();
                            }
                        });
                    } catch (AuthenticationException | UnsupportedEncodingException e) {
                        NearLog.d(TAG, "error: impossible to send requests");
                    }
                }
            }
        }
    }

    public static NearItUserDataAPI obtain(GlobalConfig globalConfig, Context context) {
        return new NearItUserDataAPI(globalConfig, new NearAsyncHttpClient(context, globalConfig));
    }

    interface UserDataSendListener {
        void onSendingSuccess(HashMap<String, String> sentData);

        void onSendingFailure();
    }
}

@@ -123,16 +123,41 @@
 NonNull;
+%0Aimport android.util.Log;
 %0A%0Aimport
@@ -3763,24 +3763,77 @@
 requests%22);%0A
+                        listener.onSendingFailure();%0A
             
@@ -3851,32 +3851,39 @@
                %7D
+ else %7B
 %0A            %7D%0A 
@@ -3871,33 +3871,434 @@
 e %7B%0A            
-%7D
+        Log.d(TAG, %22datapoint not created: profile id is null%22);%0A                    listener.onSendingFailure();%0A                %7D%0A            %7D else %7B%0A                Log.d(TAG, %22datapoint not created: data is empty%22);%0A                listener.onSendingFailure();%0A            %7D%0A        %7D else %7B%0A            Log.d(TAG, %22datapoint not created: user opted out%22);%0A            listener.onSendingFailure();
 %0A        %7D%0A    %7D

add failure callbacks