package com.beem.project.beem.ui;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TabHost;
import android.widget.Toast;

import com.beem.project.beem.BeemService;
import com.beem.project.beem.R;

/**
 * This class represents an activity which allows the user to change his account or proxy parameters
 * 
 * @author dasilvj
 */
public class EditSettings extends Activity {

	private final static String  LOG_MSG_SETTINGS_SAVED              = "Settings saved successfully.";
	private final static String  LOG_MSG_XMPP_SETTINGS_REGISTERED    = "XMPP Settings has been registered.";
	private final static String  LOG_MSG_ACCOUNT_SETTINGS_REGISTERED = "Account Settings has been registered.";
	private final static String  LOG_MSG_PROXY_SETTINGS_REGISTERED   = "Proxy Settings has been registered.";

	private final static boolean DEFAULT_BOOLEAN_VALUE               = false;
	private final static String  DEFAULT_STRING_VALUE                = "";
	private final static int     DEFAULT_INT_VALUE                   = 0;

	private final static String  DEFAULT_XMPP_PORT                   = "5222";

	private final static int     NOTIFICATION_DURATION               = Toast.LENGTH_SHORT;

	private SharedPreferences    settings                            = null;

	private EditText             accUsernameField                    = null;
	private EditText             accPasswordField                    = null;

	private EditText             xmppServerField                     = null;
	private EditText             xmppPortField                       = null;
	private CheckBox             xmppUseTLSCheckBox                  = null;

	private CheckBox             proxyUseCheckBox                    = null;
	private Spinner              proxyTypeSpinner                    = null;
	private EditText             proxyServerField                    = null;
	private EditText             proxyPortField                      = null;
	private EditText             proxyUsernameField                  = null;
	private EditText             proxyPasswordField                  = null;

	/**
	 * Add a labeled "Account" tab on the tabbed window view passed by parameter
	 * 
	 * @param tHost
	 *            a tabbed window view
	 */
	private void addAccountTab(TabHost tHost) {
		TabHost.TabSpec accountTab = tHost.newTabSpec(getString(R.string.settings_tab_tag_account));
		accountTab.setIndicator(getString(R.string.settings_tab_label_account));
		accountTab.setContent(R.id.settings_account);
		tHost.addTab(accountTab);
	}

	/**
	 * Add a labeled "Proxy" tab on the tabbed window view passed by parameter
	 * 
	 * @param tHost
	 *            a tabbed window view
	 */
	private void addProxyTab(TabHost tHost) {
		TabHost.TabSpec proxyTab = tHost.newTabSpec(getString(R.string.settings_tab_tag_proxy));
		proxyTab.setIndicator(getString(R.string.settings_tab_label_proxy));
		proxyTab.setContent(R.id.settings_proxy);
		tHost.addTab(proxyTab);
	}

	/**
	 * Add a labeled "XMPP" tab on the tabbed window view passed by parameter
	 * 
	 * @param tHost
	 *            a tabbed window view
	 */
	private void addXMPPTab(TabHost tHost) {
		TabHost.TabSpec personalTab = tHost.newTabSpec(getString(R.string.settings_tab_tag_xmpp));
		personalTab.setIndicator(getString(R.string.settings_tab_label_xmpp));
		personalTab.setContent(R.id.settings_xmpp);
		tHost.addTab(personalTab);
	}

	/**
	 * Disable proxy parameters fields
	 */
	private void disableProxyParameters() {
		proxyTypeSpinner.setEnabled(false);
		proxyServerField.setEnabled(false);
		proxyPortField.setEnabled(false);
		proxyUsernameField.setEnabled(false);
		proxyPasswordField.setEnabled(false);
	}

	private void displayNotification(CharSequence msg) {
		Toast toast = Toast.makeText(getApplicationContext(), msg, NOTIFICATION_DURATION);
		toast.show();
	}

	/**
	 * Enable proxy parameters fields
	 */
	private void enableProxyParameters() {
		proxyTypeSpinner.setEnabled(true);
		proxyServerField.setEnabled(true);
		proxyPortField.setEnabled(true);
		proxyUsernameField.setEnabled(true);
		proxyPasswordField.setEnabled(true);
	}

	/**
	 * Retrieve the value of a CheckBox
	 * 
	 * @param viewId
	 * @return true if the CheckBox is checked, else false
	 */
	private boolean getCheckBoxValue(int viewId) {
		final CheckBox checkBox = (CheckBox) findViewById(viewId);
		if (checkBox.isChecked())
			return (true);
		return (false);
	}

	/**
	 * Retrieve account password from the preferences
	 * 
	 * @return Registered account password
	 */
	private String getRegisteredAccountPassword() {
		return (settings.getString(getString(R.string.settings_key_account_password), DEFAULT_STRING_VALUE));
	}

	/**
	 * Retrieve account username from the preferences
	 * 
	 * @return Registered account username
	 */
	private String getRegisteredAccountUsername() {
		return (settings.getString(getString(R.string.settings_key_account_username), DEFAULT_STRING_VALUE));
	}

	/**
	 * Retrieve proxy password from the preferences
	 * 
	 * @return Registered proxy password
	 */
	private String getRegisteredProxyPassword() {
		return (settings.getString(getString(R.string.settings_key_proxy_password), DEFAULT_STRING_VALUE));
	}

	/**
	 * Retrieve proxy port from the preferences
	 * 
	 * @return Registered proxy port
	 */
	private String getRegisteredProxyPort() {
		return (settings.getString(getString(R.string.settings_key_proxy_port), DEFAULT_STRING_VALUE));
	}

	/**
	 * Retrieve proxy server from the preferences
	 * 
	 * @return Registered proxy server
	 */
	private String getRegisteredProxyServer() {
		return (settings.getString(getString(R.string.settings_key_proxy_server), DEFAULT_STRING_VALUE));
	}

	/**
	 * Retrieve proxy type from the preferences
	 * 
	 * @return Registered proxy type
	 */
	private int getRegisteredProxyType() {
		return (settings.getInt(getString(R.string.settings_key_proxy_type), DEFAULT_INT_VALUE));
	}

	/**
	 * Retrieve proxy use from the preferences
	 * 
	 * @return Registered proxy use
	 */
	private boolean getRegisteredProxyUse() {
		return (settings.getBoolean(getString(R.string.settings_key_proxy_use), DEFAULT_BOOLEAN_VALUE));
	}

	/**
	 * Retrieve proxy username from the preferences
	 * 
	 * @return Registered proxy username
	 */
	private String getRegisteredProxyUsername() {
		return (settings.getString(getString(R.string.settings_key_proxy_username), DEFAULT_STRING_VALUE));
	}

	/**
	 * Retrieve xmpp port from the preferences
	 * 
	 * @return Registered xmpp port
	 */
	private String getRegisteredXMPPPort() {
		return (settings.getString(getString(R.string.settings_key_xmpp_port), DEFAULT_XMPP_PORT));
	}

	/**
	 * Retrieve xmpp server from the preferences
	 * 
	 * @return Registered xmpp server
	 */
	private String getRegisteredXMPPServer() {
		return (settings.getString(getString(R.string.settings_key_xmpp_server), DEFAULT_STRING_VALUE));
	}

	/**
	 * Retrieve TLS use from the preferences
	 * 
	 * @return Registered TLS use
	 */
	private boolean getRegisteredXMPPTLSUse() {
		return (settings.getBoolean(getString(R.string.settings_key_xmpp_tls_use), DEFAULT_BOOLEAN_VALUE));
	}

	/**
	 * Initialize Account tab fields
	 */
	private void initAccountFields() {
		accUsernameField = (EditText) findViewById(R.id.settings_account_username);
		accPasswordField = (EditText) findViewById(R.id.settings_account_password);
	}

	/**
	 * Initialize all of the components displayed in tabs (EditText fields, CheckBoxes, Spinners...)
	 */
	private void initFields() {
		initAccountFields();
		initXMPPFields();
		initProxyFields();
	}

	/**
	 * Initialize Proxy tab fields
	 */
	private void initProxyFields() {
		proxyUseCheckBox = (CheckBox) findViewById(R.id.settings_proxy_use);
		proxyTypeSpinner = (Spinner) findViewById(R.id.settings_proxy_type);
		proxyServerField = (EditText) findViewById(R.id.settings_proxy_server);
		proxyPortField = (EditText) findViewById(R.id.settings_proxy_port);
		proxyUsernameField = (EditText) findViewById(R.id.settings_proxy_username);
		proxyPasswordField = (EditText) findViewById(R.id.settings_proxy_password);
	}

	/**
	 * Initialize proxy's types spinner of the proxy tab
	 */
	private void initProxyTypesSpinner() {
		ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.proxy_types,
				android.R.layout.simple_spinner_item);
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		proxyTypeSpinner.setAdapter(adapter);
	}

	/**
	 * Initialize the checkbox allowing user to use a proxy
	 */
	private void initProxyUseCheckBox() {
		proxyUseCheckBox.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				if (proxyUseCheckBox.isChecked()) {
					enableProxyParameters();
				} else {
					disableProxyParameters();
				}
			}
		});
	}

	/**
	 * Initialize "save" buttons allowing user to save settings
	 */
	private void initSaveButtons() {
		final ArrayList<Integer> views = new ArrayList<Integer>();
		Button saveButton = null;

		views.add(R.id.settings_account_button_save);
		views.add(R.id.settings_proxy_button_save);
		views.add(R.id.settings_xmpp_button_save);

		for (int i = 0; i < views.size(); i++) {
			saveButton = (Button) findViewById(views.get(i));
			saveButton.setFocusable(true);
			saveButton.setOnClickListener(new View.OnClickListener() {

				public void onClick(View v) {
					saveSettings();
				}
			});
		}
	}

	/**
	 * Initialize tabbed window view by adding tabs and setting the default tab
	 */
	private void initTabbedWindow() {
		TabHost tHost = (TabHost) this.findViewById(R.id.settings_tab_host);
		tHost.setup();
		addAccountTab(tHost);
		addXMPPTab(tHost);
		addProxyTab(tHost);
		tHost.setCurrentTab(0);
	}

	/**
	 * Initialize XMPP tab fields
	 */
	private void initXMPPFields() {
		xmppServerField = (EditText) findViewById(R.id.settings_xmpp_server);
		xmppPortField = (EditText) findViewById(R.id.settings_xmpp_port);
		xmppUseTLSCheckBox = (CheckBox) findViewById(R.id.settings_xmpp_use_tls);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.edit_settings);
		initTabbedWindow();
		initFields();
		settings = getSharedPreferences(getString(R.string.settings_filename), MODE_PRIVATE);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater mInflater = getMenuInflater();
		mInflater.inflate(R.menu.edit_settings, menu);
		return true;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		Intent i = null;
		switch (item.getItemId()) {
		case R.id.settings_menu_create_account:
			i = new Intent(this, CreateAccount.class);
			startActivity(i);
			return true;
		case R.id.settings_menu_login:
			finish();
			return true;
		}
		return false;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void onResume() {
		super.onResume();
		refreshAccountTabFields();
		refreshXMPPTabFields();
		refreshProxyTabFields();

		if (!proxyUseCheckBox.isChecked())
			disableProxyParameters();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void onStart() {
		super.onStart();
		initProxyTypesSpinner();
		initProxyUseCheckBox();
		initSaveButtons();
	}

	/**
	 * Refresh values of "Account" tab fields
	 */
	private void refreshAccountTabFields() {
		accUsernameField.setText(getRegisteredAccountUsername());
		accPasswordField.setText(getRegisteredAccountPassword());
	}

	/**
	 * Refresh values of "Account" tab fields
	 */
	private void refreshProxyTabFields() {
		proxyUseCheckBox.setChecked(getRegisteredProxyUse());
		proxyTypeSpinner.setSelection(getRegisteredProxyType());
		proxyServerField.setText(getRegisteredProxyServer());
		proxyPortField.setText(getRegisteredProxyPort());
		proxyUsernameField.setText(getRegisteredProxyUsername());
		proxyPasswordField.setText(getRegisteredProxyPassword());
	}

	/**
	 * Refresh values of "Account" tab fields
	 */
	private void refreshXMPPTabFields() {
		xmppServerField.setText(getRegisteredXMPPServer());
		xmppPortField.setText(getRegisteredXMPPPort());
		xmppUseTLSCheckBox.setChecked(getRegisteredXMPPTLSUse());
	}

	/**
	 * Register account settings changes in SharedPreferences.Editor object passed by parameter
	 * 
	 * @param settingsEditor
	 */
	private void registerAccountSettingsChanges(SharedPreferences.Editor settingsEditor) {
		final String usernameFieldValue = accUsernameField.getText().toString();
		final String passwordFieldValue = accPasswordField.getText().toString();

		if (getRegisteredAccountUsername().equals(usernameFieldValue) == false)
			settingsEditor.putString(getString(R.string.settings_key_account_username), usernameFieldValue);
		if (getRegisteredAccountPassword().equals(passwordFieldValue) == false)
			settingsEditor.putString(getString(R.string.settings_key_account_password), passwordFieldValue);
		Log.i(getString(R.string.edit_settings_tag), LOG_MSG_ACCOUNT_SETTINGS_REGISTERED);
	}

	/**
	 * Register proxy settings changes in SharedPreferences.Editor object passed by parameter
	 * 
	 * @param settingsEditor
	 */
	private void registerProxySettingsChanges(SharedPreferences.Editor settingsEditor) {
		final int proxyTypeFieldValue = proxyTypeSpinner.getSelectedItemPosition();
		final String serverFieldValue = proxyServerField.getText().toString();
		final String portFieldValue = proxyPortField.getText().toString();
		final String usernameFieldValue = proxyUsernameField.getText().toString();
		final String passwordFieldValue = proxyPasswordField.getText().toString();

		if (getRegisteredProxyType() != proxyTypeFieldValue)
			settingsEditor.putInt(getString(R.string.settings_key_proxy_type), proxyTypeFieldValue);
		if (getRegisteredProxyServer().equals(serverFieldValue) == false)
			settingsEditor.putString(getString(R.string.settings_key_proxy_server), serverFieldValue);
		if (getRegisteredProxyPort().equals(portFieldValue) == false)
			settingsEditor.putString(getString(R.string.settings_key_proxy_port), portFieldValue);
		if (getRegisteredProxyUsername().equals(usernameFieldValue) == false)
			settingsEditor.putString(getString(R.string.settings_key_proxy_username), usernameFieldValue);
		if (getRegisteredProxyPassword().equals(passwordFieldValue) == false)
			settingsEditor.putString(getString(R.string.settings_key_proxy_password), passwordFieldValue);
		Log.i(getString(R.string.edit_settings_tag), LOG_MSG_PROXY_SETTINGS_REGISTERED);
	}

	/**
	 * Register XMPP settings changes in SharedPreferences.Editor object passed by parameter
	 * 
	 * @param settingsEditor
	 */
	private void registerXMPPSettingsChanges(SharedPreferences.Editor settingsEditor) {
		final boolean tlsUseCheckBoxValue = getCheckBoxValue(R.id.settings_xmpp_use_tls);
		final String serverFieldValue = xmppServerField.getText().toString();
		final String portFieldValue = xmppPortField.getText().toString();

		if (getRegisteredXMPPTLSUse() != tlsUseCheckBoxValue)
			settingsEditor.putBoolean(getString(R.string.settings_key_xmpp_tls_use), tlsUseCheckBoxValue);
		if (getRegisteredXMPPServer().equals(serverFieldValue) == false)
			settingsEditor.putString(getString(R.string.settings_key_xmpp_server), serverFieldValue);
		if (getRegisteredXMPPPort().equals(portFieldValue) == false)
			settingsEditor.putString(getString(R.string.settings_key_xmpp_port), portFieldValue);
		Log.i(getString(R.string.edit_settings_tag), LOG_MSG_XMPP_SETTINGS_REGISTERED);
	}

	/**
	 * Save settings in shared preferences
	 */
	private void saveSettings() {
		final SharedPreferences.Editor settingsEditor = settings.edit();
		final boolean proxyUseCheckBoxValue = getCheckBoxValue(R.id.settings_proxy_use);

		if (getRegisteredProxyUse() != proxyUseCheckBoxValue)
			settingsEditor.putBoolean(getString(R.string.settings_key_proxy_use), proxyUseCheckBoxValue);
		if (proxyUseCheckBoxValue)
			registerProxySettingsChanges(settingsEditor);
		registerAccountSettingsChanges(settingsEditor);
		registerXMPPSettingsChanges(settingsEditor);

		if (settingsEditor.commit()) {
			displayNotification(getText(R.string.settings_saved_ok));
			Log.i(getString(R.string.edit_settings_tag), LOG_MSG_SETTINGS_SAVED);
		}

		stopService(new Intent(this, BeemService.class));
	}
}
