package de.hacksaar.andtuer;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.InputType;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class DoorActivity extends Activity implements View.OnClickListener {

	private static final String TAG = "DoorActivity";
	private static final int DIALOG_BOOLEAN = 7;
	private static final int DIALOG_STRING = 14;
	private static final int TEXT_ID = 42;
	private final AsyncTyshell.Prompter prompter = new DialogPrompter();
	private TextView logText;
	private AsyncTyshell task;
	private String pendingMessage;

	private Dialog askBooleanDialog() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(null);
		builder.setMessage(pendingMessage);

		builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int whichButton) {
				assert task != null;
				task.promptResult(true);
			}
		});

		builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				assert task != null;
				task.promptResult(false);
			}
		});

		return builder.create();
	}

	private Dialog askStringDialog() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(null);
		builder.setMessage(pendingMessage);

		final EditText input = new EditText(this);
		input.setId(TEXT_ID);
		input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
		builder.setView(input);

		builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int whichButton) {
				assert task != null;
				String value = input.getText().toString();
				task.promptResult(value);
			}
		});

		builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int whichButton) {
				assert task != null;
				task.promptResult(null);
			}
		});

		return builder.create();
	}

	private void onBuzzClick() {
		if (task != null) {
			task.sendCommand("buzz");
		}
	}

	@Override
	public void onClick(View view) {
		switch (view.getId()) {
			case R.id.connect_button:
				onConnectClick();
				break;
			case R.id.buzz_button:
				onBuzzClick();
				break;
			case R.id.unlock_button:
				onUnlockClick();
				break;
			case R.id.disconnect_button:
				onDisconnectClick();
				break;
		}
	}

	private void onCloseClick() {
		if (task != null) {
			task.sendCommand("close");
		}
	}

	private void onConnectClick() {
		SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
		task = new AsyncTyshell(preferences.getString(DoorSettings.PREF_SERVER_HOSTNAME, DoorSettings.DEFAULT_HOST),
								preferences.getInt(DoorSettings.PREF_SERVER_PORT, DoorSettings.DEFAULT_PORT),
								preferences.getString(DoorSettings.PREF_USER_USERNAME, null),
								preferences.getString(DoorSettings.PREF_USER_KEYFILE, DoorSettings.DEFAULT_KEYFILE),
								prompter);
		task.execute();
		findViewById(R.id.connect_button).setEnabled(false);
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.door);
		for (int view : new int[]{R.id.unlock_button, R.id.buzz_button, R.id.disconnect_button, R.id.connect_button}) {
			findViewById(view).setOnClickListener(this);
		}
		logText = (TextView) findViewById(R.id.logout);
		try {
			logText.setText("Welcome to Hacksaar AndTuer, Version " +
							getPackageManager().getPackageInfo(getPackageName(), 0).versionName);
		} catch (Exception e) {
			logText.setText("Welcome to Hacksaar AndTuer, [unknown version]");
		}
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
			case DIALOG_BOOLEAN:
				return askBooleanDialog();
			case DIALOG_STRING:
				return askStringDialog();
			default:
				return super.onCreateDialog(id);
		}
	}

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

	private void onDisconnectClick() {
		if (task != null) {
			task.sendCommand("exit");
			task.disconnect();
		}
		findViewById(R.id.unlock_button).setEnabled(false);
		findViewById(R.id.buzz_button).setEnabled(false);
		findViewById(R.id.disconnect_button).setEnabled(false);
		findViewById(R.id.connect_button).setEnabled(true);
	}

	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		switch (item.getItemId()) {
			case R.id.menu_settings:
				startActivity(new Intent(this, DoorSettings.class));
				return true;
			default:
				return super.onMenuItemSelected(featureId, item);
		}
	}

	@Override
	protected void onPrepareDialog(int id, Dialog dialog) {
		switch (id) {
			case DIALOG_STRING:
				((TextView) dialog.findViewById(TEXT_ID)).setText("");
			case DIALOG_BOOLEAN:
				((AlertDialog) dialog).setMessage(pendingMessage);
				break;
			default:
				super.onPrepareDialog(id, dialog);
		}

	}

	private void onUnlockClick() {
		if (task != null) {
			task.sendCommand("unlock");
		}
	}

	private void writeLog(String msg) {
		Log.d(TAG, "Log: " + msg);
		logText.setText(logText.getText() + "\n" + msg);

		findViewById(R.id.unlock_button).setEnabled(true);
		findViewById(R.id.buzz_button).setEnabled(true);
		findViewById(R.id.disconnect_button).setEnabled(true);
	}

	private class DialogPrompter implements AsyncTyshell.Prompter {
		DialogPrompter() {
		}

		@Override
		public void promptBoolean(String message) {
			pendingMessage = message;
			runOnUiThread(new Runnable() {
				@Override
				public void run() {
					showDialog(DIALOG_BOOLEAN);
				}
			});
		}

		@Override
		public void promptString(String message) {
			pendingMessage = message;
			runOnUiThread(new Runnable() {
				@Override
				public void run() {
					showDialog(DIALOG_STRING);
				}
			});
		}

		@Override
		public void sendMessage(final String message) {
			runOnUiThread(new Runnable() {
				@Override
				public void run() {
					writeLog(message);
				}
			});
		}
	}
}