package com.example.crystalgame.library.communication.abstraction;

import java.util.concurrent.LinkedBlockingQueue;

import com.example.crystalgame.library.communication.CommunicationFailureException;
import com.example.crystalgame.library.communication.CommunicationManager;
import com.example.crystalgame.library.communication.messages.Message;

/**
 * A Message queue
 * @author Balazs Pete, Rajan Verma
 *
 */
public class MessageQueue extends Thread {

	public static final int SLEEP_TIME = 5000;
	
	private CommunicationManager manager;
	private static LinkedBlockingQueue<MessageQueueElement> messageQueue;
	private boolean sendMessages = true;
	
	/**
	 * Create a message queue
	 * @param manager The Communication manager to use
	 */
	public MessageQueue(CommunicationManager manager) {
		this.manager = manager;
		messageQueue = new LinkedBlockingQueue<MessageQueue.MessageQueueElement>();
	}
	
	/**
	 * Add a message to send
	 * @param communicationId The ID of the communication channel to use
	 * @param message The message
	 * @return True of added
	 */
	public synchronized boolean put(String communicationId, Message message) {
		return put(new MessageQueueElement(communicationId, message));
	}
	
	private synchronized boolean put(MessageQueueElement element) {
		try {
			messageQueue.put(element);
		} catch (InterruptedException e) {
			System.err.println(e.getMessage());
			return false;
		}
		
		return true;
	}
	
	@Override
	public void run() {
		sendService();
	}
	
	/**
	 * Send the messages from the queue
	 */
	private void sendService() {
		while (sendMessages) {
			// Get the first message in the queue (block until message in queue)
			MessageQueueElement element = messageQueue.poll();
			if (element != null) {
				try {
					// try to send the data
					manager.sendData(element.communicationId, element.message);
				} catch (CommunicationFailureException e) {
					System.err.println(e.getMessage());
					boolean success = false;
					do {
						// Message failed to send, put it back on the queue
						success = put(element);
						try {
							// Let's sleep for a bit before we try to send a message again...
							sleep(SLEEP_TIME);
						} catch (InterruptedException e1) {
							System.err.println(e1.getMessage());
						}
					} while (!success);
				}
			}
		}
	}
	
	/**
	 * An element on the message queue
	 * @author Balazs Pete, Rajan Verma
	 *
	 */
	public class MessageQueueElement {
		
		public final String communicationId;
		public final Message message;
		
		public MessageQueueElement(String communicationId, Message message) {
			this.communicationId = communicationId;
			this.message = message;
		}
		
	}
}

@@ -109,16 +109,54 @@
 ngQueue;
+%0Aimport java.util.concurrent.TimeUnit;
 %0A%0Aimport
@@ -1734,28 +1734,224 @@
 t = 
-messageQueue.poll();
+null;%0A%09%09%09try %7B%0A%09%09%09%09element = messageQueue.poll(Long.MAX_VALUE, TimeUnit.MILLISECONDS);%0A%09%09%09%7D catch (InterruptedException e2) %7B%0A%09%09%09%09// Element is gonna be null, so we are going to handle it in the next step...%0A%09%09%09%7D%0A%09%09%09
 %0A%09%09%09
@@ -1962,17 +1962,17 @@
 element 
-!
+=
 = null) 
@@ -1974,16 +1974,122 @@
 ull) %7B%0A%09
+%09%09%09// Let's put the thread to sleep for a bit, then try again... %0A%09%09%09%09goToSleep();%0A%09%09%09%09continue;%0A%09%09%09%7D%0A%09%09%09%0A
 %09%09%09try %7B
@@ -2085,25 +2085,24 @@
 %09%09%0A%09%09%09try %7B%0A
-%09
 %09%09%09%09// try t
@@ -2117,17 +2117,16 @@
 he data%0A
-%09
 %09%09%09%09mana
@@ -2181,17 +2181,16 @@
 ssage);%0A
-%09
 %09%09%09%7D cat
@@ -2228,25 +2228,24 @@
 on e) %7B%0A%09%09%09%09
-%09
 System.err.p
@@ -2272,17 +2272,16 @@
 ));%0A%09%09%09%09
-%09
 boolean 
@@ -2305,15 +2305,13 @@
 %09%09%09%09
-%09
 do %7B%0A
-%09
 %09%09%09%09
@@ -2368,17 +2368,16 @@
 ue%0A%09%09%09%09%09
-%09
 success 
@@ -2396,22 +2396,8 @@
 t);%0A
-%09%09%09%09%09%09try %7B%0A%09%09
 %09%09%09%09
@@ -2467,16 +2467,104 @@
 ...%0A%09%09%09%09
+%09goToSleep();%0A%09%09%09%09%7D while (!success);%0A%09%09%09%7D%0A%09%09%7D%0A%09%7D%0A%09%0A%09private void goToSleep() %7B%0A%09%09try %7B%0A
 %09%09%09sleep
@@ -2577,20 +2577,16 @@
 _TIME);%0A
-%09%09%09%09
 %09%09%7D catc
@@ -2618,20 +2618,16 @@
 1) %7B%0A%09%09%09
-%09%09
-%09%09
 System.e
@@ -2659,52 +2659,8 @@
 ));%0A
-%09%09%09%09%09%09%7D%0A%09%09%09%09%09%7D while (!success);%0A%09%09%09%09%7D%0A%09%09%09%7D%0A
 %09%09%7D%0A

Fix CPU leak