package org.apps8os.trafficsense.pebble;


import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import com.getpebble.android.kit.PebbleKit;
import com.getpebble.android.kit.util.PebbleDictionary;

import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

public class MessageManager implements Runnable {
    public Handler messageHandler;
    private final BlockingQueue<PebbleDictionary> messageQueue = new LinkedBlockingQueue<PebbleDictionary>();
    private Boolean isMessagePending = Boolean.valueOf(false);
    private Context mContext;
    private UUID mUUID;
    private Looper threadLooper;
    
    public MessageManager(Context context, UUID uuid) {
    	mContext = context;
    	mUUID = uuid;
    }
    
    @Override
    public void run() {
        Looper.prepare();
        threadLooper = Looper.myLooper();
        messageHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
            	// My guess is that this method should be never used and thus it sends the following message to log
                Log.w(this.getClass().getSimpleName(), "Please post() your blocking runnables to Mr Manager, " +
                        "don't use sendMessage()");
            }

        };
        // Start a loop, so the thread won't quit immediately.
        Looper.loop();
    }

    private void consumeAsync() {
        messageHandler.post(new Runnable() {
            @Override
            public void run() {
                synchronized (isMessagePending) {
                    if (isMessagePending.booleanValue()) {
                        return;
                    }

                    synchronized (messageQueue) {
                        if (messageQueue.size() == 0) {
                            return;
                        }
                        
                        PebbleKit.sendDataToPebble(mContext.getApplicationContext(), mUUID, messageQueue.peek());
                    }

                    isMessagePending = Boolean.valueOf(true);
                }
            }
        });
    }

    public void notifyAckReceivedAsync() {
        messageHandler.post(new Runnable() {
            @Override
            public void run() {
                synchronized (isMessagePending) {
                    isMessagePending = Boolean.valueOf(false);
                }
                //Log.i("Pebble", "Received ack from stop: " + messageQueue.peek().toString());
                //TODO: I guess this is about fragmentation
                if (messageQueue.isEmpty() == false)
                	messageQueue.remove();
            }
        });
        consumeAsync();
    }

    public void notifyNackReceivedAsync() {
        messageHandler.post(new Runnable() {
            @Override
            public void run() {
                synchronized (isMessagePending) {
                    isMessagePending = Boolean.valueOf(false);
                }
            }
        });
        consumeAsync();
    }

    public boolean offer(final PebbleDictionary data) {
    	/**
    	 * This method should be used for adding a new message to the queue.
    	 * Call this whenever you need to send a message to the Pebble app.
    	 */
        final boolean success = messageQueue.offer(data);

        if (success) {
            consumeAsync();
        }

        return success;
    }
    
    public void stop() {
    	if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 ) {
    		threadLooper.quitSafely();
    	} else {
    		threadLooper.quit();
    	}
    }
}

@@ -1526,36 +1526,33 @@
 meAsync() %7B%0A    
-    
+%09
 messageHandler.p
@@ -1572,32 +1572,26 @@
 ble() %7B%0A    
-        
+%09%09
 @Override%0A  
@@ -1588,32 +1588,26 @@
 verride%0A    
-        
+%09%09
 public void 
@@ -1614,36 +1614,27 @@
 run() %7B%0A    
-            
+%09%09%09
 synchronized
@@ -1639,48 +1639,24 @@
 ed (
-isMessagePending) %7B%0A                    
+this) %7B%0A    %09%09%09%09
 if (
@@ -1698,133 +1698,39 @@
     
-                    return;%0A                    %7D%0A%0A                    synchronized (messageQueue) %7B%0A                        
+%09%09%09%09%09return;%0A    %09%09%09%09%7D%0A    %09%09%09%09
 if (
@@ -1765,32 +1765,13 @@
     
-                        
+%09%09%09%09%09
 retu
@@ -1782,79 +1782,22 @@
     
-  
-                  %7D%0A                        %0A                        
+%09%09%09%09%7D%0A    %09%09%09%09
 Pebb
@@ -1890,47 +1890,12 @@
     
-                %7D%0A%0A                    
+%09%09%09%09
 isMe
@@ -1940,44 +1940,26 @@
     
-            %7D%0A            
+%09%09%09%7D%0A    %09%09
 %7D%0A    
- 
-   
+%09
 %7D);%0A
@@ -2111,36 +2111,33 @@
 ) %7B%0A            
-    
+%09
 synchronized (is
@@ -2138,33 +2138,16 @@
 ed (
-isMessagePending) %7B%0A     
+this) %7B%0A
     
@@ -2146,35 +2146,34 @@
 ) %7B%0A            
-   
+%09%09
 isMessagePending
@@ -2215,30 +2215,10 @@
     
-    %7D%0A                
+%09%09
 //Lo
@@ -2305,20 +2305,18 @@
         
-    
+%09%09
 //TODO: 
@@ -2359,28 +2359,26 @@
             
-    
+%09%09
 if (messageQ
@@ -2414,20 +2414,34 @@
         
-    
+%09%09%7B%0A            %09%09
 %09message
@@ -2452,24 +2452,55 @@
 e.remove();%0A
+            %09%09%7D%0A            %09%7D%0A
             
@@ -2699,20 +2699,17 @@
         
-    
+%09
 synchron
@@ -2714,32 +2714,20 @@
 onized (
+th
 is
-MessagePending
 ) %7B%0A    
@@ -2734,24 +2734,18 @@
         
-        
+%09%09
 isMessag
@@ -2783,36 +2783,33 @@
 e);%0A            
-    
+%09
 %7D%0A            %7D%0A

refine Pebble MessageManager syncronisation