package com.bugsnag;

import com.bugsnag.callbacks.AppCallback;
import com.bugsnag.callbacks.Callback;
import com.bugsnag.callbacks.DeviceCallback;
import com.bugsnag.callbacks.ServletCallback;
import com.bugsnag.delivery.AsyncHttpDelivery;
import com.bugsnag.delivery.Delivery;
import com.bugsnag.delivery.HttpDelivery;
import com.bugsnag.serialization.Serializer;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Configuration {

    private static final String HEADER_API_PAYLOAD_VERSION = "Bugsnag-Payload-Version";
    private static final String HEADER_API_KEY = "Bugsnag-Api-Key";
    private static final String HEADER_BUGSNAG_SENT_AT = "Bugsnag-Sent-At";

    public String apiKey;
    public String appType;
    public String appVersion;
    public Delivery delivery = new AsyncHttpDelivery();
    public Delivery sessionDelivery;
    public String[] filters = new String[]{"password"};
    public String[] ignoreClasses;
    public String[] notifyReleaseStages = null;
    public String[] projectPackages;
    public String releaseStage;
    public boolean sendThreads = false;

    Collection<Callback> callbacks = new ArrayList<Callback>();
    Serializer serializer = new Serializer();
    private volatile boolean autoCaptureSessions;

    Configuration(String apiKey) {
        this.apiKey = apiKey;

        // Add built-in callbacks
        addCallback(new AppCallback(this));
        addCallback(new DeviceCallback());
        DeviceCallback.initializeCache();

        if (ServletCallback.isAvailable()) {
            addCallback(new ServletCallback());
        }
        sessionDelivery = new AsyncHttpDelivery();
        ((HttpDelivery) sessionDelivery).setEndpoint("https://sessions.bugsnag.com");
    }

    boolean shouldNotifyForReleaseStage() {
        if (notifyReleaseStages == null) {
            return true;
        }

        List<String> stages = Arrays.asList(notifyReleaseStages);
        return stages.contains(releaseStage);
    }

    boolean shouldIgnoreClass(String className) {
        if (ignoreClasses == null) {
            return false;
        }

        List<String> classes = Arrays.asList(ignoreClasses);
        return classes.contains(className);
    }

    void addCallback(Callback callback) {
        callbacks.add(callback);
    }

    boolean inProject(String className) {
        if (projectPackages != null) {
            for (String packageName : projectPackages) {
                if (packageName != null && className.startsWith(packageName)) {
                    return true;
                }
            }
        }

        return false;
    }

    public void setAutoCaptureSessions(boolean autoCaptureSessions) {
        this.autoCaptureSessions = autoCaptureSessions;
    }

    public boolean shouldAutoCaptureSessions() {
        return autoCaptureSessions;
    }

    Map<String, String> getErrorApiHeaders() {
        Map<String, String> map = new HashMap<String, String>();
        map.put(HEADER_API_PAYLOAD_VERSION, "4.0");
        map.put(HEADER_API_KEY, apiKey);
        map.put(HEADER_BUGSNAG_SENT_AT, DateUtils.toIso8601(new Date()));
        return map;
    }

    Map<String, String> getSessionApiHeaders() {
        Map<String, String> map = new HashMap<String, String>();
        map.put(HEADER_API_PAYLOAD_VERSION, "1.0");
        map.put(HEADER_API_KEY, apiKey);
        map.put(HEADER_BUGSNAG_SENT_AT, DateUtils.toIso8601(new Date()));
        return map;
    }
}

@@ -535,16 +535,66 @@
 til.Map;
+%0Aimport java.util.concurrent.atomic.AtomicBoolean;
 %0A%0Apublic
@@ -1024,16 +1024,42 @@
 Delivery
+ = new AsyncHttpDelivery()
 ;%0A    pu
@@ -1427,18 +1427,21 @@
 ate 
-volatile b
+final AtomicB
 oole
@@ -1462,16 +1462,38 @@
 Sessions
+ = new AtomicBoolean()
 ;%0A%0A    C
@@ -1824,59 +1824,8 @@
   %7D%0A
-        sessionDelivery = new AsyncHttpDelivery();%0A
     
@@ -2898,19 +2898,21 @@
 Sessions
- = 
+.set(
 autoCapt
@@ -2914,32 +2914,33 @@
 oCaptureSessions
+)
 ;%0A    %7D%0A%0A    pub
@@ -2977,24 +2977,24 @@
 essions() %7B%0A
-
         retu
@@ -3015,16 +3015,22 @@
 Sessions
+.get()
 ;%0A    %7D%0A

address review comments