package com.atid.app.atx.bluetooth.access.readmemory;

import java.util.ArrayList;
import java.util.Locale;

import com.atid.app.atx.bluetooth.access.readmemory.adapter.MemoryListAdapter;
import com.atid.app.atx.bluetooth.access.readmemory.data.DeviceItem;
import com.atid.app.atx.bluetooth.access.readmemory.data.GlobalData;
import com.atid.app.atx.bluetooth.access.readmemory.device.ReaderManager;
import com.atid.app.atx.bluetooth.access.readmemory.dialog.BaseDialog;
import com.atid.app.atx.bluetooth.access.readmemory.dialog.EnumListDialog;
import com.atid.app.atx.bluetooth.access.readmemory.dialog.MessageBox;
import com.atid.app.atx.bluetooth.access.readmemory.dialog.NumberUnitDialog;
import com.atid.app.atx.bluetooth.access.readmemory.dialog.PasswordDialog;
import com.atid.app.atx.bluetooth.access.readmemory.dialog.WaitDialog;
import com.atid.lib.diagnostics.ATException;
import com.atid.lib.module.rfid.uhf.ATRfidUhf;
import com.atid.lib.module.rfid.uhf.event.IATRfidUhfEventListener;
import com.atid.lib.module.rfid.uhf.params.TagExtParam;
import com.atid.lib.module.rfid.uhf.types.BankType;
import com.atid.lib.reader.ATEAReader;
import com.atid.lib.reader.event.IATEAReaderEventListener;
import com.atid.lib.reader.types.KeyState;
import com.atid.lib.reader.types.KeyType;
import com.atid.lib.reader.types.OperationMode;
import com.atid.lib.reader.types.UsbChargerState;
import com.atid.lib.reader.types.UsbChargerType;
import com.atid.lib.transport.types.ConnectState;
import com.atid.lib.transport.types.ConnectType;
import com.atid.lib.types.ActionState;
import com.atid.lib.types.DeviceType;
import com.atid.lib.types.ResultCode;
import com.atid.lib.util.SysUtil;
import com.atid.lib.util.diagnotics.ATLog;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Application.ActivityLifecycleCallbacks;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener,
		IATEAReaderEventListener, IATRfidUhfEventListener{

	private static final String TAG = MainActivity.class.getSimpleName();
	private static final int INFO = ATLog.L1;
	
	private static final int REQUEST_PERMISSION_CODE = 1000;
	private static final int REQUEST_ENABLE_BLUETOOTH = 1;
	
	// ------------------------------------------------------------------------
	// Member Variable
	// ------------------------------------------------------------------------
	private TextView txtVersion;
	private TextView txtDevice;
	private TextView txtAddress;

	private TextView txtResult;
	private TextView txtData;
	private TextView txtRssi;
	private TextView txtPhase;

	private ListView lstData;
	private MemoryListAdapter mAdpData;
	
	private TextView txtBank;
	private TextView txtOffset;
	private TextView txtLength;
	private TextView txtPassword;
	
	private EnumListDialog dlgBank;
	private NumberUnitDialog dlgOffset;
	private NumberUnitDialog dlgLength;
	private PasswordDialog dlgPassword;
	
	private Button btnAction;
	private Button btnSetting;
	private Button btnClear;
	
	private ATEAReader mReader;
	
	private volatile boolean mIsAction;
	private volatile boolean mIsInitialize;
	private volatile boolean mIsReportRssi;	
	private volatile boolean mIsConnected;
	
	private boolean mIsRunAppHomeButton = true;

	private PowerManager.WakeLock mWakeLock;
	private ActivityLifecycleManager mActivityLifecycleCallbacks;
	
	private BluetoothAdapter mBluetooth;
	private volatile boolean mIsCheckEnableBluetooth;
	private volatile boolean mIsSelectBluetooth;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		
		mActivityLifecycleCallbacks = new ActivityLifecycleManager();
		getApplication().registerActivityLifecycleCallbacks(mActivityLifecycleCallbacks);
		
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		checkPermission();
		
		ATLog.i(TAG, INFO, "INFO. onCreate()");
	}

	@SuppressLint("NewApi")
	private void checkPermission() {
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
			
			final String[] permissionList = new String[] {
					Manifest.permission.WAKE_LOCK,
					Manifest.permission.BLUETOOTH_ADMIN,
					Manifest.permission.BLUETOOTH,
					Manifest.permission.BLUETOOTH_SCAN,
					Manifest.permission.BLUETOOTH_CONNECT,
			};
			
			ArrayList<String> permissions = new ArrayList<String>();
			int grantResult = PackageManager.PERMISSION_GRANTED;
			for (int i = 0 ; i < permissionList.length ; i++) {
				grantResult = ContextCompat.checkSelfPermission(MainActivity.this, permissionList[i]);
				if (grantResult == PackageManager.PERMISSION_DENIED) {
					permissions.add(permissionList[i]);
				}
			}
			
			if (permissions.size() <= 0) {
				onPermissionResult(true);
			} else {
				String[] requestPermissions = new String[permissions.size()];
				//permissions.toArray(requestPermissions);
				ActivityCompat.requestPermissions(this, permissions.toArray(requestPermissions), REQUEST_PERMISSION_CODE);
				                                         
			}
		} else {
			onPermissionResult(true);
		}
	}
	
	@Override
	protected void onDestroy() {
		
		closeActivity();
		
		if (mReader != null) {
			mReader.removeListener(this);
			mReader.destroy();
		}
		super.onDestroy();
		getApplication().unregisterActivityLifecycleCallbacks(mActivityLifecycleCallbacks);		
	}
	

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override 
	public boolean onPrepareOptionsMenu(Menu menu) {
		ATLog.i(TAG, INFO, "INFO. onPrepareOptionsMenu()");
		
		MenuItem menuAction = menu.findItem(R.id.menu_action);
		MenuItem menuSearh = menu.findItem(R.id.menu_search);
		
		if (mReader != null) {
			if (mReader.getState() == ConnectState.Connected) {
				menuAction.setTitle(R.string.action_disconnect);
			} else {
				menuAction.setTitle(R.string.action_connect);
			}
			
		}
			
		if (isAvailableBluetoothState()) {
			if (mIsSelectBluetooth) 
				menuAction.setEnabled(true);
			else
				menuAction.setEnabled(false);
			
			if (mReader != null) {
				if (mReader.getState() == ConnectState.Connected) {
					menuSearh.setEnabled(false);	
				} else {
					menuSearh.setEnabled(true);	
				}
			} else {
				menuSearh.setEnabled(true);
			}

		} else {
			Toast.makeText(this, "Current state of the local Bluetooth adapter is not ON", Toast.LENGTH_SHORT).show();
			menuAction.setEnabled(false);
			menuSearh.setEnabled(false);
		}
		
		return super.onPrepareOptionsMenu(menu);
	}
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		
		int id = item.getItemId();
		switch(id) {
		case R.id.menu_action:
			if (null != mReader) {
				if(mReader.getState() == ConnectState.Connected) {
					mReader.disconnect();
				} else {
					if (!mReader.connect() ) {
						ATLog.e(TAG, "ERROR. onOptionsItemSelected - Failed to connect reader");
						MessageBox.show( this, getString(R.string.msg_not_connect_bt),
								getString(R.string.title_error));
					} else {
						DeviceItem deviceItem = new DeviceItem(ConnectType.Bluetooth, mReader.getDeviceName(), mReader.getAddress());
						GlobalData.saveDeviceInfo(this, deviceItem);
					}
				}
			}
			return true;

		case R.id.menu_search:
			selectDevice();
			return true;
		default:
			break;
		}

		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onUserLeaveHint() {
		
		if (!mIsRunAppHomeButton) {
			if (mReader != null) {
				closeActivity();
			}
		}
		ATLog.i(TAG, INFO, "INFO. onUserLeaveHint()");
		super.onUserLeaveHint();
	}
	
	@Override
	public void onClick(View v) {
		
		if (!mIsConnected) {
			ATLog.e(TAG, "ERROR - onClick(%d) - Device is not connected !!",v.getId());
			return;
		}
		
		switch(v.getId()) {
		case R.id.bank:
			dlgBank.showDialog(this, R.string.bank);
			ATLog.i(TAG, INFO, "INFO. onClick() - bank");
			break;
		case R.id.offset:
			dlgOffset.showDialog(this, R.string.offset);
			ATLog.i(TAG, INFO, "INFO. onClick() - offset");
			break;
		case R.id.length:
			dlgLength.showDialog(this, R.string.length);
			ATLog.i(TAG, INFO, "INFO. onClick() - length");
			break;
		case R.id.password:
			dlgPassword.showDialog(this, R.string.password, new BaseDialog.IValueChangedListener() {
				
				@Override
				public void onValueChanged(BaseDialog dialog) {
					try {
						
						mReader.getRfidUhf().setAccessPassword(((PasswordDialog)dialog).getValue());
					} catch (ATException e) {
						ATLog.e(TAG, e, "ERROR. onClick(R.id.password).$onValueChanged() - Failed to save access password");
					}
				}
			});
			ATLog.i(TAG, INFO, "INFO. onClick() - password");
			break;		
			
		case R.id.action:
			action();
			break;
		case R.id.setting:
			btnAction.setEnabled(false);
			btnClear.setEnabled(false);
			btnSetting.setEnabled(false);

			setting();

			btnAction.setEnabled(true);
			btnClear.setEnabled(true);
			btnSetting.setEnabled(true);
			break;
		case R.id.clear:
			btnAction.setEnabled(false);
			btnSetting.setEnabled(false);
			btnClear.setEnabled(false);

			clear();

			btnAction.setEnabled(true);
			btnSetting.setEnabled(true);
			btnClear.setEnabled(true);
			break;
		}
	}


	@Override
	public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
		if (requestCode != REQUEST_PERMISSION_CODE) {
			return;
		}
		
		boolean result = true;
		for (int i = 0 ; i < grantResults.length ; i++) {
			result &= ( grantResults[i] != PackageManager.PERMISSION_DENIED );
		}
		onPermissionResult(result);
	}	
	
	
	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == RfidOptionActivity.ID) {
			switch (resultCode) {
			case Activity.RESULT_FIRST_USER:
				mIsConnected = false;
				enableWidgets(false);
				closeActivity();
				break;
			case Activity.RESULT_OK:
			case Activity.RESULT_CANCELED:
				// Load Report Rssi
				try {
					mIsReportRssi = mReader.getRfidUhf().getReportRssi();
				} catch (ATException e) {
					ATLog.e(TAG, e, "ERROR. onActivityResult() - Failed to load report rssi");
				}
				
				if (!mIsReportRssi) {
					txtRssi.setText(String.format(Locale.US, "%.2f dB", 0.0));
					txtPhase.setText(String.format(Locale.US, "%.2f \u00B0", 0.0));
				}

				enableWidgets(true);
				break;
			}
			ATLog.i(TAG, INFO, "INFO. onActivityResult() - RfidOptionActivity [%d]" , resultCode);
		} else if (requestCode == SelectDeviceActivity.ID) {
			if (resultCode == Activity.RESULT_OK) {

				DeviceItem item = data.getParcelableExtra(SelectDeviceActivity.ITEM);
				
				if (null != mReader) 
					mReader.removeListener(this);
					
				mReader = ReaderManager.getReader(item.getConnectType(), item.getName(), item.getAddress(), false);
				if (mReader == null) {
					ATLog.e(TAG, "ERROR. onActivityResult(SelectDeviceActivity, [%s]) - %s",
							getString(R.string.msg_fail_load_reader_instance));
					MessageBox.show(this, R.string.msg_fail_load_reader_instance, 
							R.string.title_error, android.R.drawable.ic_dialog_alert,
							new DialogInterface.OnClickListener() {
						
						@Override
						public void onClick(DialogInterface dialog, int which) {
							MainActivity.this.finish();
							return;
						}
					});
					return;
				}
				// Set Reader Event Listener
				mReader.addListener(this);
				
				mIsSelectBluetooth = true;
				
				txtDevice.setText(item.getType().toString());
				txtAddress.setText(item.getAddress());
				
				ATLog.i(TAG, INFO, "INFO. onActivityResult(SelectDeviceActivity, [%s])", item.toString());
			}
		} else if (requestCode == REQUEST_ENABLE_BLUETOOTH) {
			if (resultCode == Activity.RESULT_OK) {

				checkSystem();

				ATLog.i(TAG, INFO, "INFO. onActivityResult(REQUEST_ENABLE_BLUETOOTH)");
				return;
			}
			GlobalData.isEnableBluetooth = false;
			return;
		}
		super.onActivityResult(requestCode, resultCode, data);
	}
	
	private void onPermissionResult(boolean result) {
		
		if (!result) {
			MessageBox.show(this, R.string.msg_fail_permission, R.string.title_error,
					android.R.drawable.ic_dialog_alert, new DialogInterface.OnClickListener() {
						
						@Override
						public void onClick(DialogInterface dialog, int which) {
							MainActivity.this.finish();
							return;
						}
					});
		}
		
		mReader = null;

		dlgBank = null;
		dlgOffset = null;
		dlgLength = null;
		dlgPassword = null;
		
		mIsAction = false;
		mIsInitialize = false;
		mIsConnected = false;
		
		mIsCheckEnableBluetooth = false;
		mIsSelectBluetooth = false;

		initActivity();

		dlgBank = new EnumListDialog(txtBank, BankType.values());
		dlgOffset = new NumberUnitDialog(txtOffset, getResources().getString(R.string.unit_word));
		dlgLength = new NumberUnitDialog(txtLength, getResources().getString(R.string.unit_word));
		dlgPassword = new PasswordDialog(txtPassword);

		// Bank
		dlgBank.setValue(BankType.EPC);		
		// Offset
		dlgOffset.setValue(2);
		// Length
		dlgLength.setValue(2);
		// password
		dlgPassword.setValue("00000000");
		
		clear();
		
		enableWidgets(false);

		// Initialize Bluetooth
		mBluetooth = BluetoothAdapter.getDefaultAdapter();

		checkSystem();

		DeviceItem item = GlobalData.loadDeviceInfo(this, ConnectType.Bluetooth);
		if (null != item) {
			mReader = ReaderManager.getReader(item.getConnectType(), item.getName(), item.getAddress(), false);
			if (mReader == null) {
				ATLog.e(TAG, "ERROR. onActivityResult(SelectDeviceActivity, [%s]) - %s",
						getString(R.string.msg_fail_load_reader_instance));
				MessageBox.show(this, R.string.msg_fail_load_reader_instance, 
						R.string.title_error, android.R.drawable.ic_dialog_alert,
						new DialogInterface.OnClickListener() {
					
					@Override
					public void onClick(DialogInterface dialog, int which) {
						MainActivity.this.finish();
						return;
					}
				});
				return;
			}
			// Set Reader Event Listener
			mReader.addListener(this);
			
			mIsSelectBluetooth = true;

			txtDevice.setText(item.getType().toString());
			txtAddress.setText(item.getAddress());
		}		
	}
	
	// ------------------------------------------------------------------------
	// Reader Event Handler Methods
	// ------------------------------------------------------------------------
	
	@Override
	public void onReaderStateChanged(ATEAReader reader, ConnectState state, Object params) {
		switch(state) {
		case Connected:
			WaitDialog.hide();
			mIsConnected = true;
			loadProperties();
			break;
		case Connecting:
			WaitDialog.show(this, R.string.msg_connecting_bt);
			break;				
		case Disconnected:
			WaitDialog.hide();
			mIsConnected = false;
			enableWidgets(false);
			closeActivity();
			break;
		default:
			break;
		}
		ATLog.i(TAG, INFO, "EVENT. onReaderStateChanged([%s], %s)", reader, state);
		
	}
	
	@Override
	public void onReaderActionChanged(ATEAReader reader, ResultCode code, ActionState action, Object params) {
		if(code != ResultCode.NoError ){
			ATLog.i(TAG, INFO, "ERROR. onReaderActionChanged([%s], %s, %s) - Failed to action changed [%s]",
					reader, code , action, code);
			enableWidgets(true);
			return;
		}
		
		if( action == ActionState.Stop) {
			if(mIsAction) {
				mIsAction = false;
				outputMessage(getString(R.string.msg_fail_read_tag));
				txtData.setText(getString(R.string.access_data_noti));
				txtRssi.setText(String.format(Locale.US, "%.2f dB", 0.0));
				txtPhase.setText(String.format(Locale.US, "%.2f \u00B0", 0.0));
			}
			btnAction.setText(R.string.action_start);
		} else {
			btnAction.setText(R.string.action_stop);
		}
		enableWidgets(true);

		ATLog.i(TAG, INFO, "EVENT. onReaderActionChanged([%s], %s, %s)", reader, code, action);
	}

	@Override
	public void onReaderOperationModeChanged(ATEAReader reader, OperationMode mode, Object params) {

		ATLog.i(TAG, INFO, "EVENT. onReaderOperationModeChanged([%s], %s)", reader, mode);
	}

	@Override
	public void onReaderBatteryState(ATEAReader reader, int batteryState, Object params) {

		ATLog.i(TAG, INFO, "EVENT. onReaderBatteryState([%s], %d)", reader, batteryState);
	}

	@Override
	public void onReaderKeyChanged(ATEAReader reader, KeyType type, KeyState state, Object params) {

		ATLog.i(TAG, INFO, "EVENT. onReaderKeyChanged([%s], %s, %s)", reader, type, state);	
	}

	@Override
	public void onReaderUsbChargerChanged(ATEAReader reader, UsbChargerType type, UsbChargerState state, Object params) {
		
		ATLog.i(TAG, INFO, "EVENT. onReaderUsbChargerChanged([%s], %s, %s)", reader, type, state);
	}

	// ------------------------------------------------------------------------
	// RFID Reader Event Handler Methods
	// ------------------------------------------------------------------------	
	@Override
	public void onRfidUhfReadTag(ATRfidUhf uhf, String tag, Object params) {

		ATLog.i(TAG, INFO, "EVENT. onReaderReadTag([%s], [%s], [%.2f, %.2f])", mReader, tag);
	}

	@Override
	public void onRfidUhfAccessResult(ATRfidUhf uhf, ResultCode code, ActionState action, String epc, String data,
			Object params) {

		if(epc != null)
			txtData.setText(epc);
		
		if(data != null)
			mAdpData.setValue(dlgOffset.getValue(), data);
		
		if(code == ResultCode.NoError) {
			outputMessage(getString(R.string.msg_success));
			if(params != null) {
				TagExtParam param = (TagExtParam) params;
				txtRssi.setText(String.format(Locale.US, "%.2f dB", param.getRssiD()));
				txtPhase.setText(String.format(Locale.US, "%.2f \u00B0", param.getPhaseD()));
			}
			
		} else {
			outputMessage(code.getMessage());
			txtRssi.setText(String.format(Locale.US, "%.2f dB", 0.0));
			txtPhase.setText(String.format(Locale.US, "%.2f \u00B0", 0.0));
		}
		
		mIsAction = false;
		
		ATLog.i(TAG, INFO, "EVENT. onRfidUhfAccessResult([%s], [%s], %s, [%s], [%s])", mReader, code, action, epc,
				data);
	}

	@Override
	public void onRfidUhfPowerGainChanged(ATRfidUhf uhf, int power, Object params) {

		ATLog.i(TAG, INFO, "EVENT. onRfidUhfPowerGainChanged([%s], %d)", mReader, power);
	}

	// ------------------------------------------------------------------------
	// Internal Widget Control Methods
	// ------------------------------------------------------------------------
	private void initActivity() {
		txtVersion = (TextView) findViewById(R.id.app_version);
		txtVersion.setText(SysUtil.getVersion(this));
		txtDevice = (TextView) findViewById(R.id.bluetooth_device);
		txtAddress = (TextView) findViewById(R.id.bluetooth_address);

		txtResult = (TextView) findViewById(R.id.result);
		txtData = (TextView) findViewById(R.id.data);
		txtRssi = (TextView) findViewById(R.id.rssi);
		txtPhase = (TextView) findViewById(R.id.phase);
		
		lstData = (ListView) findViewById(R.id.value);
		mAdpData = new MemoryListAdapter(this);
		lstData.setAdapter(mAdpData);
		
		txtBank = (TextView) findViewById(R.id.bank);
		txtBank.setOnClickListener(this);
		txtOffset = (TextView) findViewById(R.id.offset);
		txtOffset.setOnClickListener(this);
		txtLength = (TextView) findViewById(R.id.length);
		txtLength.setOnClickListener(this);
		txtPassword = (TextView) findViewById(R.id.password);
		txtPassword.setOnClickListener(this);
		
		btnAction = (Button) findViewById(R.id.action);
		btnAction.setOnClickListener(this);
		btnSetting = (Button) findViewById(R.id.setting);
		btnSetting.setOnClickListener(this);
		btnClear = (Button) findViewById(R.id.clear);
		btnClear.setOnClickListener(this);		
	}

	private void closeActivity() {
		WaitDialog.hide();
		
		if (mReader != null) {
			if (mReader.getRfidUhf() != null ) {
				
				if (mReader.getAction() != ActionState.Stop) {
					mReader.getRfidUhf().stop();
					while (mReader.getAction() != ActionState.Stop &&
							mReader.getState() == ConnectState.Connected) {
						
						try {
							ATLog.i(TAG, INFO, "closeActivity() - wait for action stop.");
							Thread.sleep(50);
						} catch (InterruptedException e) {
							ATLog.e(TAG, e, "closeActivity() - Falied to sleep for thread");
						}
					}
				}
				btnAction.setText(R.string.action_start);
				mReader.getRfidUhf().removeListener(this);
			}
		}

		ATLog.i(TAG, INFO, "INFO. closeActivity()");
	}	
	
	private void enableWidgets(boolean enabled) {
		
		txtResult.setEnabled(enabled);
		txtData.setEnabled(enabled);
		txtPhase.setEnabled(enabled);
		txtRssi.setEnabled(enabled);
		
		lstData.setEnabled(enabled);
		
		txtBank.setEnabled(enabled);
		txtOffset.setEnabled(enabled);
		txtLength.setEnabled(enabled);
		txtPassword.setEnabled(enabled);
		
		
		btnAction.setEnabled(enabled);
		btnSetting.setEnabled(enabled && mReader.getAction() == ActionState.Stop);
		btnClear.setEnabled(enabled && mReader.getAction() == ActionState.Stop);
		
		txtDevice.setEnabled(enabled || mIsConnected);
		txtAddress.setEnabled(enabled || mIsConnected);

		ATLog.i(TAG, INFO, "INFO. enableWidgets(%s)", enabled);
	}	
	
	// ------------------------------------------------------------------------
	// Internal Helper Methods
	// ------------------------------------------------------------------------
	private void action() {
		ResultCode res = ResultCode.NoError;
		enableWidgets(false);
		
		ATLog.i(TAG, INFO, "INFO. action() - Access PW [%s]" , dlgPassword.getValue());
		
		if(mReader.getAction() == ActionState.Stop) {
			if( (res = mReader.getRfidUhf().readMemory6c((BankType) dlgBank.getValue(), dlgOffset.getValue(), 
					dlgLength.getValue(), dlgPassword.getValue())) != ResultCode.NoError) {
				ATLog.e(TAG, "ERROR. action() - Failed to read memory[%s]",res);
				MessageBox.show(this, String.format(Locale.US, "%s. [%s]",
						getString(R.string.msg_fail_start_read_memory), res), getString(R.string.title_error));
				
				mReader.getRfidUhf().stop();
				return;
			}
			
			outputMessage(getString(R.string.msg_read_memory));
		} else {
			if( (res = mReader.getRfidUhf().stop()) != ResultCode.NoError) {
				ATLog.e(TAG, "ERROR. action() - Failed to stop operation [%s]", res);
				MessageBox.show(this, String.format(Locale.US, "%s. [%s]", 
						getString(R.string.msg_fail_stop_action), res), getString(R.string.title_error));
				enableWidgets(true);
				return;
			}
		}
		
		mIsAction = true;
		ATLog.i(TAG, INFO, "INFO. action()");
	}	
	
	private void clear() {
		txtRssi.setText(String.format(Locale.US, "%.2f dB", 0.0));
		txtPhase.setText(String.format(Locale.US, "%.2f \u00B0", 0.0));
		
		txtResult.setText(getString(R.string.access_result));
		txtData.setText(getString(R.string.access_data_noti));
		
		mAdpData.clear();
		
		ATLog.i(TAG, INFO, "INFO. clear()");
	}
	
	private void setting() {
		Intent intent = new Intent(this, RfidOptionActivity.class);
		intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

		startActivityForResult(intent, RfidOptionActivity.ID);
		
		ATLog.i(TAG, INFO, "INFO. setting()");
	}	
	
	private void outputMessage(String msg) {
		txtResult.setText(msg);
	}
	
	private void selectDevice() {
		Intent intent = new Intent(this, SelectDeviceActivity.class);
		intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

		startActivityForResult(intent, SelectDeviceActivity.ID);
		
		ATLog.i(TAG, INFO, "INFO. setting()");
	}
	
	private boolean isAvailableBluetoothState() {
		boolean available = false;
		
		if(mBluetooth == null)
			return available;
		
		int state = BluetoothAdapter.STATE_TURNING_ON;
		
		while(state == BluetoothAdapter.STATE_TURNING_OFF || state == BluetoothAdapter.STATE_TURNING_ON) {
			state = mBluetooth.getState();
		}
		
		if(state == BluetoothAdapter.STATE_ON) {
			available = true;
		} else {
			ATLog.i(TAG, INFO, "INFO. current state of the local Bluetooth adapter : " + state);
		}
		
		return available;
	}
	
	private synchronized void checkSystem() {

		// Check Bluetooth
		if (mBluetooth == null) {
			// Not Support Bluetooth...
			GlobalData.isSupportBluetooth = false;
			ATLog.e(TAG, "INFO. checkSystem() - Not suppored bluetooth");
		} else {
			GlobalData.isSupportBluetooth = true;
			// Suppoted Bluetooth
			if (!mBluetooth.isEnabled() && !mIsCheckEnableBluetooth) {
				mIsCheckEnableBluetooth = true;
				// Disabled Bluetotoh
				GlobalData.isEnableBluetooth = false;
				Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
				startActivityForResult(intent, REQUEST_ENABLE_BLUETOOTH);
				ATLog.i(TAG, INFO, "INFO. checkSystem() - Request Enable Bluetooth");
				return;
			} else {
				GlobalData.isEnableBluetooth = true;
			}
		}

		
		if (!GlobalData.isSupportBluetooth) {
			MessageBox.show(this, R.string.msg_not_support_bt, R.string.title_bt);
		}

		ATLog.i(TAG, INFO, "INFO. checkSystem()");
	}

	@SuppressWarnings("unused")
	private void showMessage(final String message) {
		runOnUiThread( new Runnable() {
			@Override
			public void run() {
				MessageBox.show(MainActivity.this, message);
			}
		});
		
	}

	// ------------------------------------------------------------------------
	// Load RFID Reader Properties
	// ------------------------------------------------------------------------
	private void loadProperties() {
		WaitDialog.show(this, R.string.msg_initialize_view);
		
		Thread thread = new Thread(mLoadingProperties);
		thread.start();
	}
	
	private Runnable mLoadingProperties = new Runnable() {
		@Override
		public void run() {
			mIsInitialize = loadingProperties();
			runOnUiThread(mLoadedProperties);
		}
	};
	
	private Runnable mLoadedProperties = new Runnable() {
		@Override
		public void run() {
			loadedProperties(mIsInitialize);
			WaitDialog.hide();
		}
	};	
	
	private boolean loadingProperties() {
		
		if (mIsConnected) {
			if (mReader.getRfidUhf() == null) {
				ATLog.e(TAG, "ERROR. loadingProperties() - Failed to get rfid instance");
				return false;
			}
		} else {
			ATLog.e(TAG, "ERROR. loadingProperties() - disconnected the bluetooth ");
			return false;
		}
		
		// Set RFID Event Listener
		mReader.getRfidUhf().addListener(this);
		
		// Load Report Rssi
		if (mIsConnected) {
			try {
				mIsReportRssi = mReader.getRfidUhf().getReportRssi();
			} catch (ATException e) {
				ATLog.e(TAG, e, "ERROR. loadingProperties() - Failed to load report rssi");
				return false;
			}
			
		} else {
			ATLog.e(TAG, "ERROR. loadingProperties() - disconnected the bluetooth ");
			return false;
		}
		
		// Disable Use Key Action
		if (mReader.getDeviceType() != DeviceType.ATD100) {
			if (mIsConnected) {
				try {
					mReader.setUseActionKey(false);
				} catch (ATException e) {
					ATLog.e(TAG, "ERROR. loadingProperties() - Failed to enabled key action");
					return false;
				}
			} else {
				ATLog.e(TAG, "ERROR. loadingProperties() - disconnected the bluetooth ");
				return false;
			}
		}
		
		// Load Password
		String password="";
		if (mIsConnected) {
			try{
				password = mReader.getRfidUhf().getAccessPassword();
			}catch(ATException e){
				ATLog.e(TAG, e, "ERROR. loadingProperties() - Failed to load access password");
				return false;
			}
		} else {
			ATLog.e(TAG, "ERROR. loadingProperties() - disconnected the bluetooth ");
			return false;
		}
		
		// set Password
		dlgPassword.setValue(password);
		
		ATLog.i(TAG, INFO, "INFO. loadingProperties()");
		return true;
	}
	
	private void loadedProperties(boolean isInitialize) {
		
		if (isInitialize) {
			
			dlgBank.display();
			
			dlgOffset.display();
			
			dlgLength.display();
			
			dlgPassword.display();
			
			if (!mIsReportRssi) {
				txtRssi.setText(String.format(Locale.US, "%.2f dB", 0.0));
				txtPhase.setText(String.format(Locale.US, "%.2f \u00B0", 0.0));
			}
			
			enableWidgets(true);
		} else {
			enableWidgets(false);
		}
		
		ATLog.i(TAG, INFO, "INFO. loadedProperties(%s)", isInitialize);
	}	
	
	// ------------------------------------------------------------------------
	// Activity Life cycle
	// ------------------------------------------------------------------------
	public class ActivityLifecycleManager implements ActivityLifecycleCallbacks {

		private int mRefCount = 0;
		private String _tag = ActivityLifecycleManager.class.getSimpleName();
		
		@SuppressWarnings("deprecation")
		@Override
		public void onActivityStarted(Activity activity) {
			mRefCount++;
			ATLog.i(TAG, INFO, "INFO. ActivityLifecycleManager.onActivityStarted : " + mRefCount);
			
			if(mRefCount == 1) {
				// Setup always wake up
				android.content.Context context = activity.getApplicationContext();
				//SysUtil.wakeLock(activity.getApplicationContext(), SysUtil.getAppName(context));
				
				if(mWakeLock != null) {
					ATLog.i(TAG, INFO, "INFO. Already exist wake lock");
				}
				
				PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
				mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, _tag);
				//mWakeLock = powerManager.newWakeLock(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, TAG);
				mWakeLock.acquire();
				ATLog.i(TAG, INFO, "INFO. Acquires the wake lock.");
			}
		}
		
		@Override
		public void onActivityStopped(Activity activity) {
			mRefCount--;
			ATLog.i(TAG, INFO, "INFO. ActivityLifecycleManager.onActivityStopped : " + mRefCount);
			
			if(mRefCount == 0) {
				// release WakeLock.
				//SysUtil.wakeUnlock();
				
				if (mWakeLock == null)
					return;

				mWakeLock.release();
				mWakeLock = null;
				ATLog.i(TAG, INFO, "INFO. Releases the wake lock.");
			}
		}

		@Override
		public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
		@Override
		public void onActivityResumed(Activity activity) {}
		@Override
		public void onActivityPaused(Activity activity) {}
		@Override
		public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
		@Override
		public void onActivityDestroyed(Activity activity) {}
		
	}		
	
}
