package com.osmnavigator;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import org.osmdroid.bonuspack.utils.BonusPackHelper;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.FolderOverlay;
import org.osmdroid.views.overlay.Marker;
import org.osmdroid.views.overlay.Overlay;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
/**
* @author M.Kergall
*/
public class FriendsManager {
private MapActivity mActivity;
private MapView mMap;
public static final int START_SHARING_REQUEST = 3;
public static final int FRIENDS_REQUEST = 4;
private Button mFriendsButton;
private static ArrayList<Friend> mFriends; //
private boolean mIsSharing;
private FolderOverlay mFriendsMarkers; //
private boolean mRecordTracks;
public FriendsManager(MapActivity activity, MapView map) {
mActivity = activity;
mMap = map;
mRecordTracks = false;
}
public static ArrayList<Friend> getFriends(){
return mFriends;
}
public void onCreate(Bundle savedInstanceState) {
mFriendsMarkers = new FolderOverlay();
mMap.getOverlays().add(mFriendsMarkers);
if (savedInstanceState != null) {
//STATIC mFriends = savedInstanceState.getParcelable("friends");
mIsSharing = savedInstanceState.getBoolean("is_sharing");
updateUIWithFriendsMarkers();
} else {
mFriends = null;
mIsSharing = false;
}
mFriendsButton = (Button) mActivity.findViewById(R.id.buttonFriends);
mFriendsButton.setVisibility(mIsSharing ? View.VISIBLE : View.GONE);
mFriendsButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if (mIsSharing) {
Intent myIntent = new Intent(view.getContext(), FriendsActivity.class);
myIntent.putExtra("ID", MapActivity.getIndexOfBubbledMarker(mFriendsMarkers.getItems()));
mActivity.startActivityForResult(myIntent, FRIENDS_REQUEST);
}
}
});
}
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean("is_sharing", mIsSharing);
}
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
switch (requestCode) {
case START_SHARING_REQUEST:
if (resultCode == Activity.RESULT_OK) {
String login = intent.getStringExtra("NICKNAME");
String group = intent.getStringExtra("GROUP");
String message = intent.getStringExtra("MESSAGE");
new StartSharingTask().execute(login, group, message);
}
break;
case FRIENDS_REQUEST:
if (resultCode == Activity.RESULT_OK) {
int id = intent.getIntExtra("ID", 0);
Friend selected = mFriends.get(id);
if (selected.mHasLocation) {
mMap.getController().setCenter(selected.mPosition);
Marker friendMarker = (Marker) mFriendsMarkers.getItems().get(id);
friendMarker.showInfoWindow();
}
}
break;
}
}
public void onResume() {
if (mIsSharing)
startSharingTimer();
}
public void onPause() {
stopSharingTimer();
}
public void onPrepareOptionsMenu(Menu menu) {
if (mIsSharing)
menu.findItem(R.id.menu_sharing).setTitle(R.string.menu_stop_sharing);
else
menu.findItem(R.id.menu_sharing).setTitle(R.string.menu_start_sharing);
}
public boolean onOptionsItemSelected(MenuItem item) {
Intent myIntent;
switch (item.getItemId()) {
case R.id.menu_sharing:
if (!mIsSharing) {
myIntent = new Intent(mActivity, StartSharingActivity.class);
mActivity.startActivityForResult(myIntent, START_SHARING_REQUEST);
} else {
new StopSharingTask().execute();
}
}
return true;
}
//--------------------------------------------
protected static final String NAV_SERVER_URL = "http://comob.free.fr/sharing/";
public String getUniqueId() {
return Settings.Secure.getString(mActivity.getContentResolver(), Settings.Secure.ANDROID_ID);
}
String callStartSharing(String nickname, String group, String message) {
//List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(4);
String url = null;
try {
url = NAV_SERVER_URL + "jstart.php?"
+ "nickname=" + URLEncoder.encode(nickname, "UTF-8")
+ "&group_id=" + URLEncoder.encode(group, "UTF-8")
+ "&user_id=" + URLEncoder.encode(getUniqueId(), "UTF-8")
+ "&message=" + URLEncoder.encode(message, "UTF-8");
} catch (UnsupportedEncodingException e) {
}
/*
nameValuePairs.add(new BasicNameValuePair("nickname", nickname));
nameValuePairs.add(new BasicNameValuePair("group_id", group));
nameValuePairs.add(new BasicNameValuePair("user_id", getUniqueId()));
nameValuePairs.add(new BasicNameValuePair("message", message));
String result = BonusPackHelper.requestStringFromPost(url, nameValuePairs);
*/
String result = BonusPackHelper.requestStringFromUrl(url);
if (result == null) {
return "Technical error with the server";
}
try {
JsonParser parser = new JsonParser();
JsonElement json = parser.parse(result);
JsonObject jResult = json.getAsJsonObject();
String answer = jResult.get("answer").getAsString();
if (!"ok".equals(answer)) {
return jResult.get("error").getAsString();
}
} catch (JsonSyntaxException e) {
return "Technical error with the server";
}
return null;
}
private class StartSharingTask extends AsyncTask<String, Void, String> {
@Override protected String doInBackground(String... params) {
return callStartSharing(params[0], params[1], params[2]);
}
@Override protected void onPostExecute(String error) {
if (error == null) {
startSharingTimer();
mIsSharing = true;
mFriendsButton.setVisibility(View.VISIBLE);
} else
Toast.makeText(mActivity.getApplicationContext(), error, Toast.LENGTH_SHORT).show();
}
}
private static final int SHARING_INTERVAL = 20 * 1000; //every 20 sec
private Handler mSharingHandler;
private Runnable mSharingRunnable = new Runnable() {
@Override
public void run() {
new UpdateSharingTask().execute();
mSharingHandler.postDelayed(this, SHARING_INTERVAL);
}
};
void startSharingTimer() {
mSharingHandler = new Handler();
mSharingHandler.postDelayed(mSharingRunnable, 0);
}
void stopSharingTimer() {
if (mSharingHandler != null) {
mSharingHandler.removeCallbacks(mSharingRunnable);
}
}
String callUpdateSharing() {
mFriends = null;
GeoPoint myPosition = mActivity.myLocationOverlay.getLocation();
int hasLocation = (myPosition != null ? 1 : 0);
if (myPosition == null)
myPosition = new GeoPoint(0.0, 0.0);
String url = null;
try {
url = NAV_SERVER_URL + "jupdate.php?"
+ "user_id=" + URLEncoder.encode(getUniqueId(), "UTF-8")
+ "&has_location=" + hasLocation
+ "&lat=" + myPosition.getLatitude()
+ "&lon=" + myPosition.getLongitude()
+ "&bearing=" + mActivity.mAzimuthAngleSpeed;
} catch (UnsupportedEncodingException e) {
return "Technical error with the server";
}
Log.d(BonusPackHelper.LOG_TAG, "callUpdateSharing:" + url);
String result = BonusPackHelper.requestStringFromUrl(url);
if (result == null) {
return "Technical error with the server";
}
try {
JsonParser parser = new JsonParser();
JsonElement json = parser.parse(result);
JsonObject jResult = json.getAsJsonObject();
String answer = jResult.get("answer").getAsString();
if (!"ok".equals(answer)) {
return jResult.get("error").getAsString();
}
JsonArray jFriends = jResult.get("people").getAsJsonArray();
mFriends = new ArrayList<Friend>(jFriends.size());
for (JsonElement jFriend : jFriends) {
JsonObject joFriend = (JsonObject) jFriend;
Friend friend = new Friend(joFriend);
mFriends.add(friend);
}
} catch (JsonSyntaxException e) {
return "Technical error with the server";
}
return null;
}
int getOpenedInfoWindow(FolderOverlay folder) {
List<Overlay> items = mFriendsMarkers.getItems();
for (int i = 0; i < items.size(); i++) {
Overlay overlay = items.get(i);
if (overlay instanceof Marker) {
Marker m = (Marker) overlay;
if (m.isInfoWindowShown())
return i;
}
}
return -1;
}
public void setTracksRecording(boolean recordTracks){
mRecordTracks = recordTracks;
}
public void recordTracks(){
for (Friend friend : mFriends) {
if (friend.mHasLocation)
mActivity.recordCurrentLocationInTrack(friend.mId, friend.mNickName, friend.mPosition);
}
}
void updateUIWithFriendsMarkers() {
//retrieve the id of the "opened" friend (friend with opened bubble):
int opened = getOpenedInfoWindow(mFriendsMarkers);
String openedFriendId = null;
if (opened != -1) {
Marker m = (Marker)mFriendsMarkers.getItems().get(opened);
Friend openedFriend = (Friend)m.getRelatedObject();
openedFriendId = openedFriend.mId;
}
mFriendsMarkers.closeAllInfoWindows();
mFriendsMarkers.getItems().clear();
if (mFriends == null) {
mMap.invalidate();
return;
}
Drawable iconOnline = mActivity.getResources().getDrawable(R.drawable.marker_car_on);
Drawable iconOffline = mActivity.getResources().getDrawable(R.drawable.marker_friend_off);
for (Friend friend : mFriends) {
//MarkerLabeled marker = new MarkerLabeled(map);
Marker marker = new Marker(mMap);
marker.setPosition(friend.mPosition);
marker.setTitle(friend.mNickName);
marker.setSnippet(friend.mMessage);
if (friend.mOnline) {
marker.setIcon(iconOnline); //((BitmapDrawable) iconOnline).getBitmap());
marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER);
marker.setRotation(friend.mBearing);
} else {
marker.setIcon(iconOffline); //((BitmapDrawable)iconOffline).getBitmap());
}
if (!friend.mHasLocation)
marker.setEnabled(false);
marker.setRelatedObject(friend);
mFriendsMarkers.add(marker);
}
mMap.invalidate();
//reopen the bubble on the "same" (but new) Friend marker:
opened = getFriendWithId(openedFriendId);
if (opened != -1) {
Marker markerToOpen = (Marker) mFriendsMarkers.getItems().get(opened);
markerToOpen.showInfoWindow();
}
}
/**
* @param friendId
* @return the index of the friend with id. -1 if not found.
*/
public int getFriendWithId(String friendId){
if (friendId == null || mFriends == null)
return -1;
for (int i=0; i<mFriends.size(); i++) {
Friend f = mFriends.get(i);
if (friendId.equals(f.mId))
return i;
}
return -1;
}
private class UpdateSharingTask extends AsyncTask<Void, Void, String> {
@Override protected String doInBackground(Void... params) {
return callUpdateSharing();
}
@Override protected void onPostExecute(String error) {
if (error == null) {
updateUIWithFriendsMarkers();
if (mRecordTracks)
recordTracks();
} else
Toast.makeText(mActivity.getApplicationContext(), error, Toast.LENGTH_SHORT).show();
}
}
String callStopSharing() {
mFriends = null;
String url = null;
try {
url = NAV_SERVER_URL + "jstop.php?"
+ "user_id=" + URLEncoder.encode(getUniqueId(), "UTF-8");
} catch (UnsupportedEncodingException e) {
return "Technical error with the server";
}
String result = BonusPackHelper.requestStringFromUrl(url);
if (result == null) {
return "Technical error with the server";
}
try {
JsonParser parser = new JsonParser();
JsonElement json = parser.parse(result);
JsonObject jResult = json.getAsJsonObject();
String answer = jResult.get("answer").getAsString();
if (!"ok".equals(answer)) {
return jResult.get("error").getAsString();
}
} catch (JsonSyntaxException e) {
return "Technical error with the server";
}
return null;
}
private class StopSharingTask extends AsyncTask<Void, Void, String> {
@Override protected String doInBackground(Void... params) {
return callStopSharing();
}
@Override protected void onPostExecute(String error) {
if (error == null) {
updateUIWithFriendsMarkers();
stopSharingTimer();
mIsSharing = false;
mFriendsButton.setVisibility(View.GONE);
} else
Toast.makeText(mActivity.getApplicationContext(), error, Toast.LENGTH_SHORT).show();
}
}
}