package main.java.com.mindscapehq.android.raygun4android.network;

import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import main.java.com.mindscapehq.android.raygun4android.RaygunClient;
import main.java.com.mindscapehq.android.raygun4android.RaygunPulseEventType;
import main.java.com.mindscapehq.android.raygun4android.RaygunSettings;
import main.java.com.mindscapehq.android.raygun4android.network.http.RaygunUrlStreamHandlerFactory;

public class RaygunNetworkLogger {
  private static final long CONNECTION_TIMEOUT = 60000L; // 1 min
  private static volatile HashMap<String, RaygunNetworkRequestInfo> connections = new HashMap<String, RaygunNetworkRequestInfo>();
  private static boolean loggingEnabled = true;
  private static boolean loggingInitialized = false;

  public static void init() {
    if (loggingEnabled && !loggingInitialized) {
      try {
        RaygunUrlStreamHandlerFactory factory = new RaygunUrlStreamHandlerFactory();
        URL.setURLStreamHandlerFactory(factory);
        loggingInitialized = true;
      }
      catch (SecurityException e) {
        loggingInitialized = false;
      }
    }
  }

  public static void setEnabled(boolean enabled) {
    loggingEnabled = enabled;
  }

  public static synchronized void startNetworkCall(String url, long startTime) {
    if (!shouldIgnoreURL(url) && loggingEnabled) {
      removeOldEntries();
      String id = sanitiseURL(url);
      connections.put(id, new RaygunNetworkRequestInfo(url, startTime));
    }
  }

  public static synchronized void endNetworkCall(String url, String requestMethod, long endTime, int statusCode) {
    if (url != null) {
      String id = sanitiseURL(url);
      if ((connections.containsKey(id))) {
        RaygunNetworkRequestInfo request = connections.get(id);
        if (request != null) {
          connections.remove(url);
          sendNetworkTimingEvent(request.url, requestMethod, request.startTime, endTime, statusCode, null);
        }
      }
    }
  }

  /**
   * When a network request is cancelled we stop tracking it and do not send the information through.
   * Future updates may include sending the cancelled request timing through with information showing it was cancelled.
   */
  public static synchronized void cancelNetworkCall(String url, String requestMethod, long endTime, String exception) {
    if (url != null) {
      String id = sanitiseURL(url);
      if ((connections != null) && (connections.containsKey(id))) {
        RaygunNetworkRequestInfo request = connections.get(id);
        if (request != null) {
          connections.remove(id);
        }
      }
    }
  }

  public static synchronized void sendNetworkTimingEvent(String url, String requestMethod, long startTime, long endTime, int statusCode, String exception) {
    if (!shouldIgnoreURL(url) && loggingEnabled) {
      RaygunClient.sendPulseTimingEvent(RaygunPulseEventType.NETWORK_CALL, requestMethod+" "+url, endTime - startTime);
    }
  }

  private static synchronized void removeOldEntries() {
    Iterator<Map.Entry<String, RaygunNetworkRequestInfo>> it = connections.entrySet().iterator();
    while (it.hasNext()) {
      Map.Entry<String, RaygunNetworkRequestInfo> pairs = it.next();
      long startTime = pairs.getValue().startTime;
      if (System.currentTimeMillis() - startTime > CONNECTION_TIMEOUT) {
        it.remove();
      }
    }
  }

  private static String sanitiseURL(String url) {
    if (url != null) {
      url = url.toLowerCase();
      url = url.replaceAll("https://", "");
      url = url.replaceAll("http://", "");
      url = url.replaceAll("www.", "");
    }
    return url;
  }

  private static boolean shouldIgnoreURL(String url) {
    if (url == null) {
      return true;
    }
    for (String ignoredUrl : RaygunSettings.getIgnoredURLs()) {
      if (url.contains(ignoredUrl) || ignoredUrl.contains(url)) {
        return true;
      }
    }
    return false;
  }
}
@@ -1851,43 +1851,8 @@
 ) %7B%0A
-          connections.remove(url);%0A
     
@@ -1951,24 +1951,58 @@
 ode, null);%0A
+          connections.remove(id);%0A
         %7D%0A  
@@ -2503,105 +2503,8 @@
 ) %7B%0A
-        RaygunNetworkRequestInfo request = connections.get(id);%0A        if (request != null) %7B%0A  
     
@@ -2527,34 +2527,24 @@
 remove(id);%0A
-        %7D%0A
       %7D%0A    
@@ -2754,24 +2754,54 @@
 gEnabled) %7B%0A
+      url = sanitiseURL(url);%0A
       Raygun
@@ -3416,159 +3416,122 @@
     
-url = url.toLowerCase();%0A      url = url.replaceAll(%22https://%22, %22%22);%0A      url = url.replaceAll(%22http://%22, %22%22);%0A      url = url.replaceAll(%22www.%22, %22%22);
+int queryIndex = url.indexOf(%22?%22);%0A      if (queryIndex %3E 0) %7B%0A        url = url.substring(0, queryIndex);%0A      %7D
 %0A   

Remove query values from network request URL when sending it through to Raygun.