package com.atid.at288n.app.demo;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.atid.at288.lib.IReaderCallbackReceiver;
import com.atid.at288.lib.Reader;
import com.atid.at288.lib.dialog.DeviceListActivity;
import com.atid.at288.lib.type.BankType;
import com.atid.at288n.app.demo.view.BaseView;

public class MainActivity extends Activity implements IReaderActivity,
Button.OnClickListener, IReaderCallbackReceiver{


	private static final int INVENTORY_VIEW = 0;
	private static final int TID_VIEW = 1;
	private static final int STORED_VIEW = 2;
	private static final int MEMORY_VIEW = 3;
	private static final int ACCESS_VIEW = 4;
	private static final int OPTION_VIEW = 5;
	

	private final String DEFAULT_DEVICE_ADDRESS = null;
	private final boolean DEFAULT_DISPLAY_PC = true;
	private final int DEFAULT_BANK_TYPE = 1;
	private final int DEFAULT_START_ADDRESS = 2;
	private final int DEFAULT_READ_LENGTH = 4;
	private final int DEFAULT_RESPONSE_TIMEOUT = 6000;
	
	private final String TAG = "MainFrame";
	
	// Widget Members 
	private TextView txtReaderVersion = null;
	private TextView txtFirmwareVersion = null;
	private TextView txtDemoVersion = null;
	private TextView txtBluetoothAddress = null;

	private Button[] btnMenus = null;

	private TextView txtLogo = null;

	private LinearLayout mainView = null;

	private BaseView[] views = null;
	private BaseView currentView = null;

	// Reader Reference Member
	private Reader reader = null;

	// Member Variable
	private String deviceAddress = DEFAULT_DEVICE_ADDRESS;
	private boolean isDisplayPC = DEFAULT_DISPLAY_PC;
	private BankType bankType = BankType.values()[DEFAULT_BANK_TYPE];
	private int startAddress = DEFAULT_START_ADDRESS;
	private int readLength = DEFAULT_READ_LENGTH;
	private int responseTimeout = DEFAULT_RESPONSE_TIMEOUT;
	
	private MenuItem mnuConnectDevice;
	private MenuItem mnuConnectNewDevice;
	private MenuItem mnuDisconnectDevice;
	
	private boolean isBusy = false;
	// ---------------------------------------------------- ---------
	// Properties
	// -------------------------------------------------------------
	@Override
	public boolean getDisplayPC() {
		return isDisplayPC;
	}

	@Override
	public void setDisplayPC(boolean displayPC) {
		isDisplayPC = displayPC;
	}

	@Override
	public BankType getBankType() {
		return bankType;
	}

	@Override
	public void setBankType(BankType type) {
		bankType = type;
	}

	@Override
	public int getStartAddress() {
		return startAddress;
	}

	@Override
	public void setStartAddress(int address) {
		startAddress = address;
	}

	@Override
	public int getReadLength() {
		return readLength;
	}

	@Override
	public void setReadLength(int length) {
		readLength = length;
	}

	@Override
	public int getResponseTimeout() {
		return responseTimeout;
	}

	@Override
	public void setResponseTimeout(int timeout) {
		responseTimeout = timeout;
	}

	void requestBluetoothPermissions(){
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
			requestPermissions(
					new String[]{
							Manifest.permission.BLUETOOTH,
							Manifest.permission.BLUETOOTH_SCAN,
							Manifest.permission.BLUETOOTH_ADVERTISE,
							Manifest.permission.BLUETOOTH_CONNECT


					},
					1);
		} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
			requestPermissions(
					new String[]{
							Manifest.permission.BLUETOOTH

					},
					1);
		}
	}

	// -------------------------------------------------------------
	// Event Handler
	// -------------------------------------------------------------
	/** Called when the activity is first created. */
	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

		//Request BT persmissions
		requestBluetoothPermissions();

        // Load Config
 		loadConfig();

 		// Create Reader Object
 		createReader();

 		// Initialize Widget
 		initWidget();
 		
 		// Output Demo Version Info
 		displayDemoVersion();
 		
 		reader.onCreate();
    }
	
	@Override
	protected void onStart() {
		super.onStart();
		reader.onStart();
	}

	@Override
	protected void onResume() {
		super.onResume();
		loadConfig();
		reader.onResume();
	}

	@Override
	protected void onPause() {
		reader.onPause();
		super.onPause();
	}

	@Override
	protected void onStop() {
		saveConfig();
		reader.onStop();
		super.onStop();
	}

	@Override
	protected void onDestroy() {
		saveConfig();
		super.onDestroy();
		reader.onDestroy();
	}
	
	@SuppressLint("NewApi")
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		
		if(data == null) {
			Log.d(TAG, "DEBUG. data is null.");
			return;
		}
		
		String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
		if(address != null) {
			reader.onActivityResult(requestCode, resultCode, data);
			if (requestCode == Reader.REQUEST_CONNECT_DEVICE
					&& resultCode == Activity.RESULT_OK) {
				showWaitDialog("", getResources()
						.getString(R.string.connect_reader));
			}
		} else {
			Log.e(TAG, "ERROR. Device address is null.");
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		
		if(isBusy) {
			return false;
		}
		
		mnuConnectDevice = menu.findItem(R.id.device_connect);
		mnuConnectNewDevice = menu.findItem(R.id.device_new_connect);
		mnuDisconnectDevice = menu.findItem(R.id.menu_disconnect);
		
		visibleMenuItem(reader.getState());
		return super.onPrepareOptionsMenu(menu);
		
	};
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		switch (keyCode) {
		case KeyEvent.KEYCODE_BACK:
			if (isShowSubView()) {
				closeSubView();
				return true;
			}
			break;
		}
		return super.onKeyDown(keyCode, event);
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.device_connect:
			connectReader();
			break;
		case R.id.device_new_connect:
			reader.openDeviceListActivity();
			break;
		case android.R.id.home:
			if (isShowSubView()) {
				closeSubView();
				return true;
			}
			break;
		case R.id.menu_disconnect:
			// Disconnect Device
			reader.stop();
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.inventory:
			showSubView(INVENTORY_VIEW);
			break;
		case R.id.tid:
			showSubView(TID_VIEW);
			break;
		case R.id.stored:
			showSubView(STORED_VIEW);
			break;
		case R.id.memory:
			showSubView(MEMORY_VIEW);
			break;
		case R.id.access:
			showSubView(ACCESS_VIEW);
			break;
		case R.id.option:
			showSubView(OPTION_VIEW);
			break;
		
		}
	}
	
	// -------------------------------------------------------------
	// Reader Functions
	// -------------------------------------------------------------


	// Create Reader
	private void createReader() {
		reader = new Reader(this, this);
		reader.mDeviceAddress = deviceAddress;
	}

	// Connect Reader...
	private void connectReader() {
		reader.connectMostRecentDevice();
		if (reader.mDeviceAddress != null) {
			showWaitDialog("", getResources()
					.getString(R.string.connect_reader));
		}
	}

	@Override
	public void onReaderStateChange(int state) {
		switch (state) {
		case Reader.STATE_CONNECTING:
			// Case Connecting Reader or Ready Connecting Reader...
			enableAllButtons(false);
			txtLogo.setTextColor(getResources().getColor(
					R.color.connecting_device));
			break;
		case Reader.STATE_CONNECTED:
			// Case Connected Reader

			// Save Reader Bluetooth Mac Address
			txtBluetoothAddress.setText(reader.mDeviceAddress);
			deviceAddress = reader.mDeviceAddress;
			reader.setResponseTime(responseTimeout);
			saveConfig();

			// Reader Activate...
			reader.activate();

			//Reader Firmware Version
			reader.getFirmwareVersion();
			
			reader.getVersionEx();
			hideWaitDialog();
			visibleMenuItem(state);
			enableAllButtons(true);
			txtLogo.setTextColor(getResources().getColor(
					R.color.connected_device));
			break;
		case Reader.STATE_LISTEN:
		default:
			// Case Disconnected Reader...
			hideWaitDialog();
			
			views[INVENTORY_VIEW].clearMaskParams();
			views[TID_VIEW].clearMaskParams();
			views[MEMORY_VIEW].clearMaskParams();
			views[ACCESS_VIEW].clearMaskParams();

			isBusy = false;
			enableAllButtons(false);
			txtLogo.setTextColor(getResources().getColor(
					R.color.disconnected_device));
			txtReaderVersion.setText("");
			txtFirmwareVersion.setText("");
			txtBluetoothAddress.setText("");
			break;
		}

		// Transfer Event to Subview...
		if (isShowSubView())
			currentView.onReaderStateChange(state);

	}

	@Override
	public void onReaderReadTag(int event, String tag) {
		Log.d(TAG, "### READ TAG [" + event + "] : " + tag);
		// Transfer Event to Subview...
		if (isShowSubView())
			currentView.onReaderReadTag(event, tag);
	}

	@Override
	public void onReaderResponse(int event, String code) {
		Log.d(TAG, "### RESPONSE [" + event + "] : " + code);
		// Transfer Event to Subview...
		if (isShowSubView())
			currentView.onReaderResponse(event, code);
	}

	@Override
	public void onReaderActionChange(char action) {
		Log.d(TAG, "### ACTION : " + action);
		
		switch(action) {
		case Reader.ACTION_INVENTORY_6B_MULTIPLE:
		case Reader.ACTION_INVENTORY_6B_SINGLE:
		case Reader.ACTION_INVENTORY_6C_MULTIPLE:
		case Reader.ACTION_INVENTORY_6C_SELECTION:
		case Reader.ACTION_INVENTORY_6C_SINGLE:
		case Reader.ACTION_INVENTORY_6C_VLC:
			isBusy = true;
			enableAllButtons(false);
			break;
		case Reader.ACTION_STOP:
			isBusy = false;
			enableAllButtons(true);
			break;
		}
		
		// Transfer Event to Subview...
		if (isShowSubView())
			currentView.onReaderAction(action);
	}
	
	@Override
	public void onReaderProperty(char code, String value) {
		//Log.d(TAG, "### PROPERTY [" + code + "] : " + value);

		if (code == Reader.PROPERTY_VERSION) {
			// Output Reader Firmware Version
			txtFirmwareVersion .setText(value);
			for (BaseView view : views)
				view.createView();
		}
		
		// Transfer Event to Subview...
		if (isShowSubView())
			currentView.onReaderProperty(code, value);
	}

	@Override
	public void onReaderExtendedProperty(char code, String value) {
		//Log.d(TAG, "### EXTENTED PROPERTY [" + code + "] : " + value);

		if(code == Reader.PROPERTY_EX_VERSION)
			txtReaderVersion.setText(value);

		if(code == Reader.PROPERTY_EX_VERSION || code == Reader.PROPERTY_EX_TAG_TYPE) {
			if(reader.IsAT288N_MA()) {
				btnMenus[5].setEnabled(false);  // Inventory with Memory is not supported when module is AT288N MA.
				if(reader.TagType == Reader.ISO18000_6B) {
					btnMenus[2].setEnabled(false);  // Read/Write are not supported when module is AT288N MA and 6B mode.
					btnMenus[3].setEnabled(false);  // Lock/Kill are not supported when module is AT288N MA and 6B mode.
				} else {
					btnMenus[2].setEnabled(true);
					btnMenus[3].setEnabled(true);
				}
			} else {
				btnMenus[2].setEnabled(true);
				btnMenus[3].setEnabled(true);
				btnMenus[5].setEnabled(true);
			}
		}

		// Transfer Event to Subview...
		if (isShowSubView())
		{
			currentView.onReaderExtentedProperty(code, value);
		}
	}

	@Override
	public void onReaderTimeout() {
		Log.d(TAG, "### TIMEOUT");
		// Transfer Event to Subview...
		if (isShowSubView())
			currentView.onReaderTimeout();
	}

	@Override
	public void onReaderMessage(String msg) {
		Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
		
	}
	
	// -------------------------------------------------------------
	// Subview Functions
	// -------------------------------------------------------------

	// Show Subview
	public void showSubView(int index) {
		// Hide Mainview
		mainView.setVisibility(View.GONE);
		// Select Current Subview
		currentView = views[index];
		// Show Subview
		currentView.setVisibility(View.VISIBLE);
		// Initialize Subview
		currentView.initView();
		
		setTitle(currentView.getTitle());
	}

	@Override
	public void closeSubView() {
		if (currentView == null)
			return;

		// Hide Subview
		currentView.setVisibility(View.GONE);
		// Exit Subview
		currentView.exitView();
		// Free Current Subview
		currentView = null;
		// Show Mainview
		mainView.setVisibility(View.VISIBLE);
		
		setTitle(getResources().getString(R.string.app_name));
	}

	// Retrieve Showable Subview
	private boolean isShowSubView() {
		return mainView.getVisibility() == View.GONE && 
				currentView != null;
	}

	// -------------------------------------------------------------
	// Widget Control Functions
	// -------------------------------------------------------------

	// Initialize Widget
	private void initWidget() {
		mainView = (LinearLayout) findViewById(R.id.view_main_frame);
		currentView = null;

		// Version Widget
		txtReaderVersion = (TextView) findViewById(R.id.device_version);
		txtFirmwareVersion = (TextView) findViewById(R.id.firmware_version);
		txtDemoVersion = (TextView) findViewById(R.id.demo_version);
		txtBluetoothAddress = (TextView) findViewById(R.id.bluetooth_address);

		// Button Widget
		btnMenus = new Button[] {
				(Button) findViewById(R.id.inventory),
				(Button) findViewById(R.id.stored),
				(Button) findViewById(R.id.memory),
				(Button) findViewById(R.id.access),
				(Button) findViewById(R.id.option),
				(Button) findViewById(R.id.tid)};
		for (Button button : btnMenus) {
			button.setOnClickListener(this);
			button.setEnabled(false);
		}
		// Logo Widget
		txtLogo = (TextView) findViewById(R.id.app_logo);
		// Initialize Subview Widget
		views = new BaseView[] {
				(BaseView) findViewById(R.id.view_inventory),
				(BaseView) findViewById(R.id.view_tid),
				(BaseView) findViewById(R.id.view_stored_inventory),
				(BaseView) findViewById(R.id.view_memory),
				(BaseView) findViewById(R.id.view_access),
				(BaseView) findViewById(R.id.view_option)
				 };
		for (BaseView view : views)
			view.onCreate(this, reader);
	}

	// All Enabled Button Widgets
	private void enableAllButtons(boolean enabled) {
		
		if(reader.IsAT288N_MA()) {
			
			if(reader.TagType == Reader.ISO18000_6B) {
				for(int i=0; i<btnMenus.length; i++) {
					if(i == 2 || i == 3 || i == 5)
						continue;
					else
						btnMenus[i].setEnabled(enabled);
				}
			} else {
				for(int i=0; i<btnMenus.length; i++) {
					if(i == 5)
						continue;
					else
						btnMenus[i].setEnabled(enabled);
				}
			}
		} else {
		
			for (Button button : btnMenus) {
				button.setEnabled(enabled);
			}
			
		}
	}

	// Display Application Version
	private void displayDemoVersion() {
		String versionName = "";
		try {
			String packageName = getPackageName();
			versionName = getPackageManager().getPackageInfo(packageName,
					PackageManager.GET_META_DATA).versionName;
		} catch (NameNotFoundException ex) {
			versionName = "";
		}
		txtDemoVersion.setText(versionName);
	}

	// -------------------------------------------------------------
	// Control Wait Dialog Functions
	// -------------------------------------------------------------

	private ProgressDialog m_dlgWait = null;

	// Show Wait Dialog
	private void showWaitDialog(String title, String message) {
		hideWaitDialog();
		m_dlgWait = ProgressDialog.show(this, title, message);
	}

	// Hide Wait Dialog
	private void hideWaitDialog() {
		if (m_dlgWait != null) {
			m_dlgWait.cancel();
			m_dlgWait = null;
		}
	}

	
	private void visibleMenuItem(int state) {
		Log.d(TAG,"state :::::::: "+state);
		mnuConnectDevice.setVisible(state != Reader.STATE_CONNECTED);
		mnuConnectDevice.setEnabled(true);
		mnuConnectNewDevice.setVisible(state != Reader.STATE_CONNECTED);
		mnuConnectNewDevice.setEnabled(true);
		mnuDisconnectDevice.setVisible(state == Reader.STATE_CONNECTED);
		
		
	}
	
	
	// -------------------------------------------------------------
	// Load/Save Config Functions
	// -------------------------------------------------------------

	// Load Config
	private void loadConfig() {
		SharedPreferences prefs = getSharedPreferences("Config", MODE_PRIVATE);

		deviceAddress = prefs.getString("device_address",
				DEFAULT_DEVICE_ADDRESS);
		isDisplayPC = prefs.getBoolean("display_pc", DEFAULT_DISPLAY_PC);
		bankType = BankType.values()[prefs.getInt("bank_type",
				DEFAULT_BANK_TYPE)];
		startAddress = prefs.getInt("start_address", DEFAULT_START_ADDRESS);
		readLength = prefs.getInt("read_length", DEFAULT_READ_LENGTH);
		responseTimeout = prefs.getInt("response_timeout",
				DEFAULT_RESPONSE_TIMEOUT);
	}

	// Save Config
	private void saveConfig() {
		SharedPreferences prefs = getSharedPreferences("Config", MODE_PRIVATE);
		SharedPreferences.Editor editor = prefs.edit();

		editor.putString("device_address", deviceAddress);
		editor.putBoolean("display_pc", isDisplayPC);
		editor.putInt("bank_type", bankType.value());
		editor.putInt("start_address", startAddress);
		editor.putInt("read_length", readLength);
		editor.putInt("response_timeout", responseTimeout);
		editor.commit();
	}
}
