package com.adsdk.sdk.video;

import static com.adsdk.sdk.Const.MAX_NUMBER_OF_TRACKING_RETRIES;

import java.lang.Thread.UncaughtExceptionHandler;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;
import java.util.Queue;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;

import com.adsdk.sdk.Const;
import com.adsdk.sdk.Log;

public class TrackerService {

	private static Object sLock = new Object();

	private static boolean sThreadRunning = false;

	private static Queue<TrackEvent> sTrackEvents = new LinkedList<TrackEvent>();

	private static Queue<TrackEvent> sRetryTrackEvents = new LinkedList<TrackEvent>();

	private static Thread sThread;

	private static boolean sStopped;

	public static void requestTrack(TrackEvent[] trackEvents) {
		synchronized (sLock) {
			for (TrackEvent trackEvent : trackEvents) {
				if (!sTrackEvents.contains(trackEvent)) {
					sTrackEvents.add(trackEvent);
				}
			}
			Log.d("Added track event:" + sTrackEvents.size());
		}
		if (!sThreadRunning) {
			startTracking();
		}
	}

	public static void requestTrack(TrackEvent trackEvent) {
		synchronized (sLock) {
			if (!sTrackEvents.contains(trackEvent)) {
				sTrackEvents.add(trackEvent);
			}
			Log.d("Added track event:" + sTrackEvents.size());
		}
		if (!sThreadRunning) {
			startTracking();
		}
	}

	public static void requestRetry(TrackEvent trackEvent) {
		synchronized (sLock) {
			if (!sRetryTrackEvents.contains(trackEvent)) {
				trackEvent.retries++;
				if (trackEvent.retries <= MAX_NUMBER_OF_TRACKING_RETRIES) {
					sRetryTrackEvents.add(trackEvent);
				}
			}
			Log.d("Added retry track event:" + sRetryTrackEvents.size());
		}
	}

	private static boolean hasMoreUpdates() {
		synchronized (sLock) {
			boolean hasMore = !sTrackEvents.isEmpty();
			Log.d("More updates:" + hasMore + " size:"
					+ sTrackEvents.size());
			return hasMore;
		}
	}

	private static TrackEvent getNextUpdate() {
		synchronized (sLock) {
			if (sTrackEvents.peek() == null) {
				return null;
			} else {
				TrackEvent nextTrackEvent = sTrackEvents.poll();
				return nextTrackEvent;
			}
		}
	}

	public static void startTracking() {

		synchronized (sLock) {
			if (!sThreadRunning) {
				sThreadRunning = true;
				sThread = new Thread(new Runnable() {

					@Override
					public void run() {
						sStopped = false;
						while (!sStopped) {
							while (hasMoreUpdates() && !sStopped) {
								TrackEvent event = getNextUpdate();
								Log.d("Sending tracking :" + event.url
										+ " Time:"
										+ event.timestamp
										+ " Events left:"
										+ sTrackEvents.size());
								if (event == null)
									continue;
								URL u = null;
								try {
									u = new URL(event.url.trim());
								} catch (MalformedURLException e) {
									Log.d("Wrong tracking url:"
											+ event.url);
									continue;
								}

								Log.d("Sending conversion Request");
								Log.d("Perform tracking HTTP Get Url: "
										+ event.url);
								DefaultHttpClient client = new DefaultHttpClient();
								HttpConnectionParams.setSoTimeout(
										client.getParams(),
										Const.SOCKET_TIMEOUT);
								HttpConnectionParams.setConnectionTimeout(
										client.getParams(),
										Const.CONNECTION_TIMEOUT);
								HttpGet get = new HttpGet(u.toString());
								get.setHeader("User-Agent", System.getProperty("http.agent"));
								HttpResponse response;
								try {
									response = client.execute(get);
									if (response.getStatusLine()
											.getStatusCode() != HttpURLConnection.HTTP_OK) {
										requestRetry(event);
									} else {
										Log.d("Tracking OK");
									}
								} catch (Throwable t) {
									requestRetry(event);
								}

							}
							if ((!sStopped) && (!sRetryTrackEvents.isEmpty())) {
								try {
									Thread.sleep(30000);
								} catch (Exception e) {

								}
								synchronized (sLock) {
									sTrackEvents.addAll(sRetryTrackEvents);
									sRetryTrackEvents.clear();
								}
							} else {
								sStopped = true;
							}
						}
						sStopped = false;
						sThreadRunning = false;
						sThread = null;
					}
				});
				sThread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {

					@Override
					public void uncaughtException(Thread thread, Throwable ex) {
						sThreadRunning = false;
						sThread = null;
						startTracking();
					}
				});
				sThread.start();
			}
		}
	}

	public static void release() {
		Log.v("release");
		if (sThread != null) {
			Log.v("release stopping Tracking events thread");
			sStopped = true;
		}
	}

}

@@ -90,16 +90,61 @@
 TRIES;%0A%0A
+import java.io.UnsupportedEncodingException;%0A
 import j
@@ -240,50 +240,18 @@
 net.
-MalformedURLException;%0Aimport java.net.URL
+URLEncoder
 ;%0Aim
@@ -2027,22 +2027,17 @@
 %22 size:%22
-%0A%09%09%09%09%09
+ 
 + sTrack
@@ -2862,19 +2862,22 @@
 %09%09%09%09%09%09%09%09
-URL
+String
  u = nul
@@ -2910,15 +2910,25 @@
 u = 
-new URL
+URLEncoder.encode
 (eve
@@ -2940,16 +2940,24 @@
 l.trim()
+,%22UTF-8%22
 );%0A%09%09%09%09%09
@@ -2972,20 +2972,27 @@
 ch (
-MalformedURL
+UnsupportedEncoding
 Exce
@@ -3085,32 +3085,40 @@
 inue;%0A%09%09%09%09%09%09%09%09%7D%0A
+%09%09%09%09%09%09%09%09
 %0A%09%09%09%09%09%09%09%09Log.d(%22
@@ -3495,32 +3495,34 @@
 CTION_TIMEOUT);%0A
+%09%0A
 %09%09%09%09%09%09%09%09HttpGet 
@@ -3544,21 +3544,12 @@
 et(u
-.toString()
 );
+%0A%09
 %0A%09%09%09

Correct URL encoding in tracker.