package com.fuse.PushNotifications;

import android.os.Bundle;
import java.util.ArrayList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Arrays;
import java.util.Iterator;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import org.json.JSONObject;
import org.json.JSONArray;
import org.json.JSONException;
import android.util.Log;

public class PushNotificationReceiver extends FirebaseMessagingService {
	public static ArrayList<Bundle> _cachedBundles = new ArrayList<Bundle>();
	public static boolean InForeground = false;
	public static String ACTION = "fuseBackgroundNotify";
	static int _notificationID = -1;
	public static int nextID() { return _notificationID += 1; }
	private static Object lock = new Object();

	public PushNotificationReceiver() { 
		super();
	}
	@Override
	public void onNewToken(String refreshedToken) {
		super.onNewToken(refreshedToken);
		com.foreign.Fuse.PushNotifications.AndroidImpl.RegistrationIDUpdated(refreshedToken);
	}
	@Override
	public void onMessageReceived(RemoteMessage message)
	{
		synchronized (lock) {
			Bundle bundle = new Bundle();

			try {
				//reconstruct JSON string from Map and test it
				String jsonStr = "{";
				for (Map.Entry<String, String> entry : message.getData().entrySet()) {
					jsonStr += "\"" + entry.getKey() + "\":";
					if (entry.getValue().charAt(0) == '{') {
						jsonStr += entry.getValue() + ",";
					} else {
						jsonStr += "\"" + entry.getValue() + "\"" + ",";	
					}
				}
				jsonStr = jsonStr.replaceAll(",$", "");
				jsonStr += "}";

				JSONObject jsonObj = new JSONObject(jsonStr);

	            jsonStr = jsonObj.toString();

	            bundle = jsonStrToBundle(jsonStr);

			} catch (JSONException je) {
				Log.d("onMessageReceived", "BAD JSON");

				//fallback to older implementation
				for (Map.Entry<String, String> entry : message.getData().entrySet()) {
					bundle.putString(entry.getKey(), entry.getValue());
				}
			}

			com.foreign.Fuse.PushNotifications.AndroidImpl.OnNotificationRecieved(this, message.getFrom(), bundle);
		}
	}

    public static Bundle jsonStrToBundle(String jsonStr) {
        Bundle bundle = new Bundle();

        try {
            JSONObject jsonObject = new JSONObject(jsonStr.trim());
            bundle = handleJSONObject(jsonObject);
        } catch (JSONException notObject) {
            try {
                JSONArray jsonArr = new JSONArray(jsonStr.trim());
                bundle = handleJSONArray(jsonArr);
            } catch (JSONException badJSON) {
                Log.d("jsonStrToBundle", "BAD JSON");
            }
        }

        return bundle;
    }
    
    
    public static Bundle handleJSONArray(JSONArray jsonArray) {
        Bundle bundle = new Bundle();

        for (int i = 0; i < jsonArray.length(); i++) {
            
            try {
                Object jsonArrayValue = jsonArray.get(i);

                if (jsonArrayValue instanceof JSONObject) {
                    bundle.putBundle("" + i, handleJSONObject((JSONObject) jsonArrayValue));
                } else if (jsonArrayValue instanceof JSONArray) {
                    bundle.putBundle("" + i, handleJSONArray((JSONArray) jsonArrayValue));
                } else if (jsonArrayValue instanceof String) {
                    bundle.putString("" + i, "" + jsonArrayValue);
                } else if (jsonArrayValue instanceof Boolean) {
                    bundle.putBoolean("" + i, (boolean) jsonArrayValue);
                } else if (jsonArrayValue instanceof Integer) {
                    bundle.putInt("" + i, (int) jsonArrayValue);
                } else if (jsonArrayValue instanceof Double) {
                    bundle.putDouble("" + i, (double) jsonArrayValue);
                } else if (jsonArrayValue instanceof Long) {
                    bundle.putLong("" + i, (long) jsonArrayValue);
                }
            } catch (JSONException je) {
                Log.d("handleJSONArray", "BAD JSON VALUE IN JSON ARRAY, AT POSITION: " + i);
            }
        }

        return bundle;
    }

    public static Bundle handleJSONObject(JSONObject jsonObject) {
        Bundle bundle = new Bundle();

        Iterator<String> keys = jsonObject.keys();

        while(keys.hasNext()) {
            String keyStr = keys.next();

            try {
                Object keyValue = jsonObject.get(keyStr);
            
                if (keyValue instanceof JSONObject) {
                    bundle.putBundle(keyStr, handleJSONObject((JSONObject) keyValue));
                } else if (keyValue instanceof JSONArray) {
                    bundle.putBundle(keyStr, handleJSONArray((JSONArray) keyValue));
                } else if (keyValue instanceof String) {
                    bundle.putString(keyStr, "" + keyValue);
                } else if (keyValue instanceof Boolean) {
                    bundle.putBoolean(keyStr, (boolean) keyValue);
                } else if (keyValue instanceof Integer) {
                    bundle.putInt(keyStr, (int) keyValue);
                } else if (keyValue instanceof Double) {
                    bundle.putDouble(keyStr, (double) keyValue);
                } else if (keyValue instanceof Long) {
                    bundle.putLong(keyStr, (long) keyValue);
                }
            } catch (JSONException je) {
                Log.d("handleJSONObject", "BAD JSON VALUE IN JSON OBJECT, AT KEY: " + keyStr);
            }
        }
        
        return bundle;
    }
}

@@ -859,18 +859,17 @@
 iver() %7B
- 
 %0A
+
 %09%09super(
@@ -1550,17 +1550,16 @@
 %22 + %22,%22;
-%09
 %0A%09%09%09%09%09%7D%0A
@@ -2713,25 +2713,17 @@
 ;%0A    %7D%0A
-    %0A    
+%0A
 %0A    pub
@@ -2873,29 +2873,17 @@
  i++) %7B%0A
-            
 %0A
+
         
@@ -4438,21 +4438,9 @@
 r);%0A
-            
 %0A
+
     
@@ -5497,24 +5497,16 @@
       %7D%0A
-        
 %0A       

trim trailing whitespace