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));
    }
}
