// Path: WebRTCSample/app/src/org/appspot/apprtcstandalone/RoomParametersFetcher.java
// public interface RoomParametersFetcherEvents {
//   /**
//    * Callback fired once the room's signaling parameters
//    * SignalingParameters are extracted.
//    */
//   void onSignalingParametersReady(final SignalingParameters params);
// 
//   /**
//    * Callback for room parameters extraction error.
//    */
//   void onSignalingParametersError(final String description);
// }
// 
// Path: WebRTCSample/app/src/org/appspot/apprtcstandalone/WebSocketChannelClient.java
// public interface WebSocketChannelEvents {
//   void onWebSocketMessage(final String message);
//   void onWebSocketClose();
//   void onWebSocketError(final String description);
// }
// 
// Path: WebRTCSample/app/src/org/appspot/apprtcstandalone/WebSocketChannelClient.java
// public enum WebSocketConnectionState { NEW, CONNECTED, REGISTERED, CLOSED, ERROR }
// 
// Path: WebRTCSample/app/src/org/appspot/apprtcstandalone/util/AsyncHttpURLConnection.java
// public class AsyncHttpURLConnection {
//   private static final int HTTP_TIMEOUT_MS = 8000;
//   private static final String HTTP_ORIGIN = "https://appr.tc";
//   private final String method;
//   private final String url;
//   private final String message;
//   private final AsyncHttpEvents events;
//   private String contentType;
// 
//   /**
//    * Http requests callbacks.
//    */
//   public interface AsyncHttpEvents {
//     void onHttpError(String errorMessage);
//     void onHttpComplete(String response);
//   }
// 
//   public AsyncHttpURLConnection(String method, String url, String message, AsyncHttpEvents events) {
//     this.method = method;
//     this.url = url;
//     this.message = message;
//     this.events = events;
//   }
// 
//   public void setContentType(String contentType) {
//     this.contentType = contentType;
//   }
// 
//   public void send() {
//     new Thread(this ::sendHttpMessage).start();
//   }
// 
//   private void sendHttpMessage() {
//     try {
//       HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
//       byte[] postData = new byte[0];
//       if (message != null) {
//         postData = message.getBytes("UTF-8");
//       }
//       connection.setRequestMethod(method);
//       connection.setUseCaches(false);
//       connection.setDoInput(true);
//       connection.setConnectTimeout(HTTP_TIMEOUT_MS);
//       connection.setReadTimeout(HTTP_TIMEOUT_MS);
//       // TODO(glaznev) - query request origin from pref_room_server_url_key preferences.
//       connection.addRequestProperty("origin", HTTP_ORIGIN);
//       boolean doOutput = false;
//       if (method.equals("POST")) {
//         doOutput = true;
//         connection.setDoOutput(true);
//         connection.setFixedLengthStreamingMode(postData.length);
//       }
//       if (contentType == null) {
//         connection.setRequestProperty("Content-Type", "text/plain; charset=utf-8");
//       } else {
//         connection.setRequestProperty("Content-Type", contentType);
//       }
// 
//       // Send POST request.
//       if (doOutput && postData.length > 0) {
//         OutputStream outStream = connection.getOutputStream();
//         outStream.write(postData);
//         outStream.close();
//       }
// 
//       // Get response.
//       int responseCode = connection.getResponseCode();
//       if (responseCode != 200) {
//         events.onHttpError("Non-200 response to " + method + " to URL: " + url + " : "
//             + connection.getHeaderField(null));
//         connection.disconnect();
//         return;
//       }
//       InputStream responseStream = connection.getInputStream();
//       String response = drainStream(responseStream);
//       responseStream.close();
//       connection.disconnect();
//       events.onHttpComplete(response);
//     } catch (SocketTimeoutException e) {
//       events.onHttpError("HTTP " + method + " to " + url + " timeout");
//     } catch (IOException e) {
//       events.onHttpError("HTTP " + method + " to " + url + " error: " + e.getMessage());
//     }
//   }
// 
//   // Return the contents of an InputStream as a String.
//   private static String drainStream(InputStream in) {
//     Scanner s = new Scanner(in, "UTF-8").useDelimiter("\\A");
//     return s.hasNext() ? s.next() : "";
//   }
// }
// 
// Path: WebRTCSample/app/src/org/appspot/apprtcstandalone/util/AsyncHttpURLConnection.java
// public interface AsyncHttpEvents {
//   void onHttpError(String errorMessage);
//   void onHttpComplete(String response);
// }


import javax.annotation.Nullable;
import org.appspot.apprtcstandalone.RoomParametersFetcher.RoomParametersFetcherEvents;
import org.appspot.apprtcstandalone.WebSocketChannelClient.WebSocketChannelEvents;
import org.appspot.apprtcstandalone.WebSocketChannelClient.WebSocketConnectionState;
import org.appspot.apprtcstandalone.util.AsyncHttpURLConnection;
import org.appspot.apprtcstandalone.util.AsyncHttpURLConnection.AsyncHttpEvents;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.webrtc.IceCandidate;
import org.webrtc.SessionDescription;
    Log.e(TAG, errorMessage);
    handler.post(new Runnable() {
      @Override
      public void run() {
        if (roomState != ConnectionState.ERROR) {
          roomState = ConnectionState.ERROR;
          events.onChannelError(errorMessage);
        }
      }
    });
  }

  // Put a |key|->|value| mapping in |json|.
  private static void jsonPut(JSONObject json, String key, Object value) {
    try {
      json.put(key, value);
    } catch (JSONException e) {
      throw new RuntimeException(e);
    }
  }

  // Send SDP or ICE candidate to a room server.
  private void sendPostMessage(
      final MessageType messageType, final String url, @Nullable final String message) {
    String logInfo = url;
    if (message != null) {
      logInfo += ". Message: " + message;
    }
    Log.d(TAG, "C->GAE: " + logInfo);
    AsyncHttpURLConnection httpConnection =
// Path: WebRTCSample/app/src/org/appspot/apprtcstandalone/RoomParametersFetcher.java
// public interface RoomParametersFetcherEvents {
//   /**
//    * Callback fired once the room's signaling parameters
//    * SignalingParameters are extracted.
//    */
//   void onSignalingParametersReady(final SignalingParameters params);
// 
//   /**
//    * Callback for room parameters extraction error.
//    */
//   void onSignalingParametersError(final String description);
// }
// 
// Path: WebRTCSample/app/src/org/appspot/apprtcstandalone/WebSocketChannelClient.java
// public interface WebSocketChannelEvents {
//   void onWebSocketMessage(final String message);
//   void onWebSocketClose();
//   void onWebSocketError(final String description);
// }
// 
// Path: WebRTCSample/app/src/org/appspot/apprtcstandalone/WebSocketChannelClient.java
// public enum WebSocketConnectionState { NEW, CONNECTED, REGISTERED, CLOSED, ERROR }
// 
// Path: WebRTCSample/app/src/org/appspot/apprtcstandalone/util/AsyncHttpURLConnection.java
// public class AsyncHttpURLConnection {
//   private static final int HTTP_TIMEOUT_MS = 8000;
//   private static final String HTTP_ORIGIN = "https://appr.tc";
//   private final String method;
//   private final String url;
//   private final String message;
//   private final AsyncHttpEvents events;
//   private String contentType;
// 
//   /**
//    * Http requests callbacks.
//    */
//   public interface AsyncHttpEvents {
//     void onHttpError(String errorMessage);
//     void onHttpComplete(String response);
//   }
// 
//   public AsyncHttpURLConnection(String method, String url, String message, AsyncHttpEvents events) {
//     this.method = method;
//     this.url = url;
//     this.message = message;
//     this.events = events;
//   }
// 
//   public void setContentType(String contentType) {
//     this.contentType = contentType;
//   }
// 
//   public void send() {
//     new Thread(this ::sendHttpMessage).start();
//   }
// 
//   private void sendHttpMessage() {
//     try {
//       HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
//       byte[] postData = new byte[0];
//       if (message != null) {
//         postData = message.getBytes("UTF-8");
//       }
//       connection.setRequestMethod(method);
//       connection.setUseCaches(false);
//       connection.setDoInput(true);
//       connection.setConnectTimeout(HTTP_TIMEOUT_MS);
//       connection.setReadTimeout(HTTP_TIMEOUT_MS);
//       // TODO(glaznev) - query request origin from pref_room_server_url_key preferences.
//       connection.addRequestProperty("origin", HTTP_ORIGIN);
//       boolean doOutput = false;
//       if (method.equals("POST")) {
//         doOutput = true;
//         connection.setDoOutput(true);
//         connection.setFixedLengthStreamingMode(postData.length);
//       }
//       if (contentType == null) {
//         connection.setRequestProperty("Content-Type", "text/plain; charset=utf-8");
//       } else {
//         connection.setRequestProperty("Content-Type", contentType);
//       }
// 
//       // Send POST request.
//       if (doOutput && postData.length > 0) {
//         OutputStream outStream = connection.getOutputStream();
//         outStream.write(postData);
//         outStream.close();
//       }
// 
//       // Get response.
//       int responseCode = connection.getResponseCode();
//       if (responseCode != 200) {
//         events.onHttpError("Non-200 response to " + method + " to URL: " + url + " : "
//             + connection.getHeaderField(null));
//         connection.disconnect();
//         return;
//       }
//       InputStream responseStream = connection.getInputStream();
//       String response = drainStream(responseStream);
//       responseStream.close();
//       connection.disconnect();
//       events.onHttpComplete(response);
//     } catch (SocketTimeoutException e) {
//       events.onHttpError("HTTP " + method + " to " + url + " timeout");
//     } catch (IOException e) {
//       events.onHttpError("HTTP " + method + " to " + url + " error: " + e.getMessage());
//     }
//   }
// 
//   // Return the contents of an InputStream as a String.
//   private static String drainStream(InputStream in) {
//     Scanner s = new Scanner(in, "UTF-8").useDelimiter("\\A");
//     return s.hasNext() ? s.next() : "";
//   }
// }
// 
// Path: WebRTCSample/app/src/org/appspot/apprtcstandalone/util/AsyncHttpURLConnection.java
// public interface AsyncHttpEvents {
//   void onHttpError(String errorMessage);
//   void onHttpComplete(String response);
// }


// Path: WebRTCSample/app/src/org/appspot/apprtcstandalone/WebSocketRTCClient.java
import javax.annotation.Nullable;
import org.appspot.apprtcstandalone.RoomParametersFetcher.RoomParametersFetcherEvents;
import org.appspot.apprtcstandalone.WebSocketChannelClient.WebSocketChannelEvents;
import org.appspot.apprtcstandalone.WebSocketChannelClient.WebSocketConnectionState;
import org.appspot.apprtcstandalone.util.AsyncHttpURLConnection;
import org.appspot.apprtcstandalone.util.AsyncHttpURLConnection.AsyncHttpEvents;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.webrtc.IceCandidate;
import org.webrtc.SessionDescription;

    Log.e(TAG, errorMessage);
    handler.post(new Runnable() {
      @Override
      public void run() {
        if (roomState != ConnectionState.ERROR) {
          roomState = ConnectionState.ERROR;
          events.onChannelError(errorMessage);
        }
      }
    });
  }

  // Put a |key|->|value| mapping in |json|.
  private static void jsonPut(JSONObject json, String key, Object value) {
    try {
      json.put(key, value);
    } catch (JSONException e) {
      throw new RuntimeException(e);
    }
  }

  // Send SDP or ICE candidate to a room server.
  private void sendPostMessage(
      final MessageType messageType, final String url, @Nullable final String message) {
    String logInfo = url;
    if (message != null) {
      logInfo += ". Message: " + message;
    }
    Log.d(TAG, "C->GAE: " + logInfo);
    AsyncHttpURLConnection httpConnection =
        new AsyncHttpURLConnection("POST", url, message, new AsyncHttpEvents() {