package com.ioabsoftware.gameraven.prefs;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnDismissListener;
import android.content.DialogInterface.OnShowListener;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceManager;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.ioabsoftware.gameraven.R;
import com.ioabsoftware.gameraven.networking.NetDesc;
import com.ioabsoftware.gameraven.networking.Session;
import com.ioabsoftware.gameraven.util.AccountManager;
import com.ioabsoftware.gameraven.util.DocumentParser;
import com.ioabsoftware.gameraven.util.FinalDoc;
import com.ioabsoftware.gameraven.util.Theming;
import com.koushikdutta.async.future.FutureCallback;
import com.koushikdutta.ion.Ion;
import com.koushikdutta.ion.Response;
import org.apache.commons.lang3.StringEscapeUtils;
import org.jsoup.nodes.Document;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import de.keyboardsurfer.android.widget.crouton.Crouton;
public class SettingsAccount extends PreferenceActivity implements FutureCallback<Response<FinalDoc>> {
private static final String ION_INSTANCE = "AccountVerifier";
private Ion accountVerifier;
public static final int ADD_ACCOUNT_DIALOG = 300;
public static final int VERIFY_ACCOUNT_DIALOG = 301;
public static final int MODIFY_ACCOUNT_DIALOG = 302;
String verifyUser;
String verifyPass;
PreferenceCategory accounts;
Preference clickedAccount;
String clickedAccountName;
SharedPreferences settings;
private Toolbar mActionBar;
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(Theming.theme());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().setStatusBarColor(Theming.colorPrimaryDark());
}
settings = PreferenceManager.getDefaultSharedPreferences(this);
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settingsaccount);
accountVerifier = Ion.getInstance(this, ION_INSTANCE);
accountVerifier.getCookieMiddleware().clear();
Theming.colorOverscroll(this);
accounts = (PreferenceCategory) findPreference("accounts");
updateAccountList();
findPreference("addAccount").setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
showDialog(ADD_ACCOUNT_DIALOG);
return true;
}
});
}
@Override
public void setContentView(int layoutResID) {
ViewGroup contentView = (ViewGroup) LayoutInflater.from(this).inflate(
R.layout.settings_activity, new LinearLayout(this), false);
mActionBar = (Toolbar) contentView.findViewById(R.id.saToolbar);
mActionBar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
mActionBar.setTitle(getTitle());
mActionBar.setTitleTextColor(Color.WHITE);
ViewGroup contentWrapper = (ViewGroup) contentView.findViewById(R.id.saContentWrapper);
LayoutInflater.from(this).inflate(layoutResID, contentWrapper, true);
getWindow().setContentView(contentView);
}
@Override
public void onDestroy() {
Crouton.clearCroutonsForActivity(this);
super.onDestroy();
}
private void updateAccountList() {
accounts.removeAll();
String def = settings.getString("defaultAccount", HeaderSettings.NO_DEFAULT_ACCOUNT);
for (String s : AccountManager.getUsernames(this)) {
Preference pref = new Preference(this);
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
clickedAccount = preference;
showDialog(MODIFY_ACCOUNT_DIALOG);
return true;
}
});
String sig = settings.getString("customSig" + s, "");
pref.setTitle(s);
if (s.equals(def) && !sig.equals(""))
pref.setSummary("Default account, custom signature applied");
else if (s.equals(def))
pref.setSummary("Default account");
else if (!sig.equals(""))
pref.setSummary("Custom signature applied");
pref.setPersistent(false);
accounts.addPreference(pref);
}
}
// creates dialogs
@Override
protected Dialog onCreateDialog(int id) {
Dialog dialog = null;
switch (id) {
case ADD_ACCOUNT_DIALOG:
dialog = createAddAccountDialog();
break;
case VERIFY_ACCOUNT_DIALOG:
ProgressDialog d = new ProgressDialog(this);
d.setTitle("Verifying Account...");
d.setCancelable(false);
dialog = d;
break;
case MODIFY_ACCOUNT_DIALOG:
dialog = createModifyAccountV2Dialog();
break;
}
return dialog;
}
private LinearLayout addAccWrapper;
private Dialog createAddAccountDialog() {
AlertDialog.Builder b = new AlertDialog.Builder(this);
LayoutInflater inflater = getLayoutInflater();
final View v = inflater.inflate(R.layout.addaccount, null);
addAccWrapper = (LinearLayout) v.findViewById(R.id.addaccWrapper);
b.setView(v);
b.setTitle("Add Account");
b.setNegativeButton("Cancel", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
removeDialog(ADD_ACCOUNT_DIALOG);
}
});
b.setPositiveButton("OK", null);
final AlertDialog d = b.create();
d.setOnShowListener(new OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
d.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
verifyUser = ((TextView) v.findViewById(R.id.addaccUser)).getText().toString().trim();
verifyPass = ((TextView) v.findViewById(R.id.addaccPassword)).getText().toString();
if (verifyUser.indexOf('@') == -1) {
showDialog(VERIFY_ACCOUNT_DIALOG);
accountVerifier.getCookieMiddleware().clear();
currentDesc = NetDesc.VERIFY_ACCOUNT_S1;
accountVerifier.build(SettingsAccount.this)
.load("GET", Session.ROOT)
.as(new DocumentParser())
.withResponse()
.setCallback(SettingsAccount.this);
} else {
Crouton.showText(SettingsAccount.this,
"Please use your username, not your email address.",
Theming.croutonStyle(),
(ViewGroup) v.findViewById(R.id.addaccUser).getParent());
}
}
});
}
});
d.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
addAccWrapper = null;
removeDialog(ADD_ACCOUNT_DIALOG);
}
});
return d;
}
private Dialog createModifyAccountV2Dialog() {
clickedAccountName = clickedAccount.getTitle().toString();
AlertDialog.Builder b = new AlertDialog.Builder(this);
LayoutInflater inflater = getLayoutInflater();
final View v = inflater.inflate(R.layout.modifyaccountv2, null);
b.setView(v);
b.setTitle("Modify " + clickedAccountName);
Button deleteAcc = (Button) v.findViewById(R.id.modaccDeleteAcc);
final CheckBox defaultAcc = (CheckBox) v.findViewById(R.id.modaccDefaultAccount);
final CheckBox useGFAQsSig = (CheckBox) v.findViewById(R.id.modaccUseGfaqsSig);
final EditText sigContent = (EditText) v.findViewById(R.id.modaccSigContent);
final TextView sigCounter = (TextView) v.findViewById(R.id.modaccSigCounter);
if (clickedAccountName.equals(settings.getString("defaultAccount", HeaderSettings.NO_DEFAULT_ACCOUNT)))
defaultAcc.setChecked(true);
else
defaultAcc.setChecked(false);
defaultAcc.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
settings.edit().putString("defaultAccount", clickedAccountName).apply();
Crouton.showText(SettingsAccount.this,
"Default account saved.",
Theming.croutonStyle(),
(ViewGroup) buttonView.getParent().getParent());
} else {
settings.edit().putString("defaultAccount", HeaderSettings.NO_DEFAULT_ACCOUNT).apply();
settings.edit().putLong("notifsLastPost", 0).apply();
Crouton.showText(SettingsAccount.this,
"Default account removed.",
Theming.croutonStyle(),
(ViewGroup) buttonView.getParent().getParent());
}
}
});
useGFAQsSig.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
settings.edit().putBoolean("useGFAQsSig" + clickedAccountName, isChecked).apply();
sigContent.setEnabled(!isChecked);
}
});
useGFAQsSig.setChecked(settings.getBoolean("useGFAQsSig" + clickedAccountName, false));
sigContent.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
String escapedSig = StringEscapeUtils.escapeHtml4(sigContent.getText().toString());
int length = escapedSig.length();
int lines = 0;
for (int i = 0; i < escapedSig.length(); i++) {
if (escapedSig.charAt(i) == '\n') lines++;
}
sigCounter.setText((1 - lines) + " line break(s), " + (160 - length) + " characters available");
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
});
sigContent.setText(settings.getString("customSig" + clickedAccountName, ""));
deleteAcc.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (clickedAccountName.equals(settings.getString("defaultAccount", HeaderSettings.NO_DEFAULT_ACCOUNT)))
settings.edit().putString("defaultAccount", HeaderSettings.NO_DEFAULT_ACCOUNT).apply();
settings.edit().remove("customSig" + clickedAccountName).apply();
AccountManager.removeUser(SettingsAccount.this, clickedAccountName);
accounts.removePreference(clickedAccount);
dismissDialog(MODIFY_ACCOUNT_DIALOG);
Crouton.showText(SettingsAccount.this, "Account removed.", Theming.croutonStyle());
}
});
b.setPositiveButton("Save Sig", null);
b.setNeutralButton("Clear Sig", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
settings.edit().putString("customSig" + clickedAccountName, "").apply();
sigContent.setText("");
Crouton.showText(SettingsAccount.this, "Signature cleared and saved.", Theming.croutonStyle());
}
});
b.setNegativeButton("Close", null);
final AlertDialog d = b.create();
d.setOnShowListener(new OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
d.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String escapedSig = StringEscapeUtils.escapeHtml4(sigContent.getText().toString());
int length = escapedSig.length();
int lines = 0;
for (int i = 0; i < escapedSig.length(); i++) {
if (escapedSig.charAt(i) == '\n') lines++;
}
if (length < 161) {
if (lines < 2) {
settings.edit().putString("customSig" + clickedAccountName,
sigContent.getText().toString()).apply();
Crouton.showText(SettingsAccount.this, "Signature saved.", Theming.croutonStyle());
d.dismiss();
} else {
Crouton.showText(SettingsAccount.this,
"Signatures can only have 1 line break.",
Theming.croutonStyle(),
(ViewGroup) sigContent.getParent());
}
} else {
Crouton.showText(SettingsAccount.this,
"Signatures can only have a maximum of 160 characters.",
Theming.croutonStyle(),
(ViewGroup) sigContent.getParent());
}
}
});
}
});
d.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
updateAccountList();
removeDialog(MODIFY_ACCOUNT_DIALOG);
}
});
return d;
}
private NetDesc currentDesc;
/**
* onCompleted is called by the Future with the result or exception of the asynchronous operation.
*
* @param e Exception encountered by the operation
* @param result Result returned from the operation
*/
@Override
public void onCompleted(Exception e, Response<FinalDoc> result) {
if (e == null && result != null) {
Document doc = result.getResult().doc;
if (currentDesc == NetDesc.VERIFY_ACCOUNT_S1) {
String loginKey = doc.getElementsByAttributeValue("name", "key").attr("value");
HashMap<String, List<String>> loginData = new HashMap<String, List<String>>();
// "EMAILADDR", user, "PASSWORD", password, "path", lastPath, "key", key
loginData.put("EMAILADDR", Collections.singletonList(verifyUser));
loginData.put("PASSWORD", Collections.singletonList(verifyPass));
loginData.put("path", Collections.singletonList(Session.ROOT));
loginData.put("key", Collections.singletonList(loginKey));
currentDesc = NetDesc.VERIFY_ACCOUNT_S2;
accountVerifier.build(this)
.load("POST", Session.ROOT + "/user/login.html")
.setBodyParameters(loginData)
.as(new DocumentParser())
.withResponse()
.setCallback(SettingsAccount.this);
}
else if (currentDesc == NetDesc.VERIFY_ACCOUNT_S2) {
if (!result.getRequest().getUri().toString().endsWith("/user/login.html")) {
AccountManager.addUser(SettingsAccount.this, verifyUser, verifyPass);
dismissDialog(VERIFY_ACCOUNT_DIALOG);
removeDialog(ADD_ACCOUNT_DIALOG);
Crouton.showText(this, "Verification succeeded.", Theming.croutonStyle());
updateAccountList();
}
else {
dismissDialog(VERIFY_ACCOUNT_DIALOG);
Crouton.showText(this,
"Verification failed. Check your username and password and try again.",
Theming.croutonStyle(),
addAccWrapper);
}
}
}
else {
dismissDialog(VERIFY_ACCOUNT_DIALOG);
Crouton.showText(this, "Network connection failed. Check your network settings.", Theming.croutonStyle(), addAccWrapper);
}
}
}