package net.coding.program;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.EditText;
import android.widget.ImageView;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.tencent.android.tpush.XGPushManager;
import net.coding.program.common.Global;
import net.coding.program.common.LoginBackground;
import net.coding.program.common.SimpleSHA1;
import net.coding.program.common.enter.SimpleTextWatcher;
import net.coding.program.common.guide.GuideActivity;
import net.coding.program.common.network.MyAsyncHttpClient;
import net.coding.program.common.network.NetworkImpl;
import net.coding.program.common.ui.BaseActivity;
import net.coding.program.common.umeng.UmengEvent;
import net.coding.program.common.util.FileUtil;
import net.coding.program.common.util.InputCheck;
import net.coding.program.common.widget.LoginAutoCompleteEdit;
import net.coding.program.login.PhoneRegisterActivity_;
import net.coding.program.login.ZhongQiuGuideActivity;
import net.coding.program.login.auth.AuthInfo;
import net.coding.program.login.auth.TotpClock;
import net.coding.program.login.phone.InputAccountActivity_;
import net.coding.program.model.AccountInfo;
import net.coding.program.model.UserObject;
import net.coding.program.third.FastBlur;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.Extra;
import org.androidannotations.annotations.FocusChange;
import org.androidannotations.annotations.OnActivityResult;
import org.androidannotations.annotations.ViewById;
import org.apache.http.Header;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.util.Calendar;
@EActivity(R.layout.activity_login)
public class LoginActivity extends BaseActivity {
public static final String EXTRA_BACKGROUND = "background";
public static String HOST_USER = Global.HOST_API + "/user/key/%s";
private static String HOST_NEED_CAPTCHA = Global.HOST_API + "/captcha/login";
final float radius = 8;
final double scaleFactor = 16;
private final String TAG_LOGIN = "TAG_LOGIN";
final String HOST_USER_RELOGIN = "HOST_USER_RELOGIN";
final String HOST_USER_NEED_2FA = Global.HOST_API + "/check_two_factor_auth_code";
final private int RESULT_CLOSE = 100;
@Extra
Uri background;
@ViewById
ImageView userIcon, backgroundImage, imageValify;
@ViewById
LoginAutoCompleteEdit editName;
@ViewById
EditText editPassword, editValify, edit2FA;
@ViewById
View captchaLayout, loginButton, layout2fa, loginLayout, layoutRoot;
private int clickIconCount = 0;
private long lastClickTime = 0;
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.icon_user_monkey)
.showImageOnFail(R.drawable.icon_user_monkey)
.resetViewBeforeLoading(true)
.cacheOnDisk(true)
.imageScaleType(ImageScaleType.EXACTLY)
.bitmapConfig(Bitmap.Config.RGB_565)
.considerExifParams(true)
.displayer(new FadeInBitmapDisplayer(300))
.build();
View androidContent;
TextWatcher textWatcher = new SimpleTextWatcher() {
@Override
public void afterTextChanged(Editable s) {
upateLoginButton();
}
};
TextWatcher textWatcherName = new SimpleTextWatcher() {
@Override
public void afterTextChanged(Editable s) {
userIcon.setImageResource(R.drawable.icon_user_monkey);
// userIcon.setBackgroundResource(R.drawable.icon_user_monkey);
}
};
private String globalKey = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 调用下,防止收到上次登陆账号的通知
XGPushManager.registerPush(this, "*");
}
@AfterViews
void init() {
settingBackground();
needCaptcha();
editName.addTextChangedListener(textWatcher);
editPassword.addTextChangedListener(textWatcher);
editValify.addTextChangedListener(textWatcher);
upateLoginButton();
editName.addTextChangedListener(textWatcherName);
androidContent = findViewById(android.R.id.content);
androidContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int height = androidContent.getHeight();
if (height > 0) {
ViewGroup.LayoutParams lp = layoutRoot.getLayoutParams();
lp.height = height;
layoutRoot.setLayoutParams(lp);
androidContent.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
String lastLoginName = AccountInfo.loadLastLoginName(this);
if (!lastLoginName.isEmpty()) {
editName.setDisableAuto(true);
editName.setText(lastLoginName);
editName.setDisableAuto(false);
editPassword.requestFocus();
editName(false);
}
}
@Click
void userIcon() {
long clickTime = Calendar.getInstance().getTimeInMillis();
long lastTemp = lastClickTime;
lastClickTime = clickTime;
if (clickTime - lastTemp < 1000) {
++clickIconCount;
} else {
clickIconCount = 1;
}
if (clickIconCount >= 5) {
clickIconCount = 0;
AlertDialog.Builder builder = new AlertDialog.Builder(this);
View content = getLayoutInflater().inflate(R.layout.host_setting, null);
final EditText editText = (EditText) content.findViewById(R.id.edit);
final EditText editCode = (EditText) content.findViewById(R.id.editCode);
AccountInfo.CustomHost customHost = AccountInfo.getCustomHost(this);
editText.setText(customHost.getHost());
editCode.setText(customHost.getCode());
editText.setHint(Global.DEFAULT_HOST);
builder.setView(content)
.setPositiveButton(R.string.action_ok, (dialog, which) -> {
String hostString = editText.getText().toString();
String hostCode = editCode.getText().toString();
AccountInfo.CustomHost customHost1 = new AccountInfo.CustomHost(hostString, hostCode);
if (!hostString.isEmpty()) {
AccountInfo.saveCustomHost(this, customHost1);
} else {
AccountInfo.removeCustomHost(this);
}
AccountInfo.loginOut(this);
setResult(RESULT_OK);
finish();
})
.setNegativeButton(R.string.action_cancel, null)
.show();
}
}
private void settingBackground() {
try {
BitmapDrawable bitmapDrawable;
if (ZhongQiuGuideActivity.isZhongqiu()) {
bitmapDrawable = createBlur(R.drawable.zhongqiu_init_photo);
} else {
if (background == null) {
LoginBackground.PhotoItem photoItem = new LoginBackground(this).getPhoto();
File file = photoItem.getCacheFile(this);
if (file.exists()) {
background = Uri.fromFile(file);
}
}
if (background == null) {
bitmapDrawable = createBlur(R.drawable.entrance1);
} else {
bitmapDrawable = createBlur(background);
}
}
backgroundImage.setImageDrawable(bitmapDrawable);
} catch (Exception e) {
Global.errorLog(e);
}
}
private BitmapDrawable createBlur(int bgId) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), bgId, options);
int height = options.outHeight;
int width = options.outWidth;
options.outHeight = (int) (height / scaleFactor);
options.outWidth = (int) (width / scaleFactor);
options.inSampleSize = (int) (scaleFactor + 0.5);
options.inJustDecodeBounds = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inMutable = true;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.entrance1, options);
Bitmap blurBitmap = FastBlur.doBlur(bitmap, (int) radius, true);
return new BitmapDrawable(getResources(), blurBitmap);
}
private BitmapDrawable createBlur(Uri uri) {
String path = FileUtil.getPath(this, uri);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
int height = options.outHeight;
int width = options.outWidth;
options.outHeight = (int) (height / scaleFactor);
options.outWidth = (int) (width / scaleFactor);
options.inSampleSize = (int) (scaleFactor + 0.5);
options.inJustDecodeBounds = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inMutable = true;
Bitmap bitmap = BitmapFactory.decodeFile(path, options);
Bitmap blurBitmap = FastBlur.doBlur(bitmap, (int) radius, true);
return new BitmapDrawable(getResources(), blurBitmap);
}
@Click
void imageValify() {
editValify.requestFocus();
downloadValifyPhoto();
}
@Click
void register() {
Global.popSoftkeyboard(this, editName, false);
PhoneRegisterActivity_.intent(this)
.startForResult(RESULT_CLOSE);
}
@OnActivityResult(RESULT_CLOSE)
void resultRegiter(int result) {
if (result == Activity.RESULT_OK) {
sendBroadcast(new Intent(GuideActivity.BROADCAST_GUIDE_ACTIVITY));
finish();
}
}
private void needCaptcha() {
getNetwork(HOST_NEED_CAPTCHA, HOST_NEED_CAPTCHA);
}
private void downloadValifyPhoto() {
String host = Global.HOST_API + "/getCaptcha";
AsyncHttpClient client = MyAsyncHttpClient.createClient(this);
client.get(host, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
imageValify.setImageBitmap(BitmapFactory.decodeByteArray(responseBody, 0, responseBody.length));
editValify.setText("");
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
showMiddleToast("获取验证码失败");
}
});
}
@Click
protected final void loginButton() {
if (layout2fa.getVisibility() == View.GONE) {
login();
} else {
login2fa();
}
}
private void login2fa() {
String input = edit2FA.getText().toString();
if (input.isEmpty()) {
showMiddleToast("请输入身份验证器中的验证码");
return;
}
RequestParams params = new RequestParams();
params.put("code", input);
postNetwork(HOST_USER_NEED_2FA, params, HOST_USER_NEED_2FA);
showProgressBar(true, "登录中");
Global.popSoftkeyboard(this, edit2FA, false);
}
private void login() {
try {
String name = editName.getText().toString();
String password = editPassword.getText().toString();
String captcha = editValify.getText().toString();
if (name.isEmpty()) {
showMiddleToast("邮箱或用户名不能为空");
return;
}
if (password.isEmpty()) {
showMiddleToast("密码不能为空");
return;
}
RequestParams params = new RequestParams();
params.put("password", SimpleSHA1.sha1(password));
if (captchaLayout.getVisibility() == View.VISIBLE) {
params.put("j_captcha", captcha);
}
params.put("remember_me", true);
String HOST_LOGIN = Global.HOST_API + "/v2/account/login";
params.put("account", name);
postNetwork(HOST_LOGIN, params, TAG_LOGIN);
showProgressBar(true, R.string.logining);
Global.popSoftkeyboard(this, editName, false);
} catch (Exception e) {
Global.errorLog(e);
}
}
@Click
protected final void loginFail() {
String account = editName.getText().toString();
if (!InputCheck.isPhone(account) && !InputCheck.isEmail(account)) {
account = "";
}
InputAccountActivity_.intent(LoginActivity.this).account(account).start();
}
@Click
protected final void login_2fa() {
Global.start2FAActivity(this);
}
private void show2FA(boolean show) {
if (show) {
layout2fa.setVisibility(View.VISIBLE);
loginLayout.setVisibility(View.GONE);
String uri = AccountInfo.loadAuth(this, globalKey);
if (!uri.isEmpty()) {
String code2FA = new AuthInfo(uri, new TotpClock(this)).getCode();
edit2FA.getText().insert(0, code2FA);
loginButton();
}
} else {
layout2fa.setVisibility(View.GONE);
loginLayout.setVisibility(View.VISIBLE);
}
}
@Override
public void parseJson(int code, JSONObject respanse, String tag, int pos, Object data) throws JSONException {
if (tag.equals(TAG_LOGIN)) {
if (code == 0) {
MainActivity.setNeedWarnEmailNoValidLogin();
loginSuccess(respanse);
umengEvent(UmengEvent.USER, "普通登陆");
} else if (code == 3205) {
MainActivity.setNeedWarnEmailNoValidLogin();
umengEvent(UmengEvent.USER, "2fa登陆");
globalKey = respanse.optJSONObject("msg").optString("two_factor_auth_code_not_empty", "");
show2FA(true);
showProgressBar(false);
} else {
loginFail(code, respanse, true);
}
} else if (tag.equals(HOST_USER_NEED_2FA)) {
if (code == 0) {
loginSuccess(respanse);
} else {
loginFail(code, respanse, false);
}
} else if (tag.equals(HOST_USER)) {
if (code == 0) {
showProgressBar(false);
UserObject user = new UserObject(respanse.getJSONObject("data"));
AccountInfo.saveAccount(this, user);
MyApp.sUserObject = user;
AccountInfo.saveReloginInfo(this, user);
Global.syncCookie(this);
String name = editName.getText().toString();
AccountInfo.saveLastLoginName(this, name);
sendBroadcast(new Intent(GuideActivity.BROADCAST_GUIDE_ACTIVITY));
finish();
startActivity(new Intent(LoginActivity.this, MainActivity_.class));
} else {
showProgressBar(false);
showErrorMsg(code, respanse);
}
} else if (tag.equals(HOST_NEED_CAPTCHA)) {
if (code == 0) {
if (respanse.getBoolean("data")) {
captchaLayout.setVisibility(View.VISIBLE);
downloadValifyPhoto();
}
} else {
showErrorMsg(code, respanse);
}
} else if (tag.equals(HOST_USER_RELOGIN)) {
if (code == 0) {
UserObject user = new UserObject(respanse.getJSONObject("data"));
imagefromNetwork(userIcon, user.avatar, options);
}
}
}
private void loginFail(int code, JSONObject respanse, boolean needCaptcha) {
String msg = Global.getErrorMsg(respanse).replaceAll("<li>(.*?)</li>", "\n$1");
showMiddleToast(msg);
showProgressBar(false);
if (code != NetworkImpl.NETWORK_ERROR &&
code != NetworkImpl.NETWORK_ERROR_SERVICE &&
needCaptcha) {
needCaptcha();
}
}
private void loginSuccess(JSONObject respanse) throws JSONException {
UserObject user = new UserObject(respanse.getJSONObject("data"));
getNetwork(String.format(HOST_USER, user.global_key), HOST_USER);
showProgressBar(true, R.string.logining);
}
@Override
public void onBackPressed() {
if (layout2fa.getVisibility() == View.GONE) {
finish();
} else {
show2FA(false);
}
}
@FocusChange
void editName(boolean hasFocus) {
if (hasFocus) {
return;
}
String name = editName.getText().toString();
if (name.isEmpty()) {
return;
}
String global = AccountInfo.loadRelogininfo(this, name);
if (global.isEmpty()) {
return;
}
getNetwork(String.format(HOST_USER, global), HOST_USER_RELOGIN);
}
private void upateLoginButton() {
if (editName.getText().length() == 0) {
loginButton.setEnabled(false);
return;
}
if (editPassword.getText().length() == 0) {
loginButton.setEnabled(false);
return;
}
if (captchaLayout.getVisibility() == View.VISIBLE &&
editValify.getText().length() == 0) {
loginButton.setEnabled(false);
return;
}
loginButton.setEnabled(true);
}
}