// Path: app/src/main/java/com/jilk/ros/ROSClient.java
// public abstract class ROSClient {
// 
//     public ROSClient() {}
//     
//     public static ROSClient create(String uriString) {
//         // if we ever implement other ROSClient types, we'll key off the URI protocol (e.g., ws://)
//         // we'd also have to abstract out Topic and Service since they depend on the ROSBridge operations
//         return new ROSBridgeClient(uriString);
//     }
//     
//     public abstract boolean connect();
//     public abstract boolean connect(ConnectionStatusListener listener);
//     public abstract void disconnect();
//     public abstract void send(Operation operation);
//     public abstract void send(String json);
//     public abstract void register(Class<? extends Operation> c,
//             String s,
//             Class<? extends Message> m,
//             FullMessageHandler h);
//     public abstract void unregister(Class<? extends Operation> c, String s);
//     public abstract void setDebug(boolean debug);
//     public abstract String[] getNodes() throws InterruptedException;
//     public abstract String[] getTopics() throws InterruptedException;
//     public abstract String[] getServices() throws InterruptedException;
//     public abstract TypeDef getTopicMessageDetails(String topic) throws InterruptedException;
//     public abstract TypeDef[] getTopicMessageList(String topic) throws InterruptedException;
//     public abstract TypeDef getServiceRequestDetails(String service) throws InterruptedException;
//     public abstract TypeDef[] getServiceRequestList(String service) throws InterruptedException;
//     public abstract TypeDef getServiceResponseDetails(String service) throws InterruptedException;
//     public abstract TypeDef[] getServiceResponseList(String service) throws InterruptedException;
//     public abstract TypeDef getTypeDetails(String type) throws InterruptedException;
//     public abstract TypeDef[] getTypeList(String type) throws InterruptedException;
//     public abstract void typeMatch(TypeDef t, Class<? extends Message> c) throws InterruptedException; 
//     public abstract Object getUnderlyingClient(); // for debugging
//     
//     public interface ConnectionStatusListener {
//         public void onConnect();
//         public void onDisconnect(boolean normal, String reason, int code);
//         public void onError(Exception ex);
//     }
// }
// 
// Path: app/src/main/java/com/jilk/ros/rosbridge/FullMessageHandler.java
// public interface FullMessageHandler<T extends Message> {
//     public void onMessage(String id, T message);
// }
// 
// Path: app/src/main/java/com/jilk/ros/rosbridge/operation/Publish.java
// @MessageType(string = "publish")
// public class Publish extends Operation {
//     
//     @Indicator public String topic;
//     @Indicated
//     public Message msg;
//     
//     public Publish() {}
//     
//     public Publish(String topic, Message msg) {
//         this.topic = topic;
//         this.msg = msg;
//     }
// }
// 
// Path: app/src/main/java/com/jilk/ros/rosbridge/operation/ServiceResponse.java
// @MessageType(string = "service_response")
// public class ServiceResponse extends Operation {
//     @Indicator public String service;
//     public boolean result;
//     @Indicated public Message values;
// 
//     public ServiceResponse() {}
//     
//     public ServiceResponse(String service) {
//         this.service = service;
//     }    
// }
// 
// Path: app/src/main/java/cn/ac/iscas/xlab/droidfacedog/entity/PublishEvent.java
// public class PublishEvent {
//     public String msg;
//     public String id;
//     public String name;
//     public String op;
// 
// 
//     public PublishEvent(Operation operation,String name, String content) {
//         if(operation != null) {
//             id = operation.id;
//             op = operation.op;
//         }
//         this.name = name;
//         msg = content;
//     }
// 
//     // FIXME: maybe toLogcat() is more accurate?
//     public String toString() {
//         return "{msg: '" + msg + "', id: '" + id + "', name: '"
//                 + name + "', op: '" + op + "'}";
//     }
// }


import com.jilk.ros.ROSClient;
import com.jilk.ros.message.Message;
import com.jilk.ros.rosbridge.FullMessageHandler;
import com.jilk.ros.rosbridge.operation.Operation;
import com.jilk.ros.rosbridge.operation.Publish;
import com.jilk.ros.rosbridge.operation.ServiceResponse;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.framing.CloseFrame;
import org.java_websocket.handshake.ServerHandshake;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.lang.reflect.Field;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.channels.SocketChannel;
import cn.ac.iscas.xlab.droidfacedog.entity.PublishEvent;
import de.greenrobot.event.EventBus;
    }
    
    public void setListener(ROSClient.ConnectionStatusListener listener) {
        this.listener = listener;
    }

    @Override
    public void onOpen(ServerHandshake handshakedata) {
        if (listener != null)
            listener.onConnect();
    }

    @Override
    public void onMessage(String message) {
        if (debug) System.out.println("<ROS " + message);
        //System.out.println("ROSBridgeWebSocketClient.onMessage (message): " + message);
        Operation operation = Operation.toOperation(message, classes);
        //System.out.println("ROSBridgeWebSocketClient.onMessage (operation): ");
        //operation.print();
        
        FullMessageHandler handler = null;
        Message msg = null;
        if (operation instanceof Publish) {
            Publish p = (Publish) operation;
            handler = handlers.lookup(Publish.class, p.topic);
            msg = p.msg;
        }
        else if (operation instanceof ServiceResponse) {
            ServiceResponse r = ((ServiceResponse) operation);
            handler = handlers.lookup(ServiceResponse.class, r.service);
// Path: app/src/main/java/com/jilk/ros/ROSClient.java
// public abstract class ROSClient {
// 
//     public ROSClient() {}
//     
//     public static ROSClient create(String uriString) {
//         // if we ever implement other ROSClient types, we'll key off the URI protocol (e.g., ws://)
//         // we'd also have to abstract out Topic and Service since they depend on the ROSBridge operations
//         return new ROSBridgeClient(uriString);
//     }
//     
//     public abstract boolean connect();
//     public abstract boolean connect(ConnectionStatusListener listener);
//     public abstract void disconnect();
//     public abstract void send(Operation operation);
//     public abstract void send(String json);
//     public abstract void register(Class<? extends Operation> c,
//             String s,
//             Class<? extends Message> m,
//             FullMessageHandler h);
//     public abstract void unregister(Class<? extends Operation> c, String s);
//     public abstract void setDebug(boolean debug);
//     public abstract String[] getNodes() throws InterruptedException;
//     public abstract String[] getTopics() throws InterruptedException;
//     public abstract String[] getServices() throws InterruptedException;
//     public abstract TypeDef getTopicMessageDetails(String topic) throws InterruptedException;
//     public abstract TypeDef[] getTopicMessageList(String topic) throws InterruptedException;
//     public abstract TypeDef getServiceRequestDetails(String service) throws InterruptedException;
//     public abstract TypeDef[] getServiceRequestList(String service) throws InterruptedException;
//     public abstract TypeDef getServiceResponseDetails(String service) throws InterruptedException;
//     public abstract TypeDef[] getServiceResponseList(String service) throws InterruptedException;
//     public abstract TypeDef getTypeDetails(String type) throws InterruptedException;
//     public abstract TypeDef[] getTypeList(String type) throws InterruptedException;
//     public abstract void typeMatch(TypeDef t, Class<? extends Message> c) throws InterruptedException; 
//     public abstract Object getUnderlyingClient(); // for debugging
//     
//     public interface ConnectionStatusListener {
//         public void onConnect();
//         public void onDisconnect(boolean normal, String reason, int code);
//         public void onError(Exception ex);
//     }
// }
// 
// Path: app/src/main/java/com/jilk/ros/rosbridge/FullMessageHandler.java
// public interface FullMessageHandler<T extends Message> {
//     public void onMessage(String id, T message);
// }
// 
// Path: app/src/main/java/com/jilk/ros/rosbridge/operation/Publish.java
// @MessageType(string = "publish")
// public class Publish extends Operation {
//     
//     @Indicator public String topic;
//     @Indicated
//     public Message msg;
//     
//     public Publish() {}
//     
//     public Publish(String topic, Message msg) {
//         this.topic = topic;
//         this.msg = msg;
//     }
// }
// 
// Path: app/src/main/java/com/jilk/ros/rosbridge/operation/ServiceResponse.java
// @MessageType(string = "service_response")
// public class ServiceResponse extends Operation {
//     @Indicator public String service;
//     public boolean result;
//     @Indicated public Message values;
// 
//     public ServiceResponse() {}
//     
//     public ServiceResponse(String service) {
//         this.service = service;
//     }    
// }
// 
// Path: app/src/main/java/cn/ac/iscas/xlab/droidfacedog/entity/PublishEvent.java
// public class PublishEvent {
//     public String msg;
//     public String id;
//     public String name;
//     public String op;
// 
// 
//     public PublishEvent(Operation operation,String name, String content) {
//         if(operation != null) {
//             id = operation.id;
//             op = operation.op;
//         }
//         this.name = name;
//         msg = content;
//     }
// 
//     // FIXME: maybe toLogcat() is more accurate?
//     public String toString() {
//         return "{msg: '" + msg + "', id: '" + id + "', name: '"
//                 + name + "', op: '" + op + "'}";
//     }
// }


// Path: app/src/main/java/com/jilk/ros/rosbridge/implementation/ROSBridgeWebSocketClient.java
import com.jilk.ros.ROSClient;
import com.jilk.ros.message.Message;
import com.jilk.ros.rosbridge.FullMessageHandler;
import com.jilk.ros.rosbridge.operation.Operation;
import com.jilk.ros.rosbridge.operation.Publish;
import com.jilk.ros.rosbridge.operation.ServiceResponse;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.framing.CloseFrame;
import org.java_websocket.handshake.ServerHandshake;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.lang.reflect.Field;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.channels.SocketChannel;
import cn.ac.iscas.xlab.droidfacedog.entity.PublishEvent;
import de.greenrobot.event.EventBus;

    }
    
    public void setListener(ROSClient.ConnectionStatusListener listener) {
        this.listener = listener;
    }

    @Override
    public void onOpen(ServerHandshake handshakedata) {
        if (listener != null)
            listener.onConnect();
    }

    @Override
    public void onMessage(String message) {
        if (debug) System.out.println("<ROS " + message);
        //System.out.println("ROSBridgeWebSocketClient.onMessage (message): " + message);
        Operation operation = Operation.toOperation(message, classes);
        //System.out.println("ROSBridgeWebSocketClient.onMessage (operation): ");
        //operation.print();
        
        FullMessageHandler handler = null;
        Message msg = null;
        if (operation instanceof Publish) {
            Publish p = (Publish) operation;
            handler = handlers.lookup(Publish.class, p.topic);
            msg = p.msg;
        }
        else if (operation instanceof ServiceResponse) {
            ServiceResponse r = ((ServiceResponse) operation);
            handler = handlers.lookup(ServiceResponse.class, r.service);
            msg = r.values;