package jp.agentec.abook.abv.ui.common.activity;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.LayoutInflater.Factory;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.TextView;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;

import jp.agentec.abook.abv.bl.acms.type.LoginMode;
import jp.agentec.abook.abv.bl.acms.type.RequirePasswordChangeCode;
import jp.agentec.abook.abv.bl.acms.type.SecurityPolicyType;
import jp.agentec.abook.abv.bl.common.ABVEnvironment;
import jp.agentec.abook.abv.bl.common.Constant;
import jp.agentec.abook.abv.bl.common.constant.ABookKeys;
import jp.agentec.abook.abv.bl.common.exception.ABVException;
import jp.agentec.abook.abv.bl.common.exception.AcmsException;
import jp.agentec.abook.abv.bl.common.exception.NetworkDisconnectedException;
import jp.agentec.abook.abv.bl.common.log.Logger;
import jp.agentec.abook.abv.bl.data.ABVDataCache;
import jp.agentec.abook.abv.bl.data.dao.AbstractDao;
import jp.agentec.abook.abv.bl.data.dao.AcmsDao;
import jp.agentec.abook.abv.bl.dto.AcmsDto;
import jp.agentec.abook.abv.bl.logic.AbstractLogic;
import jp.agentec.abook.abv.bl.logic.ContentLogic;
import jp.agentec.abook.abv.bl.logic.ContractLogic;
import jp.agentec.abook.abv.bl.logic.UserAuthenticateLogic;
import jp.agentec.abook.abv.cl.helper.ABVUncaughtExceptionHandler;
import jp.agentec.abook.abv.cl.util.PreferenceUtil;
import jp.agentec.abook.abv.launcher.android.ABVApplication;
import jp.agentec.abook.abv.launcher.android.ABVUIDataCache;
import jp.agentec.abook.abv.launcher.android.R;
import jp.agentec.abook.abv.ui.common.appinfo.AppDefType;
import jp.agentec.abook.abv.ui.common.appinfo.AppDefType.PrefName;
import jp.agentec.abook.abv.ui.common.appinfo.AppDefType.UserPrefKey;
import jp.agentec.abook.abv.ui.common.constant.ErrorCode;
import jp.agentec.abook.abv.ui.common.constant.ErrorMessage;
import jp.agentec.abook.abv.ui.common.constant.NaviConsts;
import jp.agentec.abook.abv.ui.common.dialog.ABookAlertDialog;
import jp.agentec.abook.abv.ui.common.util.AlertDialogUtil;
import jp.agentec.abook.abv.ui.common.util.Initializer;
import jp.agentec.abook.abv.ui.common.util.PatternStringUtil;
import jp.agentec.abook.abv.ui.home.activity.ChangePasswordActivity;
import jp.agentec.abook.abv.ui.home.activity.LoginActivity;
import jp.agentec.abook.abv.ui.home.helper.ABookPermissionHelper;
import jp.agentec.abook.abv.ui.home.helper.ActivityHandlingHelper;
import jp.agentec.adf.util.DateTimeUtil;
import jp.agentec.adf.util.DateTimeUtil.DateUnit;
import jp.agentec.adf.util.StringUtil;


/**
 * Activityの最上位クラスです。
 * @author Taejin Hong
 * @version 1.1.1
 *
 */
public abstract class ABVActivity extends Activity {
	private final static String TAG = "ABVActivity";

	protected static ContentLogic contentLogic = AbstractLogic.getLogic(ContentLogic.class);
	protected ProgressDialog progressDialog = null; // TODO: later ProgressDialogHelperへ
	public ProgressDialog progressDialogHorizontal = null;
	protected Handler handler = new Handler();
	protected AlertDialog mAlertDialog = null;

	private static boolean IsAppPaused = false;
	private static boolean IsAppVisible = false;
	private static boolean isVisible = false;

	public static final String CID="cid";
	public static final String PAGE="page";
	public static final String URL = "url";
	public static final String MESSAGE = "message";
	public static final String PASSWORD = "password";

	protected static final int FP = android.view.ViewGroup.LayoutParams.MATCH_PARENT;
	protected static final int WC = android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
	protected static final int R_FP = ViewGroup.LayoutParams.MATCH_PARENT;

	private HomeButtonReceiver mHomeButtonReceiver;
	protected Uri imageUri;
	private class HomeButtonReceiver extends BroadcastReceiver {

		@Override
		public void onReceive(Context context, Intent intent) {
			onClickHomeButton();
		}
	}

	@Override
	protected void onUserLeaveHint() {
		super.onUserLeaveHint();
		// Homeボタンを押した場合orActivityが他のActivityによって隠れた場合のイベントをチェック
		Logger.i(TAG, "onUserLeaveHint");
		saveLeaveAppTime();
	}

	protected void onClickHomeButton() {
		// 必要に応じてオーバーライドする
		Logger.d(TAG, "[onClickHomeButton]");
	}


	private void printLog(String name) {
		Logger.d(TAG, "%s:%s", name, getClass().getName());
	}

	public void showProgressView(String message) {
		_closeProgressPopup();
		if (!isFinishing() && progressDialogHorizontal != null && !progressDialogHorizontal.isShowing()) {
			if (message != null) {
				progressDialogHorizontal.setMessage(message);
			}
			progressDialogHorizontal.show();
			Logger.d(TAG, "-------------------------progressDialogHorizontal show");
		}
	}
	public void showProgressPopup(String msg) {
		if (!isFinishing() && progressDialog != null && !progressDialog.isShowing()) {
			Logger.d(TAG, "-------------------------showProgressPopup");
			printLog("showProgressPopup");
			if(msg != null) {
				progressDialog.setMessage(msg);
			}
			progressDialog.show();
		}
	}

	/**
	 * 同期進捗のプログレスバーインジケーターが表示状態かをチェックする
	 * @return true:表示、false:非表示
	 */
	public boolean progressDialogHorizontalShowing() {
		if (!isFinishing() && progressDialogHorizontal != null && !progressDialogHorizontal.isShowing()) {
			return false;
		}
		return true;
	}

	public void showProgressPopup() {
		showProgressPopup(getResources().getString(R.string.progress));
	}

	public void closeProgressPopup() {
		handler.post(new Runnable() {
			@Override
			public void run() {
				_closeProgressPopup();
			}
		});
	}

	private void _closeProgressPopup() {
		if (progressDialog != null && progressDialog.isShowing()) { // !isFinishing()の判定は削除
			printLog("closeProgressPopup");
			try {
				progressDialog.dismiss();
			}
			catch (Exception e) {
				Logger.e(TAG, "_closeProgressPopup error. " +e.toString());
			}
		}
		if (progressDialogHorizontal != null && progressDialogHorizontal.isShowing()) { // !isFinishing()の判定は削除
			printLog("closeProgressPopup progressDialogHorizontal");
			try {
				progressDialogHorizontal.setProgress(0);
				progressDialogHorizontal.dismiss();
			}
			catch (Exception e) {
				Logger.e(TAG, "_closeProgressPopup error. progressDialogHorizontal error = " +e.toString());
			}
		}
	}

	protected void showAlertDialog(AlertDialog alertDialog) {
		if (this.mAlertDialog != null && this.mAlertDialog.isShowing()) {
			this.mAlertDialog.dismiss();
		}
		this.mAlertDialog = alertDialog;
		this.mAlertDialog.show();
	}

	private void closeAlertDialog() {
		if (mAlertDialog != null && mAlertDialog.isShowing()) {
			mAlertDialog.dismiss();
		}
	}

	public void handleErrorMessageToast(final Object error) {
		handler.post(new Runnable() {
			@Override
			public void run() {
				ErrorMessage.showErrorMessageToast(ABVActivity.this, error);
			}
		});
	}

	protected void handleErrorMessageDialog(final int title, final ErrorCode error) {
		handler.post(new Runnable() {
			@Override
			public void run() {
				ErrorMessage.showErrorMessageDialog(ABVActivity.this, title, error);
			}
		});
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		isVisible = true;
		requestWindowFeature(Window.FEATURE_NO_TITLE);

		configureKeepScreen();

		Initializer initializer = Initializer.getInstance();
		initializer.initDB(); // DBは毎回必ずopen確認を行う。

		if (Logger.isDebugEnabled()) {
			logRunningTaskInfo();
		}

		if (progressDialog == null) {
			progressDialog = new ProgressDialog(this);
            if (progressDialog.getWindow() != null) {
                progressDialog.setMessage(getResources().getString(R.string.progress));
                progressDialog.setIndeterminate(true);
                progressDialog.setCancelable(false);
				progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); //インジケータ表示
                progressDialog.getWindow().setFormat(PixelFormat.TRANSPARENT);
            }
		}

		if (progressDialogHorizontal == null) {
			progressDialogHorizontal = new ProgressDialog(this);
			if (progressDialogHorizontal.getWindow() != null) {
				progressDialogHorizontal.setIndeterminate(false);
				progressDialogHorizontal.setMax(100); // 最大値を設定
				progressDialogHorizontal.setCancelable(false);
				progressDialogHorizontal.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); //プログレスバー表示
				progressDialogHorizontal.getWindow().setFormat(PixelFormat.TRANSPARENT);
			}
		}

		setFixedOrientation(false);
	}

	protected boolean isRotatable() {
		try {
			// OSの設定で回転ONで、かつ設定で回転固定にしていない場合
			return Settings.System.getInt(getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 1;
		} catch (SettingNotFoundException e) {
			Logger.e(TAG, "onCreate error.", e);
			return false;
		}
	}

	protected void configureKeepScreen() {
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
	}

	public void logRunningTaskInfo() {
		ActivityManager m = (ActivityManager) ABVActivity.this.getSystemService(Context.ACTIVITY_SERVICE);
		//noinspection deprecation(API21から非推奨になった。無視)
		ArrayList<ActivityManager.RunningTaskInfo> tList = (ArrayList<RunningTaskInfo>) m.getRunningTasks(10);
		for (ActivityManager.RunningTaskInfo info : tList) {
			int cnt = info.numActivities;
			int id = info.id;
			int n = info.numRunning;
			String t = info.topActivity.getClassName();
			String cName = info.baseActivity.getClassName();
			Logger.v(TAG, String.format("RunningTaskInfo ID[%3d] ROOT[%30s] num[%2d] run[%2d] TOP[%30s]", id, cName, cnt, n, t));
		}
	}


	@Override
	protected void onResume() {
		super.onResume();

        sendBroadcast(new Intent("jp.agentec.abook.saas.signage.on"));
		getABVUIDataCache().visibleActivityName = getClass().getName();
		isVisible = true;
	}

	@Override
	protected void onPause() {
		super.onPause();
        sendBroadcast(new Intent("jp.agentec.abook.saas.signage.off"));
		closeAlertDialog();
		isVisible = false;
		if (mHomeButtonReceiver != null) {
			unregisterReceiver(mHomeButtonReceiver);
		}
	}

	protected void startActivity(Intent intend, NaviConsts ABVNavi) {
        super.startActivity(intend);
        ActivityHandlingHelper.transitionNavi(this, ABVNavi);
    }

	protected void startActivityForResult(Intent intend,int requestCode, NaviConsts ABVNavi) {
        super.startActivityForResult(intend,requestCode);
        ActivityHandlingHelper.transitionNavi(this, ABVNavi);
    }

	@Override
	public boolean onPrepareOptionsMenu(Menu menu)
	{
		setMenuBackground(menu);
		return super.onPrepareOptionsMenu(menu);
	}

	protected void setMenuBackground(Menu menu) {
	    LayoutInflater service = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
	    final Factory orgFactory = service.getFactory();
	    if (orgFactory == null) {
	        final Factory factory = new Factory() {
	            @Override
				public View onCreateView(String name, Context context, AttributeSet attrs) {

	            if (name.equals("com.android.internal.view.menu.IconMenuView")) {
	                try {
	                    ClassLoader cl = getClassLoader();
	                    Class<?> clazz;
	                    clazz = cl.loadClass("com.android.internal.view.menu.IconMenuView");
	                    Constructor<?> constructor = clazz.getConstructor(Context.class, AttributeSet.class);
	                    Object view = constructor.newInstance(context, attrs);
	                    View vg = null;
                    	if (view instanceof View) {
                    		vg = (View)view;
                    		vg.setBackgroundColor(Color.BLACK);
                    	}
	                    return vg;
	                }
	                catch (ClassNotFoundException e) {
	        			Logger.w(TAG, e);
	                } catch (SecurityException e) {
	        			Logger.w(TAG, e);
	                } catch (NoSuchMethodException e) {
	        			Logger.w(TAG, e);
	                } catch (IllegalArgumentException e) {
	        			Logger.w(TAG, e);
	                } catch (InstantiationException e) {
	        			Logger.w(TAG, e);
	                } catch (IllegalAccessException e) {
	        			Logger.w(TAG, e);
	                } catch (InvocationTargetException e) {
	        			Logger.w(TAG, e);
					}
	            }
	            return null;
	         }
	      };
	      service.setFactory(factory);
	    }

		for (int i = 0 ; i < menu.size(); i++) {
			MenuItem item = menu.getItem(i);
			try {
				Class<?> c = item.getClass();
				Class<?>[] paramTypesGetItemView = { int.class, ViewGroup.class };
				Method method = c.getDeclaredMethod("getItemView", paramTypesGetItemView);
				method.setAccessible(true);
				TextView view = (TextView) method.invoke(item, 0, null);
				view.setTextColor(Color.WHITE);
			} catch (SecurityException e) {
    			Logger.w(TAG, e);
			} catch (NoSuchMethodException e) {
    			//Logger.w(Tag, e);
			} catch (IllegalArgumentException e) {
    			Logger.w(TAG, e);
			} catch (IllegalAccessException e) {
    			Logger.w(TAG, e);
			} catch (InvocationTargetException e) {
    			Logger.w(TAG, e);
			}
		}
	}


	@Override
	public boolean onKeyUp(int keyCode, KeyEvent event) {
		boolean eventPrevent = false;

		switch(keyCode) {
		case KeyEvent.KEYCODE_BACK:

        	super.finish();
            overridePendingTransition(R.anim.viewin_right_to_left, R.anim.viewout_right_to_left);

	        eventPrevent = true;
		}

        return eventPrevent;
	}

	@Override
	public void onLowMemory() {
		Logger.d(TAG, "★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★");
		Logger.w(TAG, "★★★★★★★★★★★★★★★★★　onLowMemory　★★★★★★★★★★★★★★★★★★★");
		Logger.d(TAG, "★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★");

		ABVUncaughtExceptionHandler.getInstancer().onLowMemory();
	}

	@Override
	protected void onStop() {
		super.onStop();

		if (getClass().getName().equals(getABVUIDataCache().visibleActivityName)) {
//			IsAppPaused = !IsAppVisible;
			IsAppPaused = true;
		}

	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		saveLeaveAppTime();
	}

	@Override
	public void onWindowFocusChanged (boolean hasFocus) {

		if (getClass().getName().equals(getABVUIDataCache().visibleActivityName)) {
			//Logger.d("focus", getClass().getName() + " " + hasFocus);
			IsAppVisible = hasFocus;

			if (IsAppPaused) {
				new Handler().post(new Runnable() {
					@Override
					public void run() {
						onApplicationBroughtFromBackground();
					}
				});
			}

			//	このイベントは、onResumeの後、onPauseの前に発生する。hasFocusはActivityが画面の最上段に表示されているのかを示す。
			//	アプリは複数のActivityで構成されている。
			//	AというActivityからbというActivityに遷移する際、AのhasFocusがfalseになってからBのhasFocusがtrueになる。
			//	つまり、Activity間の遷移により、hasFocusはfalseになったりtrueになったりするが、
			//	最終的にtrueになったということは、アプリ自体は画面に表示されていることを示す。
			//	falseの状態で、onStopが呼び出されると、このアプリはバックグラウンドになったが、またが終了したことを示す。
			if (IsAppVisible) {
				IsAppPaused = false;
			}
		}
	}

	protected void onApplicationBroughtFromBackground() {
	}
	//Splash画面のパスワード変更する時ダイアログからイベントもらうため
	protected void onPasswordChanged() {
	}

	/**
	 * 前回の端末利用から一定期間が経っているかどうかチェックする
	 * @return true：認証有効 false：認証無効
	 */
	protected boolean checkValidAuthTime() {
		boolean result = false;
		try {
			// サービスオプションチェック
			if (AbstractLogic.getLogic(ContractLogic.class).getForceLoginPeriodically()) {
				long leavedAppTime = getUserPref(UserPrefKey.LEAVE_APP, -1L);
				if (leavedAppTime != -1) {
					Date leavedAppDate = new Date(leavedAppTime);
					Date currentDate = new Date(System.currentTimeMillis());
					if (currentDate.after(DateTimeUtil.add(leavedAppDate, DateUnit.Day, ABVEnvironment.LastLoginExpiryDate))) {
						callLoginActivity(false, true, false);
						result = true;
					}
				}
			}
		} catch (Exception e) {
			result = false;
			Logger.e("Exception LoginTimeOutCheck", e);
		}
		return result;
	}

    // 一定期間経過後強制ログアウトチェック
    protected boolean checkForceOfflineLogout() {
        boolean result = false;
        ContractLogic contractLogic;
        contractLogic = AbstractLogic.getLogic(ContractLogic.class);
        if (contractLogic.getForceOfflineLogout()) {
            UserAuthenticateLogic service = AbstractLogic.getLogic(UserAuthenticateLogic.class);
            Date serverDate;
            try {
                serverDate = service.getServerTime();
            } catch (NetworkDisconnectedException e) {
                // ネットワーク非接続状態の場合、ローカル時刻を入れる
                serverDate = DateTimeUtil.getCurrentDate();
            } catch (AcmsException e) {
                Logger.e("Exception checkForceOfflineLogout", e);
                return false;
            }
            Date lastCmsAccessDate = ABVDataCache.getInstance().getMemberInfo().lastCMSAccessDate;
            Logger.d(TAG, "checkForceOfflineLogout():lastCmsAccessDate=" + lastCmsAccessDate);
            if (lastCmsAccessDate != null && serverDate != null &&
                    serverDate.after(DateTimeUtil.add(lastCmsAccessDate, DateUnit.Day, contractLogic.getForceOfflineWait()))) {
                callLoginActivity(false, false, true);
                result = true;
            }
        }
        return result;
    }

	// パスワード定期変更チェック
	protected boolean checkRequiredChangePassword(final DialogInterface.OnClickListener cancelListener) {
		boolean result = false;
		try {
			// パスワード変更必要のチェックをサービスオプションの確認後に行うように修正
			// ただし、チェックが必要になった場合、起動時のネットワークの遅延によるANRが発生する懸念はまだある
			ContractLogic contractService = AbstractLogic.getLogic(ContractLogic.class);
			ABookAlertDialog changePwDialog = AlertDialogUtil.createAlertDialog(this, R.string.pwd_change);
			final SecurityPolicyType securityPolicyType = contractService.getForcePwChangePeriodically();
			if (securityPolicyType == SecurityPolicyType.None) {
				return false;
			} else {
				UserAuthenticateLogic service = AbstractLogic.getLogic(UserAuthenticateLogic.class);
				if (service.requirePasswordChange() == RequirePasswordChangeCode.Required) {
					if (securityPolicyType == SecurityPolicyType.Reminder) {
						// 既に今日通知済みの場合またはパスワード変更画面では表示しない
						if (!contractService.isTodayLastAnnounceChangePasswordDate() && !(this instanceof ChangePasswordActivity)) {
							changePwDialog.setMessage(R.string.pwd_change_reminder_message);
							changePwDialog.setNegativeButton(R.string.no, cancelListener);
						} else {
							changePwDialog = null;
						}
					} else if (securityPolicyType == SecurityPolicyType.Enforcement) {
						changePwDialog.setMessage(R.string.pwd_change_reminder_enforcement_message);
						changePwDialog.setCancelable(false);
					} else {
						changePwDialog = null;
					}

					if (changePwDialog != null) {
						changePwDialog.setPositiveButton(R.string.pwd_change, new DialogInterface.OnClickListener() {
							@Override
							public void onClick(DialogInterface dialog, int whichButton) {
								final String loginId = ABVDataCache.getInstance().getMemberInfo().loginId;
								showChangePasswordDialog(R.string.pwd_change, securityPolicyType, loginId, null, cancelListener);
							}
						});
						result = true;
						showAlertDialog(changePwDialog);
					}
				}
			}
		} catch (Exception e) {
			result = false;
			Logger.e(TAG, "checkRequiredChangePassword failed.", e);
		}
		return result;
	}

	private void showChangePasswordDialog(final int title, final SecurityPolicyType securityPolicyType, final String loginId, final String password, final DialogInterface.OnClickListener cancelListener) {
		ABookAlertDialog passwordChangeDialog = AlertDialogUtil.createAlertDialog(this, title);
		View passwordChangeView = null;

    	switch (securityPolicyType) {
		case Reminder:
			passwordChangeView = getLayoutInflater().inflate(R.layout.ac_setting_password_change, null);
			passwordChangeDialog.setView(passwordChangeView);
			passwordChangeDialog.setNegativeButton(R.string.no, cancelListener);
			break;
		case Enforcement:
			passwordChangeView = getLayoutInflater().inflate(R.layout.ac_setting_password_change_enforcement, null);
			EditText edtLoginId = (EditText)passwordChangeView.findViewById(R.id.edt_id);
			edtLoginId.setText(loginId);
			passwordChangeDialog.setCancelable(false);
			passwordChangeDialog.setView(passwordChangeView);
			break;
		case None:
			break;
		default:
			break;
		}

		final EditText edtPwdNow = (EditText) (passwordChangeView != null ? passwordChangeView.findViewById(R.id.edt_pwd_now) : null);
		final EditText edtPwdNew = (EditText) (passwordChangeView != null ? passwordChangeView.findViewById(R.id.edt_pwd_new) : null);
		final EditText edtPwdReNew = (EditText) (passwordChangeView != null ? passwordChangeView.findViewById(R.id.edt_pwd_renew) : null);

		passwordChangeDialog.setNeutralButton(R.string.pwd_change, new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int whichButton) {
				String password_now = edtPwdNow != null ? edtPwdNow.getText().toString() : null;
				String password_new = edtPwdNew != null ? edtPwdNew.getText().toString() : null;
				String password_renew = edtPwdReNew != null ? edtPwdReNew.getText().toString() : null;

				if (StringUtil.isNullOrEmpty(password_now)) {
					showChangePasswordDialog(R.string.E101, securityPolicyType, loginId, password, cancelListener);
					return ;
				}
				if (StringUtil.isNullOrEmpty(password_new)) {
					showChangePasswordDialog(R.string.E102, securityPolicyType, loginId, password, cancelListener);
					return;
				}
				if (StringUtil.isNullOrEmpty(password_renew)) {
					showChangePasswordDialog(R.string.E103, securityPolicyType, loginId, password, cancelListener);
					return;
				}
				if (!password_new.equals(password_renew)) {
					showChangePasswordDialog(R.string.E104, securityPolicyType, loginId, password, cancelListener);
					return;
				}

	   		 	try {
					UserAuthenticateLogic userservice = AbstractLogic.getLogic(UserAuthenticateLogic.class);
					if(userservice.changePassword(edtPwdNow.getText().toString(), edtPwdNew.getText().toString(), false)){
						onPasswordChanged();
					}
				} catch (NetworkDisconnectedException e) {
					Logger.e("NetworkDisconnectedException", e);
					handleErrorMessageToast(ErrorCode.NETWORK);
					showChangePasswordDialog(R.string.pwd_change, securityPolicyType, loginId, password, cancelListener);
				} catch (ABVException e) {
					Logger.e("ABVException", e.toString());
					handleErrorMessageToast(ErrorMessage.getErrorCode(e));
					showChangePasswordDialog(R.string.pwd_change, securityPolicyType, loginId, password, cancelListener);
				} catch (IllegalArgumentException e) {
					Logger.e("IllegalArgumentException", e);
					handleErrorMessageToast(ErrorCode.E109);
					showChangePasswordDialog(R.string.pwd_change, securityPolicyType, loginId, password, cancelListener);
				} catch (Exception e) {
					Logger.e("Exception ", e);
					handleErrorMessageToast(ErrorCode.E107);
					showChangePasswordDialog(R.string.pwd_change, securityPolicyType, loginId, password, cancelListener);
				}
			}
		});

		showAlertDialog(passwordChangeDialog);
	}


	/**
	 * ログインActivityを呼び出します。
	 * @param closeCurrentActivity trueに設定しると、ログインActivityの呼び出し後、現在のActivityを閉じます。
	 * @param limitLogin 定期パスワード変更に関するメッセージを表示するにはtrueを設定します。
	 * @param forceLogout アプリロックに関するメッセージを表示するにはtrueを設定します。
	 * @since 1.1.1
	 * @author Taejin Hong
	 */
	protected void callLoginActivity(boolean closeCurrentActivity, boolean limitLogin, boolean forceLogout) {
		// TODO later int callLoginType = status:normal(0),  limitLogin(1), forceLogout(2)
		try {
			// modify by Jang 2013.06.20
			UserAuthenticateLogic user = AbstractLogic.getLogic(UserAuthenticateLogic.class);
			// ログイン情報がある場合のみログアウト処理を行う
			if (user.getMemberInfo() != null) {
				if (limitLogin) {
					// 一定期間経過後アプリロック
					user.limitLoginSignoutUser();
				} else if (forceLogout) {
					// 一定期間経過後強制ログアウト
					user.forceSignoutUser();
				} else {
					user.signoutUser();
				}
			}
		} catch (Exception e) {
			Logger.w("signoutUser failed at callLoginActivity", e);
		}

		Intent intent = new Intent(this, LoginActivity.class);
		intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
		startActivity(intent);
		if (closeCurrentActivity) {
			finish();
		}
	}

	protected ABVUIDataCache getABVUIDataCache() {
		return getABVApplication().getABVUIDataCache();
	}

	public ABVApplication getABVApplication() {
		return (ABVApplication) getApplication();
	}

	/**
	 * 携帯（SP）端末か確認
	 * @return true 携帯端末
	 */
	public boolean isNormalSize() {
		return (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_NORMAL;
	}

	public boolean isOrientationPortrait() {
		return getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
	}

	/**
	 * * 画面の回転を現在の向きで固定・解除する
	 *
	 * @param flg
	 *            true:回転固定 false:回転可能
	 */
	protected void setFixedOrientation(boolean flg) {
		if (flg) {
			int rotation = getWindowManager().getDefaultDisplay().getRotation();
			if (isOrientationPortrait()) {
				if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270) {
					setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
				} else {
					setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
				}
			} else {
				if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_0) {
					setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
				} else {
					setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
				}
			}
		} else {
			setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
		}
	}

	protected void setPortraitIfNormal() {
		if(isNormalSize()){
			setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		}
	}

	protected String getRString(int id) {
		return getResources().getString(id);
	}

	protected int getRInteger(int id) {
		return getResources().getInteger(id);
	}

	protected String[] getRStringArray(int id) {
		return getResources().getStringArray(id);
	}

	protected boolean getRBoolean(int id) {
		return getResources().getBoolean(id);
	}

	protected Drawable getRDrawable(int id) {
		return getResources().getDrawable(id);
	}

	protected int getRColor(int id) {
		return getResources().getColor(id);
	}

	protected int getRDimensionSize(int id) {
		return getResources().getDimensionPixelOffset(id);
	}


	protected int convertDensitySize(int size) {
		return (int)(getResources().getDisplayMetrics().density * size);
	}

	/**
	 * アプリを終了orバックグラウンドに行った場合の時間を記録
	 */
	protected void saveLeaveAppTime() {
		Logger.d(TAG, "saveLeaveAppTime()");
		PreferenceUtil.putUserPref(this, UserPrefKey.LEAVE_APP, System.currentTimeMillis());
	}

	public void showSimpleAlertDialog(final int titleResId, final int bodyResId) {
		showSimpleAlertDialog(getString(titleResId), getString(bodyResId));
	}

	public void showSimpleAlertDialog(final String title, final String body) {
		handler.postDelayed(new Runnable() {
			@Override
			public void run() {
				final ABookAlertDialog alertDialog = AlertDialogUtil.createAlertDialog(ABVActivity.this, title, body);
				alertDialog.setPositiveButton(R.string.ok, null);
				showAlertDialog(alertDialog);
			}
		}, 500);
	}

	public static boolean isVisible() {
		return isVisible;
	}

	protected int getUserPref(String key, int def) {
		return PreferenceUtil.getUserPref(this, key, def);
	}

	protected String getUserPref(String key, String def) {
		return PreferenceUtil.getUserPref(this, key, def);
	}

	protected long getUserPref(String key, long def) {
		return PreferenceUtil.getUserPref(this, key, def);
	}

	protected boolean getUserPref(String key, boolean def) {
		return PreferenceUtil.getUserPref(this, key, def);
	}

	protected float getUserPref(String key, float def) {
		return PreferenceUtil.getUserPref(this, key, def);
	}

	protected void putUserPref(String key, boolean val) {
		PreferenceUtil.putUserPref(this, key, val);
	}

	protected void putUserPref(String key, int val) {
		PreferenceUtil.putUserPref(this, key, val);
	}

	protected void putUserPref(String key, long val) {
		PreferenceUtil.putUserPref(this, key, val);
	}

    protected void putUserPref(String key, String val) {
        PreferenceUtil.putUserPref(this, key, val);
    }

	/**
	 * CMSのアドレスをロードする
	 */
	protected void loadAddressIfSaasGeneral() {
		if (getRInteger(R.integer.login_mode) == LoginMode.SITE_PATH_ID_PASS) {
			AcmsDto acmsDto = AbstractDao.getDao(AcmsDao.class).getAcms();
			if (acmsDto != null) {
				ABVEnvironment.getInstance().acmsAddress = acmsDto.acmsAddress;
				ABVEnvironment.getInstance().downloadServerAddress = acmsDto.downloadServerAddress;
				ABVEnvironment.getInstance().websocketServerHttpUrl = acmsDto.websocketServerHttpUrl;
				ABVEnvironment.getInstance().websocketServerWsUrl = acmsDto.websocketServerWsUrl;

				Logger.i(TAG, "acmsAddress=%s,", ABVEnvironment.getInstance().acmsAddress);
				Logger.i(TAG, "downloadServerAddress=%s,", ABVEnvironment.getInstance().downloadServerAddress);
				Logger.i(TAG, "websocketServerHttpUrl=%s,", ABVEnvironment.getInstance().websocketServerHttpUrl);
				Logger.i(TAG, "websocketServerWsUrl=%s,", ABVEnvironment.getInstance().websocketServerWsUrl);
			}
		}
	}

	protected void showToastOnDebug(String... msgs) {
		if (msgs == null || msgs.length == 0) {
			return;
		}
		if (Logger.isDebugEnabled()) {
			String msg;
			if (msgs.length <= 1) {
				msg = msgs[0];
			}
			else {
				String[] param = new String[msgs.length - 1];
				System.arraycopy(msgs, 1, param, 0, param.length);
				msg = String.format(msgs[0], (Object[])param);
			}
			handleErrorMessageToast(msg);
		}
	}

	/**
	 *
	 * @param requestCode onActivityResultで取得できる
	 * @param title インテントのタイトル
	 * @param type image,video
	 * @param cameraFlg カメラ撮影をするフラグ
	 */
	public boolean startCameraIntent(int requestCode , String title, String type, boolean cameraFlg) {
        if (cameraFlg) {
            //カメラパーミッションチェック
            ABookPermissionHelper helper = new ABookPermissionHelper(this, Constant.ABookPermissionType.Camera, null);
            if (!helper.checkMultiPermissions(true)) {
                Logger.w(TAG,"startCameraIntent Camera Permission  false");
                return false;
            }
        }
        //外部ストレージパーミッションチェック
        ABookPermissionHelper helper = new ABookPermissionHelper(this, Constant.ABookPermissionType.ReadExternalStorage, null);
        if (!helper.checkMultiPermissions(true)) {
			Logger.w(TAG,"startCameraIntent ReadExternalStorage Permission  false");
            return false;
        }

        showCameraOrAlbumSelectView(requestCode, title, type, cameraFlg);
        return true;
	}

	private void showCameraOrAlbumSelectView(int requestCode , String title, String type, boolean cameraFlg) {
        if (type.toLowerCase().equals(ABookKeys.IMAGE)) {
            Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            galleryIntent.setType("image/*");
            Intent chooser = new Intent(Intent.ACTION_CHOOSER);
            chooser.putExtra(Intent.EXTRA_INTENT, galleryIntent);
            chooser.putExtra(Intent.EXTRA_TITLE, title);
            if (cameraFlg) {

                Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

				ContentValues values = new ContentValues();
				values.put(MediaStore.MediaColumns.TITLE, "New Picture");
				values.put(MediaStore.Images.ImageColumns.DESCRIPTION, "From your Camera");
				imageUri = getContentResolver().insert(
						MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
                cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

                Intent[] intentArray = new Intent[]{cameraIntent};
                chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
            }

            startActivityForResult(chooser, requestCode);

        } else if(type.toLowerCase().equals(ABookKeys.VIDEO)) {
            Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
            galleryIntent.setType("video/*");
            Intent chooser = new Intent(Intent.ACTION_CHOOSER);
            chooser.putExtra(Intent.EXTRA_INTENT, galleryIntent);
            chooser.putExtra(Intent.EXTRA_TITLE, title);
            if (cameraFlg) {
                Intent cameraIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
                Intent[] intentArray = new Intent[]{cameraIntent};
                chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
            }
            startActivityForResult(chooser, requestCode);
        }
    }

	/**
	 * マイクパーミッションチェック
	 */
	public boolean checkMicPermission() {
		ABookPermissionHelper helper = new ABookPermissionHelper(this, Constant.ABookPermissionType.Audio, null);
		if (!helper.checkMultiPermissions(true)) {
			Logger.w(TAG,"checkMicPermission Audio Permission  false");
			return false;
		}
		return true;
	}

	/**
	 * 共通エラーダイアログ表示
	 * @param errorMessage エラーメッセージ
	 */
	protected void showErrorDialog(int errorMessage) {
		int message = PatternStringUtil.patternToInt(getApplicationContext(),
				errorMessage,
				getUserPref(AppDefType.UserPrefKey.RESOURCE_PATTERN_TYPE, 0));
		AlertDialogUtil.showAlertDialog(this, message);
	}
}
