package com.atid.at288n.app.demo.view;


import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.atid.at288.lib.Reader;
import com.atid.at288.lib.ReaderService;
import com.atid.at288.lib.type.BankType;
import com.atid.at288.lib.type.SelectionActionType;
import com.atid.at288n.app.demo.IReaderActivity;
import com.atid.at288n.app.demo.R;
import com.atid.at288n.app.demo.type.ActionType;
import com.atid.at288n.app.demo.view.adapter.MemoryOptionListAdapter;
import com.atid.at288n.app.demo.view.adapter.MemoryValueListAdapter;
import com.atid.at288n.app.demo.view.dialog.MaskSelectionDialog;

public class MemoryView extends BaseView implements Button.OnClickListener,
		OnItemClickListener, OnItemSelectedListener {

	private ProgressBar progress;
	private TextView message;

	private MemoryValueListAdapter adapterReadValue;
	private EditText edtWriteValue;

	private MemoryOptionListAdapter adapterOption;

	private ArrayAdapter<CharSequence> adapterPowerGain;
	private Spinner spinPowerGain;

	private Button btnRead;
	private Button btnWrite;
	private Button btnClear;
	private Button btnMask;

	private ActionType action = ActionType.Stop;
	private MaskSelectionDialog mask = null;
	private boolean enabledWidgets = false;
	private InitChecker initChecker = new InitChecker();

	public MemoryView(Context context) {
		super(context);
		if (isInEditMode())
			return;
		init(context);
	}

	public MemoryView(Context context, AttributeSet attrs) {
		super(context, attrs);
		if (isInEditMode())
			return;
		init(context);
	}

	private void init(Context context) {
		TAG = "MemoryView";
		
		action = ActionType.Stop;
		
		if (!isInEditMode()) {
			LayoutInflater inflater = (LayoutInflater) context
					.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			inflater.inflate(R.layout.view_memory, this, true);
		}
	}

	@Override
	public void onCreate(IReaderActivity parent, Reader reader) {
		super.onCreate(parent, reader);
		
		title = getResources().getString(R.string.memory_access_title);
		icon = R.drawable.ic_memory_access;
		
		// Initialize Widget
		initWidget();
		// Disable Widget
		enableWidget(false);

		mask = new MaskSelectionDialog(getContext(), maskListener);
	}

	@SuppressLint("NewApi")
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.read_memory:
			if (ActionType.Stop == this.action) {
				if (!adapterOption.getPassword().equals("")) {
					if(adapterOption.getPassword().length() != 8) {
						Toast.makeText(getContext(), "Password's length is must be 8", Toast.LENGTH_SHORT).show();
						return;
					}
						
					reader.setAccessPassword(adapterOption.getPassword());
				} else {
					reader.setAccessPassword(getResources().getString(R.string.default_access_password));
				}

				if (mask.getMask().equals("")) {
					reader.readMemory(adapterOption.getBank(),
							adapterOption.getOffset(),
							adapterOption.getLength());
				} else {
					reader.readMemory(adapterOption.getBank(),
							adapterOption.getOffset(),
							adapterOption.getLength(), mask.getMask());
				}
				displayMessage(
						getResources().getString(R.string.memory_read_label),
						true);
			} else {
				reader.stopOperation();
				displayMessage(getResources().getString(R.string.stop_msg),
						false);
			}
			enableWidget(false);
			break;
		case R.id.write_memory:
			if (ActionType.Stop == this.action) {
				
				if(edtWriteValue.getText().toString().isEmpty()) {
					Toast.makeText(getContext(), "WriteValue is not to be null or empty", Toast.LENGTH_SHORT).show();
					return;
				}
				
				if (!adapterOption.getPassword().equals("")) {
					if(adapterOption.getPassword().length() != 8) {
						Toast.makeText(getContext(), "Password's length is must be 8", Toast.LENGTH_SHORT).show();
						return;
					}
					
					reader.setAccessPassword(adapterOption.getPassword());
				} else {
					reader.setAccessPassword(getResources().getString(R.string.default_access_password));
				}

				if (mask.getMask().equals("")) {
					reader.writeMemory(adapterOption.getBank(), adapterOption
							.getOffset(), edtWriteValue.getText().toString());
				} else {
					reader.writeMemory(adapterOption.getBank(), adapterOption
							.getOffset(), edtWriteValue.getText().toString(),
							mask.getMask());
				}
				displayMessage(
						getResources().getString(R.string.memory_write_label),
						true);
			} else {
				reader.stopOperation();
				displayMessage(getResources().getString(R.string.stop_msg),
						false);
			}
			enableWidget(false);
			break;
		case R.id.clear:
			clearTagList();
			break;
		case R.id.mask:
			mask.show();
			break;
		}
	}

	public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
		if (!this.enabledWidgets)
			return;

		AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
		switch (position) {
		case MemoryOptionListAdapter.BANK:
			builder.setTitle(getResources().getString(
					R.string.bank_type_prompt_label));
			builder.setSingleChoiceItems(R.array.bank_type_array, adapterOption
					.getBank().value(), new DialogInterface.OnClickListener() {

				public void onClick(DialogInterface dialog, int which) {
					adapterOption.setBank(BankType.valueOf(which));
					dialog.cancel();
				}

			});
			break;
		case MemoryOptionListAdapter.OFFSET:
			builder.setTitle(getResources().getString(
					R.string.start_address_prompt_label));
			builder.setSingleChoiceItems(R.array.memory_offset_array,
					adapterOption.getOffset(),
					new DialogInterface.OnClickListener() {

						public void onClick(DialogInterface dialog, int which) {
							adapterOption.setOffset(which);
							dialog.cancel();
						}

					});
			break;
		case MemoryOptionListAdapter.LENGTH:
			builder.setTitle(getResources().getString(
					R.string.read_length_prompt_label));
			builder.setSingleChoiceItems(R.array.memory_length_array,
					adapterOption.getLength() - 1,
					new DialogInterface.OnClickListener() {

						public void onClick(DialogInterface dialog, int which) {
							adapterOption.setLength(which + 1);
							dialog.cancel();
						}

					});
			break;
		case MemoryOptionListAdapter.PASSWORD:
			final LinearLayout linear = (LinearLayout) View.inflate(
					getContext(), R.layout.dialog_access_password, null);
			final EditText txtPassword = (EditText) linear
					.findViewById(R.id.password);

			builder.setTitle(getResources().getString(
					R.string.password_prompt_label));
			builder.setView(linear);
			builder.setPositiveButton(R.string.ok_button_label,
					new DialogInterface.OnClickListener() {

						public void onClick(DialogInterface dialog, int which) {
							adapterOption.setPassword(txtPassword.getText()
									.toString());
							reader.setAccessPassword(adapterOption.getPassword());
							dialog.cancel();
						}
					});
			break;
		}
		builder.setNegativeButton(
				getResources().getString(R.string.cancel_button_label), null);
		builder.show();
	}

	@Override
	public void onItemSelected(AdapterView<?> parent, View view, int position,
			long id) {
		Log.d(TAG, String.format("onItemSelected(%d, %d, %d)", parent.getId(),
				position, id));

		if (!initChecker.init)
			return;

		switch (parent.getId()) {
		case R.id.power_gain:
			// Change Power Gain...
			reader.setPowerEx(position);
			break;
		}
	}

	@Override
	public void onNothingSelected(AdapterView<?> parent) {

	}

	DialogInterface.OnClickListener maskListener = new DialogInterface.OnClickListener() {

		@Override
		public void onClick(DialogInterface dialog, int which) {
			reader.setSelectionBank(mask.getBank());
			reader.setSelectionOffset(mask.getOffset());
			reader.setSelectionAction(mask.getAction());
			mask.setMask(mask.getMask());
		}
	};

	@Override
	public void initView() {
		// Initalize Checker
		initChecker.init();
		// Enable Activity Widget
		enableWidget(false);
		// Clear Tag List
		clearTagList();
		
		InitTask requestParamsTask = new InitTask();
		requestParamsTask.execute();
		
	}
	
	public void requestParameters() {
		// Set Continue Mode
		reader.setContinueMode(false);
		// Set Use Serial No
		reader.setUseSerialNo(false);
		// Set Access Password
		reader.setAccessPassword("");
		// Set Mask Memory Bank
		reader.setSelectionBank(mask.getBank());
		// Set Mask Offset
		reader.setSelectionOffset(mask.getOffset());
		// Set Mask Action
		reader.setSelectionAction(mask.getAction());

		// Request Mask Memory Bank
		reader.getSelectionBank();
		// Request Mask Offset
		reader.getSelectionOffset();
		// Request Mask Action
		reader.getSelectionAction();
		
		// Global band
		reader.getGlobalBand();
		
		// Request Power Gain
		reader.getPowerEx();
	}

	@Override
	public void exitView() {
		reader.stopOperation();
		this.action = ActionType.Stop;
		enableWidget(true);
	}

	@Override
	public void createView() {		
	}

	public void createView(int Globalband) {
		
		if(adapterPowerGain != null) {
			return;
		}

		if (Globalband == 8)//Japan 1W 
		{
			adapterPowerGain = ArrayAdapter.createFromResource(getContext(),
							R.array.power_gain_array,
							android.R.layout.simple_spinner_dropdown_item);
		}
		else if (Globalband == 9)//Japan 0.25W
		{
			adapterPowerGain = ArrayAdapter.createFromResource(getContext(), 
							R.array.power_gain_japan_array,
							android.R.layout.simple_spinner_dropdown_item);
		}
		else if (Globalband == 12)//Japan 0.125W
		{
			adapterPowerGain = ArrayAdapter.createFromResource(getContext(), 
							R.array.power_gain_japan_array_125,
							android.R.layout.simple_spinner_dropdown_item);
		}
		else					//Normal
		{
			adapterPowerGain = ArrayAdapter.createFromResource(getContext(), 
							R.array.power_gain_array,
							android.R.layout.simple_spinner_dropdown_item);
		}
		
		spinPowerGain.setAdapter(adapterPowerGain);
	}

	@Override
	public void onReaderStateChange(int state) {
		Log.d(TAG, String.format("onReaderStateChange(%d)", state));
		if (state == Reader.STATE_LISTEN || state == Reader.STATE_NONE)
			parent.closeSubView();
	}

	@Override
	public void onReaderReadTag(int event, String tag) {
		Log.d(TAG, String.format("onReaderReadTag(%d, %s)", event, tag));
		if (action == ActionType.ReadMemory) {
			adapterReadValue.setValue(adapterOption.getOffset(), tag);
			reader.stopOperation();
			if(!reader.IsAT288N_MA())
				action = ActionType.Stop;
			
			displayMessage("01");
			enableWidget(true);
		}
	}

	@Override
	public void onReaderResponse(int event, String code) {
		Log.d(TAG, String.format("onReaderResponse(%d, %s)", event, code));
		displayMessage(code);
		reader.stopOperation();
		if(!reader.IsAT288N_MA())
			action = ActionType.Stop;
		enableWidget(true);
	}

	@Override
	public void onReaderProperty(char code, String value) {
		Log.d(TAG, String.format("onReaderProperty(%c, %s)", code, value));
		int val = 0;
		switch (code) {
		case ReaderService.PROPERTY_SELECTION_BANK:
			val = Integer.parseInt(value);
			mask.setBank(BankType.valueOf(val));
			checkInit(InitChecker.BANK);
			break;
		case ReaderService.PROPERTY_SELECTION_OFFSET:
			val = Integer.parseInt(value);
			mask.setOffset(val);
			checkInit(InitChecker.OFFSET);
			break;
		case ReaderService.PROPERTY_SELECTION_ACTION:
			val = Integer.parseInt(value);
			mask.setAction(SelectionActionType.valueOf(val));
			checkInit(InitChecker.ACTION);
			break;
		case Reader.PROPERTY_GLOBAL_BAND:
			int globalBand = Integer.parseInt(value);			
			createView(globalBand);
			break;
		}
		if(reader.IsAT288N_MA() && reader.TagType == Reader.ISO18000_6B){
			checkInit(InitChecker.BANK);
			checkInit(InitChecker.OFFSET);
			checkInit(InitChecker.ACTION);
			
		}
	}

	@Override
	public void onReaderAction(char code) {
		Log.d(TAG, String.format("onReaderActionChange(%c)", code));
		
		switch(code) {
		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:
			enableWidget(false);
			break;
		case Reader.ACTION_STOP:
			this.action = ActionType.Stop;
			enableWidget(true);
			break;
		case Reader.ACTION_READ_MEMORY:
			this.action = ActionType.ReadMemory;
			enableWidget(true);
			break;
		case Reader.ACTION_WRITE_MEMORY:
			this.action = ActionType.WriteMemory;
			enableWidget(true);
			break;
		}
	}

	@Override
	public void onReaderExtentedProperty(char code, String value) {
		Log.d(TAG,
				String.format("onReaderExtendedProperty(%c, %s)", code, value));
		int val = Integer.parseInt(value);
		switch (code) {
		case Reader.PROPERTY_EX_POWER_GAIN:
			spinPowerGain.setSelection(val);
			checkInit(InitChecker.POWER);
			break;
		case Reader.PROPERTY_EX_TAG_TYPE:
			enableWidget(true);
			break;
		}
	}

	@Override
	public void onReaderTimeout() {
		Log.d(TAG, "onReaderTimeout()");
		displayMessage("TIMEOUT");
		reader.stopOperation();
		action = ActionType.Stop;
		enableWidget(true);
	}

	// =================================================================
	// MainActivity Widget Control Methods
	// =================================================================

	// Initialize Widget
	private void initWidget() {
		ListView listView = null;

		// Initialize progress bar
		this.progress = (ProgressBar) findViewById(R.id.progress_bar);

		// Initialize message text view
		this.message = (TextView) findViewById(R.id.memory_msg);

		// Initialize read value list view
		this.adapterReadValue = new MemoryValueListAdapter(getContext());
		listView = (ListView) findViewById(R.id.memory_list);
		listView.setAdapter(adapterReadValue);
		listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

		// Initialize write value edit text
		this.edtWriteValue = (EditText) findViewById(R.id.write_value);

		// Initialize option list view
		this.adapterOption = new MemoryOptionListAdapter(getContext());
		listView = (ListView) findViewById(R.id.memory_option);
		listView.setAdapter(adapterOption);
		listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
		listView.setOnItemClickListener(this);

		// Initialize power gain spinner
		this.spinPowerGain = (Spinner) findViewById(R.id.power_gain);
		this.spinPowerGain.setPrompt(getResources().getString(
				R.string.power_gain_prompt_label));
		this.spinPowerGain.setOnItemSelectedListener(this);

		// Initialize read memory button
		this.btnRead = (Button) findViewById(R.id.read_memory);
		this.btnRead.setOnClickListener(this);

		// Initlaiize write memory button
		this.btnWrite = (Button) findViewById(R.id.write_memory);
		this.btnWrite.setOnClickListener(this);

		// Initialize clear button
		this.btnClear = (Button) findViewById(R.id.clear);
		this.btnClear.setOnClickListener(this);

		// Initialize mask button
		this.btnMask = (Button) findViewById(R.id.mask);
		this.btnMask.setOnClickListener(this);
	}

	// Enable Widget
	private void enableWidget(boolean enabled) {
		ListView listView = (ListView) findViewById(R.id.memory_option);
		if (enabled) {
			if (this.action == ActionType.ReadMemory) {
				enabledWidgets = false;
				this.edtWriteValue.setEnabled(false);
				listView.setEnabled(false);
				this.spinPowerGain.setEnabled(false);
				this.btnRead.setText(getResources().getString(
						R.string.stop_button_label));
				this.btnRead.setEnabled(true);
				this.btnWrite.setEnabled(false);
				this.btnClear.setEnabled(false);
				this.btnMask.setEnabled(false);
			} else if (this.action == ActionType.WriteMemory) {
				enabledWidgets = false;
				this.edtWriteValue.setEnabled(false);
				listView.setEnabled(false);
				this.spinPowerGain.setEnabled(false);
				this.btnRead.setEnabled(false);
				this.btnWrite.setText(getResources().getString(
						R.string.stop_button_label));
				this.btnWrite.setEnabled(true);
				this.btnClear.setEnabled(false);
				this.btnMask.setEnabled(false);
			} else if (reader.TagType == Reader.ISO18000_6B){
				enabledWidgets = true;
				this.edtWriteValue.setEnabled(false);
				listView.setEnabled(false);
				this.spinPowerGain.setEnabled(false);
				this.btnRead.setText(getResources().getString(
						R.string.read_button_label));
				this.btnRead.setEnabled(false);
				this.btnWrite.setText(getResources().getString(
						R.string.write_button_label));
				this.btnWrite.setEnabled(false);
				this.btnClear.setEnabled(false);
				this.btnMask.setEnabled(false);
			}
			else {
				enabledWidgets = true;
				this.edtWriteValue.setEnabled(true);
				listView.setEnabled(true);
				this.spinPowerGain.setEnabled(true);
				this.btnRead.setText(getResources().getString(
						R.string.read_button_label));
				this.btnRead.setEnabled(true);
				this.btnWrite.setText(getResources().getString(
						R.string.write_button_label));
				this.btnWrite.setEnabled(true);
				this.btnClear.setEnabled(true);
				this.btnMask.setEnabled(true);
			}
		} else {
			enabledWidgets = false;
			this.edtWriteValue.setEnabled(false);
			listView.setEnabled(false);
			this.spinPowerGain.setEnabled(false);
			this.edtWriteValue.setEnabled(false);
			listView.setEnabled(false);
			this.btnRead.setEnabled(false);
			this.btnWrite.setEnabled(false);
			this.btnClear.setEnabled(false);
			this.btnMask.setEnabled(false);
		}
	}

	// Clear Tag List View
	private void clearTagList() {
		this.adapterReadValue.clear();
		this.edtWriteValue.setText("");
		this.adapterOption.setBank(BankType.EPC);
		this.adapterOption.setOffset(2);
		this.adapterOption.setLength(2);
		displayMessage(getResources().getString(R.string.memory_intro_label),
				false);
	}

	private void displayMessage(String msg, boolean showProgress) {
		progress.setVisibility(showProgress ? View.VISIBLE : View.GONE);
		message.setText(msg);
		message.setTextColor(getResources().getColor(R.color.black));
		message.setBackgroundColor(getResources().getColor(
				R.color.message_background));
	}

	private void displayMessage(String code) {
		int backColor = 0;
		String msg;

		if (code.equals("TIMEOUT")) {
			msg = getResources().getString(R.string.timeout_title);
			backColor = getResources().getColor(R.color.red);
		} else if (code.equals("01")) {
			msg = Reader.getResponses(code);
			backColor = getResources().getColor(R.color.blue);
		} else {
			msg = Reader.getResponses(code);
			backColor = getResources().getColor(R.color.red);
		}
		progress.setVisibility(View.GONE);
		message.setText(msg);
		message.setTextColor(getResources().getColor(R.color.white));
		message.setBackgroundColor(backColor);
	}

	// Check Initialize Reader Service
	private void checkInit(int index) {
		if (initChecker.init)
			return;

		initChecker.check[index] = true;
		if (initChecker.isInitialized()) {
			initChecker.init = true;
			enableWidget(true);
		}
	}

	// =================================================================
	// Declare Internal Classes
	// =================================================================

	private class InitChecker {
		public static final int POWER = 0;
		public static final int BANK = 1;
		public static final int OFFSET = 2;
		public static final int ACTION = 3;

		public boolean init;
		public boolean[] check;

		public InitChecker() {
			init();
		}
		
		public void init() {
			init = false;
			check = new boolean[] { false, false, false, false };
		}

		private boolean isInitialized() {
			return !init && check[0] && check[1] && check[2] && check[3];
		}
	}
	
	private class InitTask extends AsyncTask<Void, Void, Void> {

		private Context context = MemoryView.this.getContext();
		ProgressDialog asyncDialog = new ProgressDialog(context);
		
		@Override
		protected void onPreExecute() {
			asyncDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
			asyncDialog.setMessage("wait for initialize");
			asyncDialog.setCancelable(false);
			asyncDialog.show();
			super.onPreExecute();
		}

		@Override
		protected Void doInBackground(Void... params) {
			
			requestParameters();
			
			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			asyncDialog.dismiss();
			super.onPostExecute(result);
		}
		
	}

	@Override
	public void clearMaskParams() {
		if(mask != null) {
			mask.resetContents();
		}
	}
}
