package com.nbs.client.assassins.views;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragment;
import com.google.android.gms.internal.m;
import com.googlecode.androidannotations.annotations.AfterInject;
import com.googlecode.androidannotations.annotations.Background;
import com.googlecode.androidannotations.annotations.Click;
import com.googlecode.androidannotations.annotations.EFragment;
import com.googlecode.androidannotations.annotations.UiThread;
import com.googlecode.androidannotations.annotations.ViewById;
import com.googlecode.androidannotations.annotations.rest.RestService;
import com.nbs.client.assassins.R;
import com.nbs.client.assassins.R.id;
import com.nbs.client.assassins.R.layout;
import com.nbs.client.assassins.models.App;
import com.nbs.client.assassins.models.Repository;
import com.nbs.client.assassins.models.User;
import com.nbs.client.assassins.network.HuntedRestClient;
import com.nbs.client.assassins.network.JoinMatchRequest;
import com.nbs.client.assassins.network.MatchResponse;
import com.nbs.client.assassins.network.Response;
import com.nbs.client.assassins.services.NotificationService;
import com.nbs.client.assassins.services.NotificationService_;
@EFragment(R.layout.join_match_fragment)
public class JoinMatchFragment extends SherlockFragment {
private static final String TAG = "JoinMatchFragment";
// Container Activity must implement this interface
public interface OnMatchJoinedListener {
public void onMatchJoined(boolean wasJoind);
}
private static final int MIN_PASSWORD_LEN = 6;
private static final int MIN_MATCH_NAME_LEN = 6;
OnMatchJoinedListener mListener;
@ViewById(R.id.join_match)
Button btnJoin;
@ViewById(R.id.edit_join_match_name)
EditText matchName;
@ViewById(R.id.edit_join_match_password)
EditText password;
@RestService
HuntedRestClient restClient;
public JoinMatchFragment() {}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnMatchJoinedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnMatchJoindListener");
}
}
@Click(R.id.join_match)
void onJoinMatchClicked() {
//TODO: validate name and password before allowing button to be enabled
//TODO: show visual indication if there are validation issues
Log.i(TAG, password.getText().toString());
String passwordStr = password.getText().toString();
if((passwordStr.length() >= MIN_PASSWORD_LEN || passwordStr.length() == 0) &&
matchName.getText().toString().length() >= MIN_MATCH_NAME_LEN) {
hideKeyboard();
btnJoin.setEnabled(false);
Repository model = ((App)(getActivity().getApplication())).getRepo();
User user = model.getUser();
JoinMatchRequest msg = new JoinMatchRequest(
user.getToken(),
(passwordStr.length() > 0 ? passwordStr : null),
matchName.getText().toString()
);
joinMatchInBackground(msg,
ProgressDialog.show(getActivity(),"Please Wait","Joining match...", true, false));
}
else {
//TODO: provide earlier and better validation information to user
Toast.makeText(
getActivity(),
"Match name at least " + MIN_MATCH_NAME_LEN +
" chars, Password at least " + MIN_PASSWORD_LEN + " chars",
Toast.LENGTH_LONG
).show();
}
}
private void hideKeyboard() {
InputMethodManager imm = (InputMethodManager)getSherlockActivity().getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
}
@Background
void joinMatchInBackground(JoinMatchRequest msg, ProgressDialog progress) {
MatchResponse response = null;
try {
response = restClient.joinMatch(msg.matchName, msg);
if(response.ok() && response.time != null && response.match != null) {
//in order to have clients start at the same time,
//here we account for time discrepancy between server and client
//the time it takes to send the message is still NOT accounted for
//a server push notification on match start is probably a better solution...
long now = System.currentTimeMillis();
long serverTimeDifference = response.time - now;
Log.d(TAG, "match start time ["+response.match.startTime+"]");
if(response.match.startTime != null) {
response.match.startTime += serverTimeDifference;
Log.d(TAG, "time [local:" + now + "], [server:" + response.time +
"], fix local time ["+serverTimeDifference+"]");
Log.d(TAG, "corrected match start time ["+response.match.startTime+"]");
}
}
}
catch(Exception e) {
Log.i(TAG, "EXCEPTION: " + e.toString());
}
matchJoinedResult(response, progress);
}
@UiThread
void matchJoinedResult(MatchResponse response, ProgressDialog progress) {
if(response != null) {
Toast.makeText(getActivity(), response.message, Toast.LENGTH_SHORT).show();
Log.d(TAG, response.toString());
if(response.ok()) {
Repository model = App.getRepo();
model.createOrUpdateMatch(response.match);
Log.d(TAG, "starting notification service with start time ["+response.match.startTime+"]");
if(response.match.startTime != null) {
getActivity().startService(
new Intent(getActivity(), NotificationService_.class)
.setAction(NotificationService.SET_MATCH_REMINDER_ALARMS)
.putExtra("start_time", response.match.startTime));
} else {
getActivity().startService(
new Intent(getActivity(), NotificationService_.class)
.setAction(NotificationService.WAIT_FOR_MATCH_START));
}
mListener.onMatchJoined(true);
return;
}
} else {
Toast.makeText(getActivity(), "Network error.", Toast.LENGTH_LONG).show();
}
progress.dismiss();
btnJoin.setEnabled(true);
}
@AfterInject
public void afterInjection() {
//subvert a bug in HttpUrlConnection
//see: http://www.sapandiwakar.in/technical/eofexception-with-spring-rest-template-android/
restClient.getRestTemplate().setRequestFactory(
new HttpComponentsClientHttpRequestFactory());
}
}