package com.bortbort.arduino.FiloFirmata;

import com.bortbort.arduino.FiloFirmata.Messages.Message;
import net.jodah.typetools.TypeResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * SynchronousMessageListener
 * Turns an async design for listening and sending messages into a synchronous design allowing
 * a message to be sent with the return value being the response message.
 */
abstract class SynchronousMessageListener<T extends Message> extends MessageListener<T> {
    private static final Logger log = LoggerFactory.getLogger(SynchronousMessageListener.class);
    private static final int RESPONSE_WAIT_TIME = 5000;
    private T responseMessage;
    private Boolean responseReceived = null;
    private final Object lock = new Object();

    @Override
    public void messageReceived(T message) {
        if (responseReceived != null && responseReceived) {
            log.warn("Received more than one synchronous message reply!");
        }

        if (responseReceived == null) {
            responseMessage = message;
            responseReceived = true;
        }

        synchronized (lock) {
            lock.notify();
        }
    }

    public Boolean getResponseReceived() {
        return responseReceived;
    }

    public Boolean waitForResponse() {
        if (responseReceived != null) {
            return responseReceived;
        }
        
        synchronized (lock) {
            try {
                lock.wait(RESPONSE_WAIT_TIME);
            } catch (InterruptedException e) {
                log.warn("Interrupted waiting for synchronous response.");
            }
        }

        if (responseReceived == null) {
            log.warn("Timed out waiting for synchronous response.");
            responseReceived = false;
        }

        return responseReceived;
    }

    public T getResponseMessage() {
        waitForResponse();
        return responseMessage;
    }

}


@@ -98,49 +98,8 @@
 ge;%0A
-import net.jodah.typetools.TypeResolver;%0A
 impo
@@ -725,16 +725,427 @@
 ect();%0A%0A
+    /**%0A     * When we get our expected message response. Save the message object, and notify the waiting thread%0A     * that the message is now available to be passed back.%0A     * This method attempts to handle and warn against cases where multiple messages came in, or a message%0A     * came in after the timeout period.%0A     * @param message Message response from the project board that will be saved.%0A     */%0A
     @Ove
@@ -1235,12 +1235,28 @@
 null
- && 
+) %7B%0A            if (
 resp
@@ -1267,24 +1267,28 @@
 Received) %7B%0A
+    
             
@@ -1362,55 +1362,136 @@
     
-%7D%0A%0A        if (responseReceived == null) %7B%0A    
+    %7D%0A            else %7B%0A                log.warn(%22Received response message after timeout was hit!%22);%0A            %7D%0A        %7D%0A%0A
     
@@ -1521,36 +1521,32 @@
 essage;%0A        
-    
 responseReceived
@@ -1553,26 +1553,16 @@
  = true;
-%0A        %7D
 %0A%0A      
@@ -1637,86 +1637,665 @@
     
-public Boolean getResponseReceived() %7B%0A        return responseReceived;%0A    %7D%0A
+/**%0A     * Check if there has been a response from the project board with our expected message.%0A     * @return True if response received. False if not. Null if we have not started waiting yet,%0A     *   or are in the process of still waiting.%0A     */%0A    public Boolean getResponseReceived() %7B%0A        return responseReceived;%0A    %7D%0A%0A    /**%0A     * Wait/Block for a specific response message from the project board. This will block for up to 5 seconds%0A     *   waiting for a reply message matching the given class T.%0A     * @return True if the response came through while waiting. False if the timeout was hit while waiting%0A     *   for the response.%0A     */
 %0A   
@@ -2417,24 +2417,16 @@
       %7D%0A
-        
 %0A       
@@ -2854,24 +2854,302 @@
 ved;%0A    %7D%0A%0A
+    /**%0A     * Get the response message that was sent up by the project board. Auto casts to the correct specific%0A     * class type that was used when implementing this class.%0A     * @return T Message type object holding the response message the client was waiting for.%0A     */%0A
     public T

Add comments to SynchronousMessageListener.