package de.rmdir.ms2debounce;

import android.app.Activity;
import android.app.Dialog;
import android.app.AlertDialog;
import android.os.Bundle;
import android.content.Intent;
import android.content.DialogInterface;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.Button;
import android.widget.CheckBox;
import android.view.View;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.text.TextWatcher;
import android.text.Editable;

public class MS2Debounce extends Activity
{
	private DebounceModuleHelper module;

	// Calling these is expensive, so cache the result...
	private boolean loaded;
	private boolean safe_to_load;
	private int debounce_delay;
	private int settle_time;
	private int poll_time;
	private boolean hw_debounce_en;
	private int hw_debounce_time;
	private boolean drive_inactive_en;
	private boolean active_high_en;

	public MS2Debounce()
	{
		super();
		module = new DebounceModuleHelper(this);
	}

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);

		setContentView(R.layout.main);

		EditText textDelay = (EditText)findViewById(R.id.debounce_delay);
		textDelay.addTextChangedListener(new TextWatcher() {
			@Override
			public void afterTextChanged(Editable delay) {
				if (delay.toString().length() > 0) {
					module.setSavedDelay(Integer.parseInt(delay.toString()));
				}
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count, int after) {
			}

			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count) {
			}
		});

		EditText textSettle = (EditText)findViewById(R.id.settle_time);
		textSettle.addTextChangedListener(new TextWatcher() {
			@Override
			public void afterTextChanged(Editable settle_time) {
				if (settle_time.toString().length() > 0) {
					module.setSavedSettle(Integer.parseInt(settle_time.toString()));
				}
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count, int after) {
			}

			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count) {
			}
		});

		EditText textPoll = (EditText)findViewById(R.id.poll_time);
		textPoll.addTextChangedListener(new TextWatcher() {
			@Override
			public void afterTextChanged(Editable poll_time) {
				if (poll_time.toString().length() > 0) {
					module.setSavedPoll(Integer.parseInt(poll_time.toString()));
				}
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count, int after) {
			}

			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count) {
			}
		});

		EditText textHwDebounceTime = (EditText)findViewById(R.id.hw_debounce_time);
		textHwDebounceTime.addTextChangedListener(new TextWatcher() {
			@Override
			public void afterTextChanged(Editable hw_debounce_time) {
				if (hw_debounce_time.toString().length() > 0) {
					module.setSavedHwDebounceTime(Integer.parseInt(hw_debounce_time.toString()));
				}
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count, int after) {
			}

			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count) {
			}
		});

		updateUI();
	}

	private void updateUI() {
		disableUI();

		// Calling these is expensive, so cache the result...
		loaded = module.isLoaded();
		safe_to_load = module.is_safe_to_load();
		debounce_delay = module.getDelay();
		settle_time = module.getSettle();
		poll_time = module.getPoll();
		hw_debounce_en = module.getHwDebounce();
		hw_debounce_time = module.getHwDebounceTime();
		//drive_inactive_en = module.getDriveInactive();
		active_high_en = module.getActiveHigh();

		TextView text = (TextView)findViewById(R.id.text);
		text.setText("Module loaded: " + loaded + "\n" +
			"debounce_delay: " + debounce_delay + "ms\n" + 
			"settle_time: " + settle_time + "us\n" + 
			"poll_time: " + poll_time + "ms\n" + 
			"safe_to_load: " + safe_to_load + " (module loaded by this app)\n" +
			"hw_debounce: " + (hw_debounce_en?"en":"dis") + "abled, " + ((hw_debounce_time+1)*31) + "us (" + hw_debounce_time + "), active high: " + (active_high_en?"en":"dis") + "abled");

		EditText textDelay = (EditText)findViewById(R.id.debounce_delay);
		textDelay.setText(Integer.toString(module.getSavedDelay()));
		textDelay.setEnabled(true);

		EditText textSettle = (EditText)findViewById(R.id.settle_time);
		textSettle.setText(Integer.toString(module.getSavedSettle()));
		textSettle.setEnabled(true);

		EditText textPoll = (EditText)findViewById(R.id.poll_time);
		textPoll.setText(Integer.toString(module.getSavedPoll()));
		textPoll.setEnabled(true);

		EditText textHwDebounceTime = (EditText)findViewById(R.id.hw_debounce_time);
		textHwDebounceTime.setText(Integer.toString(module.getSavedHwDebounceTime()));
		textHwDebounceTime.setEnabled(true);

		Button set = (Button)findViewById(R.id.set);
		if (loaded) {
			set.setEnabled(true);
		} else {
			set.setEnabled(false);
		}

		Button load = (Button)findViewById(R.id.load);
		if (loaded) {
			load.setEnabled(false);
		} else {
			load.setEnabled(true);
		}

		Button unload = (Button)findViewById(R.id.unload);
		if (loaded) {
			unload.setEnabled(true);
		} else {
			unload.setEnabled(false);
		}

		CheckBox on_boot = (CheckBox)findViewById(R.id.on_boot);
		on_boot.setChecked(module.get_on_boot());
		if (safe_to_load) {
			on_boot.setEnabled(true);
		} else {
			on_boot.setEnabled(false);
		}

		CheckBox hw_debounce = (CheckBox)findViewById(R.id.hw_debounce);
		hw_debounce.setChecked(module.getSavedHwDebounce());
		hw_debounce.setEnabled(true);

		//CheckBox drive_inactive = (CheckBox)findViewById(R.id.drive_inactive);
		//drive_inactive.setChecked(module.getSavedDriveInactive());
		//drive_inactive.setEnabled(true);

		CheckBox active_high = (CheckBox)findViewById(R.id.active_high);
		active_high.setChecked(module.getSavedActiveHigh());
		active_high.setEnabled(true);
	}

	private void disableUI() {
		EditText textDelay = (EditText)findViewById(R.id.debounce_delay);
		textDelay.setEnabled(false);

		EditText textSettle = (EditText)findViewById(R.id.settle_time);
		textSettle.setEnabled(false);

		EditText textPoll = (EditText)findViewById(R.id.poll_time);
		textPoll.setEnabled(false);

		EditText textHwDebounceTime = (EditText)findViewById(R.id.hw_debounce_time);
		textHwDebounceTime.setEnabled(false);

		Button set = (Button)findViewById(R.id.set);
		set.setEnabled(false);

		Button load = (Button)findViewById(R.id.load);
		load.setEnabled(false);

		Button unload = (Button)findViewById(R.id.unload);
		unload.setEnabled(false);

		CheckBox on_boot = (CheckBox)findViewById(R.id.on_boot);
		on_boot.setEnabled(false);

		CheckBox hw_debounce = (CheckBox)findViewById(R.id.hw_debounce);
		hw_debounce.setEnabled(false);

		//CheckBox drive_inactive = (CheckBox)findViewById(R.id.drive_inactive);
		//drive_inactive.setEnabled(false);

		CheckBox active_high = (CheckBox)findViewById(R.id.active_high);
		active_high.setEnabled(false);
	}

	public void loadModule(View view) {
		disableUI();
		if (!module.isLoaded()) {
			try {
				if (!module.loadModule())
					showDialog(22);
			} catch (NotRootedException e) {
					showDialog(23);
			} catch (ShellException e) {
					showDialog(24);
			}
		}
		updateUI();
	}

	public void unloadModule(View view) {
		disableUI();
		if (module.isLoaded()) {
			try {
				module.unloadModule();
			} catch (NotRootedException e) {
					showDialog(23);
			} catch (ShellException e) {
					showDialog(24);
			}
		}
		updateUI();
	}

	public void setValues(View view) {
		disableUI();
		if (!module.isLoaded()) {
			try {
				if (!module.loadModule())
					showDialog(22);
			} catch (NotRootedException e) {
				showDialog(23);
			} catch (ShellException e) {
				showDialog(24);
			}
		}
		module.setAllValues();
		updateUI();
	}

	public void toggle_on_boot(View view) {
		CheckBox on_boot = (CheckBox)view;

		module.set_on_boot(on_boot.isChecked());
	}

	public void toggle_hw_debounce(View view) {
		CheckBox hw_debounce = (CheckBox)view;

		module.setSavedHwDebounce(hw_debounce.isChecked());
	}

	//public void toggle_drive_inactive(View view) {
	//	CheckBox drive_inactive = (CheckBox)view;

	//	module.setSavedDriveInactive(drive_inactive.isChecked());
	//}

	public void toggle_active_high(View view) {
		CheckBox active_high = (CheckBox)view;

		module.setSavedActiveHigh(active_high.isChecked());
	}

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

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
			case R.id.about:
				showDialog(42);
				return true;
			default:
				return super.onOptionsItemSelected(item);
		}
	}

	protected Dialog onCreateDialog(int id) {
		Dialog dlg = null;

		switch(id) {
			case 22:
				AlertDialog.Builder noload = new AlertDialog.Builder(this);
				noload.setMessage("Could not load/unload the module! Do you have a MS2/Droid2 with kernel 2.6.32?")
					.setCancelable(true)
					.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int id) {
							dialog.cancel();
						}
					});
				dlg = noload.create();
				break;
			case 23:
				AlertDialog.Builder noroot = new AlertDialog.Builder(this);
				noroot.setMessage("Could not get root access! Is this device rooted and have you granted Superuser privileges?")
					.setCancelable(true)
					.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int id) {
							dialog.cancel();
						}
					});
				dlg = noroot.create();
				break;
			case 24:
				AlertDialog.Builder shellexec = new AlertDialog.Builder(this);
				shellexec.setMessage("Problems executing shell commands as root! Is this device rooted and are insmod/rmmod binaries available?")
					.setCancelable(true)
					.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int id) {
							dialog.cancel();
						}
					});
				dlg = shellexec.create();
				break;
			case 42:
				String version;
				
				try {
					version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
				} catch (Exception e) {
					version = "?";
				}

				AlertDialog.Builder about = new AlertDialog.Builder(this);
				about.setMessage("Milestone 2 Debounce " + version + "\n\n(C) 2011 Michael Gernoth <michael@gernoth.net>\n\nThis program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA")
					.setCancelable(true)
					.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int id) {
							dialog.cancel();
						}
					});
				dlg = about.create();
				break;
			default:
				dlg = null;
				break;
		}

		return dlg;
	}
}
