package com.woopra.java.sdk;

import com.woopra.json.JSONException;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Woopra Java SDK This class enables back-end tracking in Java for Woopra. Even
 * though the getInstance is implemented for this class, note that the design of
 * this object is such that a new instance should be created for each new
 * request.
 *
 * @author Antoine Chkaiban
 * @version 2013-09-30
 */
public class WoopraTracker {

    private static final String SDK_ID = "java";
    protected static int defaultTimeout = 300 * 1000;
    private static final Map<String, WoopraTracker> instances = new ConcurrentHashMap();
    /**
     *
     */
    private final String domain;
    private int idleTimeout;

    /**
     * If an instance of WoopraTracker already exists, this method returns it.
     * It creates a new instance otherwise.
     *
     * @param domain
     * @return WoopraTracker
     */
    public synchronized final static WoopraTracker getInstance(String domain) {
        WoopraTracker instance = WoopraTracker.instances.get(domain);
        if (instance != null) {
            return instance;
        } else {
            instance = new WoopraTracker(domain);
            WoopraTracker.instances.put(domain, instance);
            return instance;
        }
    }

    /**
     * Public Constructor
     *
     * @param domain
     */
    public WoopraTracker(String domain) {
        this.domain = domain;
        this.idleTimeout = WoopraTracker.defaultTimeout;
    }

    /**
     * Tracks a custom event through the back-end.
     *
     * @param visitor
     * @param event	(WoopraEvent) the event to track
     */
    public void track(WoopraVisitor visitor, WoopraEvent event) {
        if (visitor != null && event != null) {
            this.woopraHttpRequest(event, visitor);
        }
    }

    /**
     * Pushes the identified user to Woopra through the back-end. Please note
     * that the identified user is automatically pushed with any tracking event.
     * Therefore, this method is useful if you need to identify a user without
     * tracking any event.
     *
     * @param visitor
     */
    public void push(WoopraVisitor visitor) {
        if (visitor != null) {
            this.woopraHttpRequest(null, visitor);
        }
    }

    /**
     * Set the value of the idle timeout (time in milliseconds after which the
     * user is considered offline)
     *
     * @param idleTimeout
     */
    public void setIdleTimeout(int idleTimeout) {
        this.idleTimeout = idleTimeout;
    }

    private void woopraHttpRequest(WoopraEvent event, WoopraVisitor visitor) {
        try {
            String baseUrl = "http://www.woopra.com/track/";
            String configParams = "?host=".concat(URLEncoder.encode((String) this.domain, "UTF-8"));
            configParams = configParams.concat("&cookie=").concat(URLEncoder.encode(visitor.getCookieValue(), "UTF-8"));
            if (!visitor.getIpAddress().equals("")) {
                configParams = configParams.concat("&ip=").concat(URLEncoder.encode(visitor.getIpAddress(), "UTF-8"));
            }
            configParams = configParams.concat("&timeout=").concat(URLEncoder.encode(String.valueOf(this.idleTimeout), "UTF-8"));
            String userParams = "";
            Iterator<String> userKeys = visitor.properties.keySet().iterator();
            while (userKeys.hasNext()) {
                String key = userKeys.next();
                String value = visitor.properties.get(key).toString();
                System.out.println(key.concat(" : ").concat(value));
                userParams = userParams.concat("&cv_").concat(URLEncoder.encode(key, "UTF-8")).concat("=").concat(URLEncoder.encode(value, "UTF-8"));
            }
            String url;
            if (event == null) {
                url = baseUrl.concat("identify/").concat(configParams).concat(userParams).concat("&ce_app=").concat(WoopraTracker.SDK_ID);
            } else {
                String eventParams = "";
                eventParams = eventParams.concat("&ce_name=").concat(URLEncoder.encode(event.name, "UTF-8"));
                @SuppressWarnings("unchecked")
                Iterator<String> eventKeys = event.properties.keys();
                while (eventKeys.hasNext()) {
                    String key = eventKeys.next();
                    String value = event.properties.get(key).toString();
                    eventParams = eventParams.concat("&ce_").concat(URLEncoder.encode(key, "UTF-8")).concat("=").concat(URLEncoder.encode(value, "UTF-8"));
                }
                url = baseUrl.concat("ce/").concat(configParams).concat(userParams).concat(eventParams).concat("&ce_app=").concat(WoopraTracker.SDK_ID);
            }

            HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
            conn.setRequestMethod("GET");

            conn.setConnectTimeout(4000);
            conn.setReadTimeout(6000);

            if (visitor.getUserAgent().equals("") == false) {
                conn.addRequestProperty("User-Agent", visitor.getUserAgent());
            }

            InputStream in = conn.getInputStream();
            in.read();
            in.close();

        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

@@ -240,16 +240,41 @@
 ncoder;%0A
+import java.util.Base64;%0A
 import j
@@ -292,16 +292,16 @@
 erator;%0A
-
 import j
@@ -980,16 +980,149 @@
 meout;%0A%0A
+    /**%0A     *%0A     */%0A    private boolean httpAuthEnable = false;%0A    private String httpAuthUser = null, httpAuthPassword = null;%0A%0A
     /**%0A
@@ -2941,24 +2941,337 @@
 out;%0A    %7D%0A%0A
+    /**%0A     *%0A     * @param user%0A     * @param password%0A     */%0A    public void enableBasicAuth(String user, String password) %7B%0A        this.httpAuthEnable = true;%0A        this.httpAuthUser = user;%0A        this.httpAuthPassword = password;%0A    %7D%0A%0A    /**%0A     *%0A     * @param event%0A     * @param visitor%0A     */%0A
     private 
@@ -5539,24 +5539,24 @@
 nnection();%0A
-
             
@@ -5582,24 +5582,245 @@
 od(%22GET%22);%0A%0A
+            if (this.httpAuthEnable) %7B%0A                conn.setRequestProperty(%22Authorization%22, %22Basic %22 + Base64.getEncoder().encodeToString((this.httpAuthUser + %22:%22 + this.httpAuthPassword).getBytes()));%0A            %7D%0A%0A
             

enable http basic auth in tracker