package stetson.CTF.utils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.google.android.maps.GeoPoint;
import stetson.CTF.JoinCTF;
import stetson.CTF.Join.GameItem;
import android.util.Log;
public class Connections {
public final static String TAG = "Connections";
private final static String GOOD_RESPONSE = "OK";
public static final int CUSTOM_PARAMS = -1;
public static final int CREATE_PARAMS = 0;
public static final int JOIN_PARAMS = 1;
public static final int UPDATE_PARAMS = 2;
public static final int LEAVE_PARAMS = 3;
/**
* Makes an HTTP request and returns a response as a string.
* @param request
* @return response
*/
public static String sendRequest(HttpRequestBase request) {
Log.i(TAG, "ConnectionF: " + request.getURI());
try {
HttpClient client = new DefaultHttpClient();
HttpResponse resp;
resp = client.execute(request);
return responseToString(resp);
} catch (ClientProtocolException e) {
Log.e(TAG, "Web Request Failed", e);
} catch (IOException e) {
Log.e(TAG, "Web Request Failed", e);
}
return "";
}
/**
* Generates HttpParams automatically for the current user.
* Type: CREATE_PARAMS = lat, long, name, gameId
* JOIN_PARAMS = lat, long, accuracy, uid, name
* UPDATE_PARAMS = lat, long, accuracy, uid, name, game
* CUSTOM_PARAMS = uses ArrayList passed to create FormEntity
* @param type
* @return
*/
public static UrlEncodedFormEntity buildHttpParams(int type, ArrayList<NameValuePair> customList) {
ArrayList<NameValuePair> params = new ArrayList<NameValuePair>(4);
boolean location = false;
boolean user_id = false;
boolean game_id = false;
boolean name = false;
boolean custom = false;
// Determine what is needed for each protocol
switch(type) {
case CREATE_PARAMS:
location = true;
user_id = true;
name = true;
game_id = true;
break;
case JOIN_PARAMS:
location = true;
user_id = true;
name = true;
break;
case UPDATE_PARAMS:
location = true;
user_id = true;
name = true;
game_id = true;
break;
case LEAVE_PARAMS:
user_id = true;
break;
case CUSTOM_PARAMS:
custom = true;
break;
}
if(custom)
{
params = customList;
}
// Location Information
if(location) {
params.add(new BasicNameValuePair("latitude", Double.toString(CurrentUser.getLatitude())));
params.add(new BasicNameValuePair("longitude", Double.toString(CurrentUser.getLongitude())));
params.add(new BasicNameValuePair("accuracy", Float.toString(CurrentUser.getAccuracy())));
}
// User UID
if(user_id) {
params.add(new BasicNameValuePair("user_id", CurrentUser.getUID()));
}
// Game ID
if(game_id) {
params.add(new BasicNameValuePair("game_id", CurrentUser.getGameId()));
}
// Username
if(name) {
params.add(new BasicNameValuePair("name", CurrentUser.getName()));
}
try {
return new UrlEncodedFormEntity(params,HTTP.UTF_8);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Error adding params to request!", e);
}
return null;
}
/**
* Draws a string from an HttpResponse object.
* @param rp
* @return
*/
public static String responseToString(HttpResponse rp) {
String str = "";
try {
str = EntityUtils.toString(rp.getEntity());
} catch(IOException e) {
Log.e(TAG, "HttpRequest Error!", e);
}
return str;
}
/**
* Main method to create a game if the game parameter is ""
* Main method to join a game if the game parameter is the gameName
*
* @param usrName
* @param usrGame
* @return
*/
public static String joinOrCreate(String usrName) {
// More friendly parameters :)
String name = usrName;
String game = CurrentUser.getGameId();
Log.i(TAG, "(WORKER) joinGame(" + name + ", " + game + ")");
// If a game name wasn't given, then we need to make a game.
if(game.equals("")) {
CurrentUser.setGameId(CurrentUser.getName());
String data = callPost("/game/", buildHttpParams(CREATE_PARAMS,null));
Log.i(TAG, "RESPONSE: " +data);
try {
JSONObject response = new JSONObject(data);
Log.i(TAG, "(WORKER) create game response: " + data);
if(response.has("response") && !response.getString("response").equals(GOOD_RESPONSE)) {
return "Unexpected server response #1";
} else if (response.has("error")) {
return "Server Error: " + response.get("error");
}
} catch (JSONException e) {
Log.e(TAG, "Error parsing JSON.", e);
return "Unexpected server response #2";
}
}
// If a game was created, then it was a success at this point! Now we must join the game.
String data = callPost("/game/" + encString(CurrentUser.getGameId()) ,buildHttpParams(JOIN_PARAMS,null));
try {
JSONObject jsonGame = new JSONObject(data);
if(jsonGame.has("error")) {
return "Server Error: " + jsonGame.get("error");
}
} catch (JSONException e) {
Log.e(TAG, "Error parsing JSON.", e);
return "Unexpected server response #3";
}
return GOOD_RESPONSE;
}
/**
* Method returns ArrayList<String> of the list of games available
*
* @return ArrayList<String> games
*/
public static ArrayList<GameItem> getGames() {
ArrayList<GameItem> gamesList = new ArrayList<GameItem>();
// Sweet, we have a location, lets grab a list of games
HttpGet req = new HttpGet(JoinCTF.SERVER_URL + "/game/?" + CurrentUser.buildQueryParams());
String data = Connections.sendRequest(req);
try {
JSONObject games = new JSONObject(data);
if (games.has("games")) {
// Add all the games to a list
JSONArray list = games.getJSONArray("games");
for(int n = 0; n < list.length(); n++) {
GameItem item = new GameItem(list.optJSONObject(n));
gamesList.add(item);
}
// Ok, that's all, return the games list
return gamesList;
} else {
Log.e(TAG, "Unexpected Server Response: " + data);
}
} catch (JSONException e) {
Log.e(TAG, "Error parsing JSON.", e);
}
return null;
}
/**
* Methods returns all gameData
*
* @return JSONObject gameData
*/
public static JSONObject getGameData() {
String data = callPost("/location/", buildHttpParams(UPDATE_PARAMS,null));
try {
JSONObject jObject = new JSONObject(data);
return jObject;
} catch (JSONException e) {
Log.e(TAG, "Error parsing JSON.", e);
}
return null;
}
/**
* Sends server request to move a flag.
* Requires that the user is the creator of the game.
* @param loc
* @param team
*/
public static void moveFlag(GeoPoint loc, String team) {
ArrayList<NameValuePair> params = new ArrayList<NameValuePair>(4);
params.add(new BasicNameValuePair("latitude", "" + (loc.getLatitudeE6() / 1E6)));
params.add(new BasicNameValuePair("longitude", "" + (loc.getLongitudeE6() / 1E6)));
params.add(new BasicNameValuePair("user_id", CurrentUser.getUID()));
params.add(new BasicNameValuePair("game_id", CurrentUser.getGameId()));
params.add(new BasicNameValuePair("team", team));
String data = callPost("/flag/",buildHttpParams(CUSTOM_PARAMS, params));
Log.i(TAG, "FLAG MOVE: " + data);
}
/**
* Method that calls HttpPost with the servers url
* Uses given url and form entity to make post.
*
* @param postURL
* @param params
* @return
*/
public static String callPost(String postURL,UrlEncodedFormEntity params)
{
// url to post data to
String url = postURL;
HttpPost req = new HttpPost(JoinCTF.SERVER_URL + url);
req.setEntity(params);
String data = Connections.sendRequest(req);
return data;
}
/**
* Request to leave the game that the user is in.
* This call does not handle the server's response!
* @param game name
* @param user uid
*/
public static void leaveGame(String gameName, String uid) {
String gameUrl = encString(gameName);
HttpDelete req = new HttpDelete(JoinCTF.SERVER_URL + "/game/" + gameUrl + "/" + uid);
Connections.sendRequest(req);
}
public static String encString(String param)
{
String message="";
if(!param.equals(""))
{
try {
message = URLEncoder.encode(param,HTTP.UTF_8);
message = message.replaceAll("\\+", "%20");
} catch (UnsupportedEncodingException e) {
message = "error encoding string";
e.printStackTrace();
}
catch (NullPointerException e)
{
message = "error encoding string";
e.printStackTrace();
}
}
return message;
}
}