package com.buddycloud;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONObject;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.text.Editable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.UnderlineSpan;
import android.util.Patterns;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.MenuItem;
import com.buddycloud.customviews.TooltipErrorView;
import com.buddycloud.http.SSLUtils;
import com.buddycloud.model.AccountModel;
import com.buddycloud.model.ModelCallback;
import com.buddycloud.preferences.Preferences;
import com.buddycloud.utils.ActionbarUtil;
import com.buddycloud.utils.DNSUtils;
import com.buddycloud.utils.InputUtils;
/**
* This activity used to show the create account screen
* and handle all the actions.
*
* @author Adnan Urooj (Deminem)
*
*/
public class CreateAccountActivity extends SherlockActivity {
private static final String TAG = CreateAccountActivity.class.getSimpleName();
private static final String DOMAIN_SUGGESTION_URL = "http://buddycloud.com/registration-helper/sign-up-domains.json";
public static final String BUDDYCLOUD_DOMAIN = "buddycloud.org";
public static final int REQUEST_CODE = 105;
public static final int ACCOUNT_CREATED_RESULT = 205;
private EditText mUsernameTxt;
private EditText mPasswordTxt;
private EditText mEmailAddressTxt;
private TextView mCreateAccountCaption;
private TooltipErrorView mUsernameErrorTooltip;
private TooltipErrorView mPasswordErrorTooltip;
private TooltipErrorView mEmailErrorTooltip;
private ProgressDialog mProgressDialog;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_account);
ActionbarUtil.showActionBarwithBack(this, getString(R.string.create_account_title));
mUsernameErrorTooltip = (TooltipErrorView) findViewById(R.id.usernameErrorTooltip);
mUsernameTxt = (EditText) findViewById(R.id.usernameTxt);
mUsernameTxt.addTextChangedListener(mUserNameTxtWatcher);
mPasswordErrorTooltip = (TooltipErrorView) findViewById(R.id.passwordErrorTooltip);
mPasswordTxt = (EditText) findViewById(R.id.passwordTxt);
mPasswordTxt.addTextChangedListener(mPasswordTxtWatcher);
mEmailErrorTooltip = (TooltipErrorView) findViewById(R.id.emailErrorTooltip);
mEmailAddressTxt = (EditText) findViewById(R.id.emailAddressTxt);
mEmailAddressTxt.addTextChangedListener(mEmailAddressTxtWatcher);
mEmailAddressTxt.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
final String accountNameTxt = getValue(R.id.usernameTxt);
final String passwordTxt = getValue(R.id.passwordTxt);
final String emailAddressTxt = getValue(R.id.emailAddressTxt);
// resolve API service and create account.
resolveAPISRVAndCreateAccount(accountNameTxt, passwordTxt, emailAddressTxt);
}
return false;
}
});
mCreateAccountCaption = (TextView) findViewById(R.id.createAccountCaption);
SpannableString hyperLinkSpan = new SpannableString(mCreateAccountCaption.getText().toString());
hyperLinkSpan.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.bc_green_blue_color)), 162, hyperLinkSpan.length() - 1, 0);
hyperLinkSpan.setSpan(new UnderlineSpan(), 162, hyperLinkSpan.length() - 1, 0);
hyperLinkSpan.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
String url = getString(R.string.buddycloud_website);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
startActivity(intent);
}
}, 162, hyperLinkSpan.length() - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mCreateAccountCaption.setText(hyperLinkSpan);
mCreateAccountCaption.setMovementMethod(LinkMovementMethod.getInstance());
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage(getString(R.string.message_account_creation));
mProgressDialog.setCancelable(false);
final Button createAccountBtn = (Button) findViewById(R.id.createAccountBtn);
createAccountBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
final String accountNameTxt = getValue(R.id.usernameTxt);
final String passwordTxt = getValue(R.id.passwordTxt);
final String emailAddressTxt = getValue(R.id.emailAddressTxt);
// resolve API service and create account.
resolveAPISRVAndCreateAccount(accountNameTxt, passwordTxt, emailAddressTxt);
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
InputUtils.hideKeyboard(CreateAccountActivity.this);
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onAttachedToWindow() {
// fillSuggestions();
}
/*
private void fillSuggestions() {
BuddycloudHTTPHelper.reqArrayNoSSL(DOMAIN_SUGGESTION_URL, this,
new ModelCallback<JSONArray>() {
@Override
public void success(JSONArray response) {
List<Domain> domains = new ArrayList<Domain>();
for (int i = 0; i < response.length(); i++) {
JSONObject domainJson = response.optJSONObject(i);
domains.add(new Domain(domainJson));
}
final DomainAdapter adapter = new DomainAdapter(
getApplicationContext(),
R.layout.domain_spinner_item,
domains);
AlertDialog.Builder builder = new
AlertDialog.Builder(CreateAccountActivity.this);
DialogInterface.OnClickListener dialogListener = new
DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int
which) {
Domain domain = adapter.getItem(which);
TextView domainTextView = (TextView)
findViewById(R.id.domainTxt);
domainTextView.setText(domain.toString());
dialog.dismiss();
}
};
builder.setTitle(getString(R.string.create_account_domain_hint));
builder.setAdapter(adapter, dialogListener);
builder.create().show();
}
@Override
public void error(Throwable throwable) {
// TODO Auto-generated method stub
}
});
} */
/**
* Resolve API Service and create new account
*
*/
private void resolveAPISRVAndCreateAccount(final String accountNameTxt,
final String passwordTxt,
final String emailAddressTxt) {
if (isEmpty(accountNameTxt)) {
showErrorToolTip(mUsernameErrorTooltip,
getString(R.string.message_account_username_mandatory));
return;
}
if (isEmpty(passwordTxt)) {
showErrorToolTip(mPasswordErrorTooltip,
getString(R.string.message_account_password_mandatory));
return;
}
if (!isValidEmail(emailAddressTxt)) {
showErrorToolTip(mEmailErrorTooltip,
getString(R.string.message_account_email_invalid));
return;
}
final String bareJid = accountNameTxt + "@" + BUDDYCLOUD_DOMAIN;
if (!isBareJid(bareJid)) {
Toast.makeText(getApplicationContext(),
getString(R.string.message_account_invalid_domain),
Toast.LENGTH_LONG).show();
return;
}
// remove all error tooltips
hideAllErrorTooltips();
//hide keyboard
InputUtils.hideKeyboard(CreateAccountActivity.this);
// show progress dialog
mProgressDialog.show();
// resolve API service
DNSUtils.resolveAPISRV(new ModelCallback<String>() {
@Override
public void success(final String apiAddress) {
SSLUtils.checkSSL(getApplicationContext(), apiAddress,
new ModelCallback<Void>() {
@Override
public void success(Void response) {
createAccount(emailAddressTxt,
passwordTxt, bareJid,
apiAddress);
}
@Override
public void error(Throwable throwable) {
// Do nothing, SSL error not tolerable
mProgressDialog.dismiss();
}
});
}
@Override
public void error(Throwable throwable) {
mProgressDialog.dismiss();
Toast.makeText(
getApplicationContext(),
getString(R.string.message_api_discovery_failed),
Toast.LENGTH_LONG).show();
return;
}
}, BUDDYCLOUD_DOMAIN);
}
/**
* Create new account
*
* @param emailAddressTxt
* @param passwordTxt
* @param bareJid
* @param apiAddress
*/
private void createAccount(final String emailAddressTxt,
final String passwordTxt, final String bareJid,
final String apiAddress) {
Map<String, String> accountInfo = new HashMap<String, String>();
accountInfo.put("username", bareJid);
accountInfo.put("password", passwordTxt);
accountInfo.put("email", emailAddressTxt);
AccountModel.getInstance().save(getApplicationContext(),
new JSONObject(accountInfo), new ModelCallback<JSONObject>() {
@Override
public void success(JSONObject response) {
mProgressDialog.dismiss();
Preferences.setPreference(getApplicationContext(),
Preferences.MY_CHANNEL_JID, bareJid);
Preferences.setPreference(getApplicationContext(),
Preferences.PASSWORD, passwordTxt);
Preferences.setPreference(getApplicationContext(),
Preferences.API_ADDRESS, apiAddress);
setResult(ACCOUNT_CREATED_RESULT);
finish();
}
@Override
public void error(Throwable throwable) {
mProgressDialog.dismiss();
showErrorToolTip(mUsernameErrorTooltip,
getString(R.string.message_account_creation_failed));
Toast.makeText(
getApplicationContext(),
getString(R.string.message_account_creation_failed),
Toast.LENGTH_LONG).show();
}
}, apiAddress);
}
private void showErrorToolTip(TooltipErrorView errorView, String errorMsg) {
if (errorView != null && !isEmpty(errorMsg)) {
errorView.setText(errorMsg);
errorView.setVisibility(View.VISIBLE);
}
}
private void hideAllErrorTooltips() {
if (mUsernameErrorTooltip != null && mPasswordErrorTooltip != null
&& mEmailErrorTooltip != null) {
mUsernameErrorTooltip.setVisibility(View.GONE);
mPasswordErrorTooltip.setVisibility(View.GONE);
mEmailErrorTooltip.setVisibility(View.GONE);
}
}
private static boolean isEmpty(String string) {
return string.length() == 0;
}
private static boolean isValidEmail(String email) {
final String EMAIL_REGEX = "^[\\w-_\\.+]*[\\w-_\\.]\\@([\\w]+\\.)+[\\w]+[\\w]$";
return (!isEmpty(email) && email.matches(EMAIL_REGEX));
}
private static boolean isValidUsername(String username) {
final String USERNAME_REGEX = "^([a-zA-Z0-9._])+$";
return (!isEmpty(username) && username.matches(USERNAME_REGEX));
}
public static boolean isBareJid(CharSequence target) {
return Patterns.EMAIL_ADDRESS.matcher(target).matches();
}
private String getValue(int resId) {
return ((EditText) findViewById(resId)).getText().toString();
}
private static class Domain {
private JSONObject domainObject;
public Domain(JSONObject domainObject) {
this.domainObject = domainObject;
}
JSONObject getJSON() {
return domainObject;
}
@Override
public String toString() {
return domainObject.optString("domain");
}
}
private class DomainAdapter extends ArrayAdapter<Domain> {
public DomainAdapter(Context context, int textViewResourceId,
List<Domain> objects) {
super(context, textViewResourceId, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
public View getCustomView(int position, View convertView,
ViewGroup parent) {
Domain domain = getItem(position);
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.domain_spinner_item, parent,
false);
TextView label = (TextView) row.findViewById(R.id.textHeader);
label.setText(domain.getJSON().optString("domain"));
TextView sub = (TextView) row.findViewById(R.id.textSub);
sub.setText(domain.getJSON().optString("name"));
return row;
}
}
private final TextWatcher mUserNameTxtWatcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void afterTextChanged(Editable s) {
if (s.length() == 0) {
showErrorToolTip(mUsernameErrorTooltip,
getString(R.string.message_account_username_mandatory));
} else if (s.toString().contains("@") || s.toString().contains(" ")) {
showErrorToolTip(mUsernameErrorTooltip,
getString(R.string.message_account_username_invalid1));
}
else if (!isValidUsername(s.toString())) {
showErrorToolTip(mUsernameErrorTooltip,
getString(R.string.message_account_username_invalid2));
}
else {
mUsernameErrorTooltip.setVisibility(View.GONE);
}
}
};
private final TextWatcher mPasswordTxtWatcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void afterTextChanged(Editable s) {
if (s.length() == 0) {
showErrorToolTip(mPasswordErrorTooltip,
getString(R.string.message_account_password_mandatory));
} else if (s.length() < 6) {
showErrorToolTip(mPasswordErrorTooltip,
getString(R.string.message_account_password_short_length));
} else {
mPasswordErrorTooltip.setVisibility(View.GONE);
}
}
};
private final TextWatcher mEmailAddressTxtWatcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void afterTextChanged(Editable s) {
if (s.length() == 0) {
showErrorToolTip(mEmailErrorTooltip,
getString(R.string.message_account_email_invalid));
} else {
mEmailErrorTooltip.setVisibility(View.GONE);
}
}
};
}