<commit_before>package org.pocketcampus.plugin.freeroom.android.views;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.pocketcampus.android.platform.sdk.core.PluginController;
import org.pocketcampus.android.platform.sdk.tracker.Tracker;
import org.pocketcampus.android.platform.sdk.ui.element.InputBarElement;
import org.pocketcampus.android.platform.sdk.ui.element.OnKeyPressedListener;
import org.pocketcampus.android.platform.sdk.ui.layout.StandardTitledLayout;
import org.pocketcampus.android.platform.sdk.ui.list.LabeledListViewElement;
import org.pocketcampus.plugin.freeroom.R;
import org.pocketcampus.plugin.freeroom.android.FreeRoomAbstractView;
import org.pocketcampus.plugin.freeroom.android.FreeRoomController;
import org.pocketcampus.plugin.freeroom.android.FreeRoomModel;
import org.pocketcampus.plugin.freeroom.android.adapter.ActualOccupationArrayAdapter;
import org.pocketcampus.plugin.freeroom.android.adapter.ExpandableListViewAdapter;
import org.pocketcampus.plugin.freeroom.android.adapter.ExpandableListViewFavoriteAdapter;
import org.pocketcampus.plugin.freeroom.android.adapter.FRRoomSuggestionArrayAdapter;
import org.pocketcampus.plugin.freeroom.android.iface.IFreeRoomView;
import org.pocketcampus.plugin.freeroom.android.utils.FRRequestDetails;
import org.pocketcampus.plugin.freeroom.android.utils.OrderMapListFew;
import org.pocketcampus.plugin.freeroom.android.utils.SetArrayList;
import org.pocketcampus.plugin.freeroom.shared.ActualOccupation;
import org.pocketcampus.plugin.freeroom.shared.AutoCompleteRequest;
import org.pocketcampus.plugin.freeroom.shared.FRPeriod;
import org.pocketcampus.plugin.freeroom.shared.FRRequest;
import org.pocketcampus.plugin.freeroom.shared.FRRoom;
import org.pocketcampus.plugin.freeroom.shared.ImWorkingRequest;
import org.pocketcampus.plugin.freeroom.shared.Occupancy;
import org.pocketcampus.plugin.freeroom.shared.WorkingOccupancy;
import org.pocketcampus.plugin.freeroom.shared.utils.FRStruct;
import org.pocketcampus.plugin.freeroom.shared.utils.FRTimes;

import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.app.TimePickerDialog.OnTimeSetListener;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnShowListener;
import android.content.Intent;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
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.CheckBox;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.TimePicker;
import android.widget.Toast;

import com.markupartist.android.widget.ActionBar.Action;

/**
 * <code>FreeRoomHomeView</code> is the main <code>View</code>, it's the entry
 * of the plugin. It displays the availabilities for the search given, and for
 * your favorites NOW at the start.
 * <p>
 * All others views are supposed to be dialog windows, therefore it's always
 * visible.
 * <p>
 * <code>AlertDialog</code> that exists are the following:
 * <p>
 * INFO ROOM display detailed information and occupancy about a room, and give
 * the ability to share the location.
 * <p>
 * SEARCH enables the user to enter a customized search, and retrieves
 * previously entered searches.
 * <p>
 * FAVORITES show the current favorites, with the possibility to remove them one
 * by one. Adding is done by the ADD ROOM dialog.
 * <p>
 * ADD ROOM gives the possibility to construct an user-defined list of selected
 * rooms, with auto-complete capabilities. It can be user to add favorites or a
 * custom search.
 * <p>
 * SHARE give the possibility to share the location with friends through a share
 * Intent. The server will also be notified, such that approximately occupancies
 * continues to be as accurate as possible.
 * <p>
 * 
 * @author FreeRoom Project Team (2014/05)
 * @author <NAME> <<EMAIL>>
 * @author <NAME> <<EMAIL>>
 */
public class FreeRoomHomeView extends FreeRoomAbstractView implements
		IFreeRoomView {

	/* MVC STRUCTURE */
	/**
	 * FreeRoom controller in MVC scheme.
	 */
	private FreeRoomController mController;
	/**
	 * FreeRoom model in MVC scheme.
	 */
	private FreeRoomModel mModel;

	/* COMMON SHARED VALUES */
	/**
	 * Class name for logs.
	 */
	private String className = this.getClass().getSimpleName();
	/**
	 * Width of the main Activity.
	 */
	private int activityWidth;
	/**
	 * Height of the main Activity.
	 */
	private int activityHeight;
	/**
	 * Common LayoutInflater for all Layout inflated from xml.
	 */
	private LayoutInflater mLayoutInflater;

	/* UI OF MAIN ACTIVITY */
	/**
	 * Titled layout that holds the title and the main layout.
	 */
	private StandardTitledLayout titleLayout;
	/**
	 * Main layout that hold all UI components.
	 */
	private LinearLayout mainLayout;
	/**
	 * TextView to display a short message about what is currently displayed.
	 */
	private TextView mTextView;
	/**
	 * ExpandableListView to display the results of occupancies building by
	 * building.
	 */
	private ExpandableListView mExpListView;
	/**
	 * Adapter for the results (to display the occupancies).
	 */
	private ExpandableListViewAdapter<Occupancy> mExpListAdapter;

	/* VIEW/DIALOGS FOR ALL ALERTDIALOG */
	/**
	 * View that holds the INFO dialog content, defined in xml in layout folder.
	 */
	private View mInfoRoomView;
	/**
	 * AlertDialog that holds the INFO dialog.
	 */
	private AlertDialog mInfoRoomDialog;
	/**
	 * View that holds the SEARCH dialog content, defined in xml in layout
	 * folder.
	 */
	private View mSearchView;
	/**
	 * Dialog that holds the SEARCH Dialog.
	 */
	private AlertDialog mSearchDialog;
	/**
	 * View that holds the FAVORITES dialog content, defined in xml in layout
	 * folder.
	 */
	private View mFavoritesView;
	/**
	 * AlertDialog that holds the FAVORITES dialog.
	 */
	private AlertDialog mFavoritesDialog;
	/**
	 * View that holds the ADDROOM dialog content, defined in xml in layout
	 * folder.
	 */
	private View mAddRoomView;
	/**
	 * AlertDialog that holds the ADDROOM dialog.
	 */
	private AlertDialog mAddRoomDialog;
	/**
	 * View that holds the SHARE dialog content, defined in xml in layout
	 * folder.
	 */
	private View mShareView;
	/**
	 * Dialog that holds the SHARE Dialog.
	 */
	private AlertDialog mShareDialog;
	/**
	 * Dialog that holds the WARNING Dialog.
	 */
	private AlertDialog mWarningDialog;

	/* UI ELEMENTS FOR ALL DIALOGS */
	/* UI ELEMENTS FOR DIALOGS - INFO ROOM */

	/* UI ELEMENTS FOR DIALOGS - SEARCH */
	/**
	 * ListView that holds previous searches.
	 */
	private ListView mSearchPreviousListView;
	/**
	 * TextView to write "previous searches" +show/hide
	 */
	private TextView prevSearchTitle;
	/**
	 * Layout of the first part, the search input (without the second part,
	 * previous searches).
	 */
	private LinearLayout searchDialogUpperLinearLayout;
	/**
	 * Main layout of the search dialog.
	 */
	private LinearLayout searchDialogMainLinearLayout;
	/**
	 * Stores the height available
	 */
	private int searchDialogMainLayoutHeightAvailable = 0;
	/**
	 * Stores if the screen is too small
	 */
	private boolean searchDialogHasHeightExtenstionProblem = false;
	/**
	 * Ratio of dialog that should be occupied with searches input when NOT
	 * displaying previous request.
	 */
	private double searchDialogNonExtended = 0.90;
	/**
	 * Ratio of dialog that should be occupied with searches input when
	 * displaying previous request.
	 */
	private double searchDialogExtended = 0.70;
	/**
	 * Stores if the previous search has been hidden (the rest is more
	 * extended).
	 */
	private boolean searchDialogExtendMoreTriggered = false;

	/* UI ELEMENTS FOR DIALOGS - FAVORITES */

	/* UI ELEMENTS FOR DIALOGS - ADDROOM */

	/* UI ELEMENTS FOR DIALOGS - SHARE */

	/* OTHER UTILS */
	/**
	 * Enum to have types and store the last caller of the "Add" dialog.
	 * 
	 */
	private enum AddRoomCaller {
		FAVORITES, SEARCH;
	}

	/**
	 * Stores the last caller of the ADDROOM dialog.
	 */
	private AddRoomCaller lastCaller = null;

	/* ACTIONS FOR THE ACTION BAR */
	/**
	 * Action to perform a customized search, by showing the search dialog.
	 */
	private Action search = new Action() {
		public void performAction(View view) {
			displaySearchDialog();
		}

		public int getDrawable() {
			return R.drawable.magnify2x06;
		}
	};

	/**
	 * Action to edit the user's favorites, by showing the favorites dialog.
	 */
	private Action editFavorites = new Action() {
		public void performAction(View view) {
			mFavoritesAdapter.notifyDataSetChanged();
			mFavoritesDialog.show();
		}

		public int getDrawable() {
			return R.drawable.star2x28;
		}
	};

	/**
	 * Action to refresh the view (it sends the same stored request again).
	 * <p>
	 * TODO: useful? useless ? delete !
	 */
	private Action refresh = new Action() {
		public void performAction(View view) {
			refresh();
		}

		public int getDrawable() {
			return R.drawable.refresh2x01;
		}
	};

	/* MAIN ACTIVITY - OVERRIDEN METHODS */

	@Override
	protected Class<? extends PluginController> getMainControllerClass() {
		return FreeRoomController.class;
	}

	@Override
	protected void onDisplay(Bundle savedInstanceState,
			PluginController controller) {
		// Tracker
		Tracker.getInstance().trackPageView("freeroom");

		// Get and cast the controller and model
		mController = (FreeRoomController) controller;
		mModel = (FreeRoomModel) controller.getModel();

		// Setup the layout
		mLayoutInflater = this.getLayoutInflater();
		titleLayout = (StandardTitledLayout) mLayoutInflater.inflate(
				R.layout.freeroom_layout_home, null);
		mainLayout = (LinearLayout) titleLayout
				.findViewById(R.id.freeroom_layout_home_main_layout);
		// The ActionBar is added automatically when you call setContentView
		setContentView(titleLayout);
		titleLayout.setTitle(getString(R.string.freeroom_title_main_title));

		mExpListView = (ExpandableListView) titleLayout
				.findViewById(R.id.freeroom_layout_home_list);
		mTextView = (TextView) titleLayout
				.findViewById(R.id.freeroom_layout_home_text_summary);
		setTextSummary(getString(R.string.freeroom_home_init_please_wait));
		initializeView();

		// This is necessary: xml definition don't support affFillerView!!
		titleLayout.removeView(mainLayout);
		titleLayout.addFillerView(mainLayout);
	}

	/**
	 * This is called when the Activity is resumed.
	 * 
	 * If the user presses back on the Authentication window, This Activity is
	 * resumed but we do not have the freeroomCookie. In this case we close the
	 * Activity.
	 */
	@Override
	protected void onResume() {
		super.onResume();
		/*
		 * if(mModel != null && mModel.getFreeRoomCookie() == null) { // Resumed
		 * and lot logged in? go back finish(); }
		 */
	}

	/**
	 * Handles an intent for coming from outside, eg. for specific search.
	 * <p>
	 * If it's not a specific intended Intent, it will simply construct the
	 * default request and refresh it. As specified in SDK javadoc, this method
	 * is called AFTER the onCreate and onResume methods, so it's used to
	 * initiate the default behavior at (re)launch.
	 * <p>
	 * It supports:
	 * <p>
	 * http://occupancy.epfl.ch/content format, with content being the
	 * autocomplete requet.
	 * <p>
	 * TODO: pockecampus://
	 * 
	 * @param intent
	 *            the intent to handle
	 */
	@Override
	protected void handleIntent(Intent intent) {
		logV("Starting the app: handling an Intent");
		// Intent and/or action seems to be null in some cases... so we just
		// skip these cases and launch the default settings.
		if (intent != null && intent.getAction() != null) {
			if (intent.getAction().equalsIgnoreCase(
					"android.intent.action.MAIN")) {
				logV("starting MAIN and default mode");
				defaultMainStart();
			} else if (intent.getAction().equalsIgnoreCase(
					"android.intent.action.VIEW")) {
				logV("starting the app and handling simple VIEW intent");
				String errorIntentHandled = ""
						+ getString(R.string.freeroom_urisearch_error_URINotUnderstood)
						+ " "
						+ getString(R.string.freeroom_urisearch_error_URINotSupported);
				String intentScheme = intent.getScheme();
				Uri intentUri = intent.getData();
				if (intentScheme != null && intentUri != null) {
					String intentUriHost = intentUri.getHost();
					String intentUriPath = intentUri.getPath();
					if (intentUriHost != null && intentUriPath != null) {
						String intentUriPathQuery = FRStruct
								.removeFirstCharSafely(intentUriPath);
						// using standard epfl http page
						if (intentScheme.equalsIgnoreCase("http")
								&& intentUriHost
										.equalsIgnoreCase("occupancy.epfl.ch")) {
							logV("Found an EPFL http://occupancy.epfl.ch/room URI");
							logV("With room query: \"" + intentUriPathQuery + "\"");
							errorIntentHandled = searchByUriPrepareArguments(intentUriPathQuery);
						}

						// using freeroom links.
						else if (intentScheme.equalsIgnoreCase("pocketcampus")
								&& intentUriHost
										.equalsIgnoreCase("freeroom.plugin.pocketcampus.org")) {
							logV("Found a pocketcampus://freeroom.plugin.pocketcampus.org/data URI");
							logV("With room query: \"" + intentUriPathQuery + "\"");
							// TODO: do something.
							errorIntentHandled = "URI NOR supported right now!";
						} else {
							logE("Unknow URI: \"" + intentUri + "\"");
						}
					}
				}
				if (errorIntentHandled.length() != 0) {
					onErrorHandleIntent(errorIntentHandled);
				}
			} else {
				logE("ERROR: Found an unhandled action: \""
						+ intent.getAction() + "\"");
				logE("Starting the app in default mode anyway");
				defaultMainStart();
			}
		} else {
			logE("ERROR: Found a null Intent or Action !!!");
			logE("Starting the app in default mode anyway");
			defaultMainStart();
		}
	}

	/**
	 * In case of error while handling an Intent, display a message to the user,
	 * and then launch a default request (without taking the favorites into
	 * account).
	 * 
	 * @param errorMessage
	 *            the error message to display.
	 */
	private void onErrorHandleIntent(String errorMessage) {
		// TODO: display a popup
		Log.e("uri-search-error",
				getString(R.string.freeroom_urisearch_error_basis));
		Log.e("uri-search-error", errorMessage);
		Log.e("uri-search-error",
				getString(R.string.freeroom_urisearch_error_end));
		if (mController != null && mModel != null) {
			initDefaultRequest(false);
			refresh();
		}
	}

	/**
	 * Constructs the default request and refreshes it.
	 */
	private void defaultMainStart() {
		logV("Starting in default mode.");
		if (mController != null && mModel != null) {
			initDefaultRequest(true);
			refresh();
			logV("Successful start in default mode: wait for server response.");
		} else {
			logE("Controller or Model not defined: cannot start default mode.");
		}
	}

	/**
	 * Logs a given message using Log.V (VERBOSE MODE)
	 * 
	 * @param msg
	 *            message to log.
	 */
	private void logV(String msg) {
		Log.v(className, msg);
	}

	/**
	 * Logs a given message using Log.E (ERROR MODE)
	 * 
	 * @param msg
	 *            message to log.
	 */
	private void logE(String msg) {
		Log.e(className, msg);
	}

	/**
	 * Stores if a search by URI has been initiated recently, in order for
	 * auto-complete to automatically launch a new search if triggered, using
	 * <code>searchByUriMakeRequest</code>
	 */
	private boolean mSearchByUriTriggered = false;

	/**
	 * Initiates a search by URI with the given constraint as the argument for
	 * the auto-complete.
	 * 
	 * <p>
	 * If the requirement for autocomplete are not met, it will simply start a
	 * standard request (any free room now). If the autocomplete gave relevant
	 * results, it will search the availabilities of these rooms now. If
	 * autocomplete gave no results, it will also search for any free room now.
	 * 
	 * @param constraint
	 *            argument for the auto-complete to search for rooms.
	 * @return an empty String if successful, an error message if
	 */
	private String searchByUriPrepareArguments(String constraint) {
		// TODO: constraint in common!!
		if (constraint.length() < 2) {
			return getString(R.string.freeroom_urisearch_error_AutoComplete_error)
					+ " "
					+ getString(R.string.freeroom_urisearch_error_AutoComplete_precond);
		} else {
			mSearchByUriTriggered = true;
			// TODO: group
			AutoCompleteRequest req = new AutoCompleteRequest(constraint, 1);
			mController.autoCompleteBuilding(this, req);
			return "";
		}
	}

	/**
	 * Make a FRRequest with the FRRoom given in argument, for the rest of the
	 * day. If the argument is empty, it will display free room now.
	 * 
	 * @param collection
	 *            collection of FRRoom to make a new search on.
	 */
	private void searchByUriMakeRequest(Collection<FRRoom> collection) {
		mSearchByUriTriggered = false;

		boolean empty = collection.isEmpty();
		if (empty) {
			// if nothing matched the search, we notify the user.
			onErrorHandleIntent(getString(R.string.freeroom_urisearch_error_AutoComplete_error)
					+ " "
					+ getString(R.string.freeroom_urisearch_error_AutoComplete_noMatch));
		} else {
			// TODO: warn if there is more than 1 result ? Val. think no.

			// search for the rest of the day.
			FRPeriod period = FRTimes.getNextValidPeriodTillEndOfDay();
			FRRequestDetails request = null;
			List<String> uidList = new ArrayList<String>();
			SetArrayList<FRRoom> uidNonFav = new SetArrayList<FRRoom>();
			// TODO: find a simpler and more efficient way ?
			Iterator<FRRoom> iter = collection.iterator();
			while (iter.hasNext()) {
				FRRoom room = iter.next();
				uidList.add(room.getUid());
				uidNonFav.add(room);
			}
			// TODO: usergroup
			request = new FRRequestDetails(period, false, uidList, false,
					false, true, uidNonFav, 1);
			mModel.setFRRequestDetails(request, !empty);
			refresh();
		}
	}

	/* MAIN ACTIVITY - INITIALIZATION */

	@Override
	public void initializeView() {
		// retrieve display dimensions
		Rect displayRectangle = new Rect();
		Window window = this.getWindow();
		window.getDecorView().getWindowVisibleDisplayFrame(displayRectangle);
		activityWidth = displayRectangle.width();
		activityHeight = displayRectangle.height();

		mExpListAdapter = new ExpandableListViewAdapter<Occupancy>(
				getApplicationContext(), mModel.getOccupancyResults(),
				mController, this);
		mExpListView.setAdapter(mExpListAdapter);
		addActionToActionBar(refresh);
		addActionToActionBar(editFavorites);
		addActionToActionBar(search);
		initInfoDialog();
		initSearchDialog();
		initFavoritesDialog();
		initAddRoomDialog();
		initShareDialog();
		initWarningDialog();
	}

	/**
	 * Inits the dialog to diplay the information about a room.
	 */
	private void initInfoDialog() {
		// Instantiate an AlertDialog.Builder with its constructor
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle("room name");
		builder.setIcon(R.drawable.details_white_50);
		builder.setPositiveButton(
				getString(R.string.freeroom_dialog_info_share), null);
		builder.setNegativeButton(
				getString(R.string.freeroom_dialog_fav_close), null);

		// Get the AlertDialog from create()
		mInfoRoomDialog = builder.create();

		// redefine paramaters to dim screen when displayed
		WindowManager.LayoutParams lp = mInfoRoomDialog.getWindow()
				.getAttributes();
		lp.dimAmount = 0.60f;
		// these doesn't work
		lp.width = LayoutParams.FILL_PARENT;
		lp.height = LayoutParams.WRAP_CONTENT;
		mInfoRoomDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
		mInfoRoomDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_DIM_BEHIND);
		mInfoRoomDialog.getWindow().setAttributes(lp);

		mInfoRoomView = mLayoutInflater.inflate(
				R.layout.freeroom_layout_dialog_info, null);

		// these work perfectly
		mInfoRoomView.setMinimumWidth((int) (activityWidth * 0.9f));
		mInfoRoomView.setMinimumHeight((int) (activityHeight * 0.8f));

		mInfoRoomDialog.setView(mInfoRoomView);
		mInfoRoomDialog.setOnShowListener(new OnShowListener() {

			@Override
			public void onShow(DialogInterface dialog) {

			}
		});
	}

	/**
	 * Inits the dialog to diplay the favorites.
	 */
	private ExpandableListViewFavoriteAdapter mFavoritesAdapter;

	private void initFavoritesDialog() {
		// Instantiate an AlertDialog.Builder with its constructor
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(getString(R.string.freeroom_dialog_fav_title));
		builder.setIcon(R.drawable.star2x28);
		builder.setPositiveButton(getString(R.string.freeroom_dialog_fav_add),
				null);
		builder.setNegativeButton(
				getString(R.string.freeroom_dialog_fav_close), null);
		builder.setNeutralButton(getString(R.string.freeroom_dialog_fav_reset),
				null);

		// Get the AlertDialog from create()
		mFavoritesDialog = builder.create();

		// redefine paramaters to dim screen when displayed
		WindowManager.LayoutParams lp = mFavoritesDialog.getWindow()
				.getAttributes();
		lp.dimAmount = 0.60f;
		// these doesn't work
		lp.width = LayoutParams.FILL_PARENT;
		lp.height = LayoutParams.WRAP_CONTENT;
		mFavoritesDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
		mFavoritesDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_DIM_BEHIND);
		mFavoritesDialog.getWindow().setAttributes(lp);

		mFavoritesView = mLayoutInflater.inflate(
				R.layout.freeroom_layout_dialog_fav, null);

		// these work perfectly
		mFavoritesView.setMinimumWidth((int) (activityWidth * 0.9f));
		mFavoritesView.setMinimumHeight((int) (activityHeight * 0.8f));

		mFavoritesDialog.setView(mFavoritesView);
		mFavoritesDialog.setOnShowListener(new OnShowListener() {

			@Override
			public void onShow(DialogInterface dialog) {
				mFavoritesAdapter.notifyDataSetChanged();
			}
		});

		mFavoritesDialog.hide();
		mFavoritesDialog.show();
		mFavoritesDialog.dismiss();

		mFavoritesDialog
				.setOnDismissListener(new AlertDialog.OnDismissListener() {

					@Override
					public void onDismiss(DialogInterface dialog) {
						// sends a new request with the new favorites
						initDefaultRequest(true);
						refresh();
					}
				});

		Button tv = mFavoritesDialog.getButton(DialogInterface.BUTTON_POSITIVE);
		tv.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if (!mAddRoomDialog.isShowing()) {
					displayAddRoomDialog(AddRoomCaller.FAVORITES);
				}
			}
		});

		Button bt = mFavoritesDialog.getButton(DialogInterface.BUTTON_NEUTRAL);
		bt.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				mWarningDialog.show();
			}
		});

		ExpandableListView lv = (ExpandableListView) mFavoritesView
				.findViewById(R.id.freeroom_layout_dialog_fav_list);
		mFavoritesAdapter = new ExpandableListViewFavoriteAdapter(this, mModel
				.getFavorites().keySetOrdered(), mModel.getFavorites(), mModel);
		lv.setAdapter(mFavoritesAdapter);
		mFavoritesAdapter.notifyDataSetChanged();
	}

	private void displayAddRoomDialog(AddRoomCaller calling) {
		mAddRoomDialog.show();
		// TODO: reset the data ? the text input, the selected room ?
		lastCaller = calling;
	}

	private void dimissAddRoomDialog() {
		if (lastCaller.equals(AddRoomCaller.FAVORITES)) {
			Iterator<FRRoom> iter = selectedRooms.iterator();
			while (iter.hasNext()) {
				FRRoom mRoom = iter.next();
				// TODO: add all in batch!
				mModel.addFavorite(mRoom);
			}
			mFavoritesAdapter.notifyDataSetChanged();
			resetUserDefined();
		} else if (lastCaller.equals(AddRoomCaller.SEARCH)) {
			// we do nothing: reset will be done at search time
			mSummarySelectedRoomsTextViewSearchMenu
					.setText(getSummaryTextFromCollection(selectedRooms));
		}
	}

	private void initAddRoomDialog() {
		// Instantiate an AlertDialog.Builder with its constructor
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(getString(R.string.freeroom_dialog_add_room_title));
		builder.setIcon(R.drawable.ic_dialog_adding);

		// Get the AlertDialog from create()
		mAddRoomDialog = builder.create();

		// redefine paramaters to dim screen when displayed
		WindowManager.LayoutParams lp = mAddRoomDialog.getWindow()
				.getAttributes();
		lp.dimAmount = 0.60f;
		// these doesn't work
		lp.width = LayoutParams.FILL_PARENT;
		lp.height = LayoutParams.WRAP_CONTENT;
		mAddRoomDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
		mAddRoomDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_DIM_BEHIND);
		mAddRoomDialog.getWindow().setAttributes(lp);

		mAddRoomView = mLayoutInflater.inflate(
				R.layout.freeroom_layout_dialog_add_room, null);
		// these work perfectly
		mAddRoomView.setMinimumWidth((int) (activityWidth * 0.9f));
		// mAddRoomView.setMinimumHeight((int) (activityHeight * 0.8f));

		mAddRoomDialog.setView(mAddRoomView);
		mAddRoomDialog.setOnShowListener(new OnShowListener() {

			@Override
			public void onShow(DialogInterface dialog) {
				// searchButton.setEnabled(auditSubmit() == 0);
			}
		});

		Button bt_done = (Button) mAddRoomView
				.findViewById(R.id.freeroom_layout_dialog_add_room_done);
		bt_done.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				dismissSoftKeyBoard(v);
				mAddRoomDialog.dismiss();
				dimissAddRoomDialog();
			}
		});

		mSummarySelectedRoomsTextView = (TextView) mAddRoomView
				.findViewById(R.id.freeroom_layout_dialog_add_room_summary);

		UIConstructInputBar();
		LinearLayout ll = (LinearLayout) mAddRoomView
				.findViewById(R.id.freeroom_layout_dialog_add_layout_main);
		ll.addView(mAutoCompleteSuggestionInputBarElement);
		createSuggestionsList();

	}

	private void initShareDialog() {
		// Instantiate an AlertDialog.Builder with its constructor
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(getString(R.string.freeroom_dialog_share_title));
		builder.setPositiveButton(
				getString(R.string.freeroom_dialog_share_button_friends), null);
		builder.setNegativeButton(getString(R.string.freeroom_search_cancel),
				null);
		builder.setNeutralButton(
				getString(R.string.freeroom_dialog_share_button_server), null);
		builder.setIcon(R.drawable.share_white_50);

		// Get the AlertDialog from create()
		mShareDialog = builder.create();

		// redefine paramaters to dim screen when displayed
		WindowManager.LayoutParams lp = mShareDialog.getWindow()
				.getAttributes();
		lp.dimAmount = 0.60f;
		// these doesn't work
		lp.width = LayoutParams.FILL_PARENT;
		lp.height = LayoutParams.FILL_PARENT;
		mShareDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
		mShareDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_DIM_BEHIND);
		mShareDialog.getWindow().setAttributes(lp);

		mShareView = mLayoutInflater.inflate(
				R.layout.freeroom_layout_dialog_share, null);
		// these work perfectly
		mShareView.setMinimumWidth((int) (activityWidth * 0.95f));
		// mShareView.setMinimumHeight((int) (activityHeight * 0.8f));
		mShareDialog.setOnShowListener(new OnShowListener() {

			@Override
			public void onShow(DialogInterface dialog) {
				dismissSoftKeyBoard(mShareView);
			}
		});

		mShareDialog.setView(mShareView);

	}

	public void displayShareDialog(final FRPeriod mPeriod, final FRRoom mRoom) {
		mShareDialog.hide();
		mShareDialog.show();

		final TextView tv = (TextView) mShareView
				.findViewById(R.id.freeroom_layout_dialog_share_textBasic);
		tv.setText(wantToShare(mPeriod, mRoom, ""));

		final EditText ed = (EditText) mShareView
				.findViewById(R.id.freeroom_layout_dialog_share_text_edit);
		ed.setOnEditorActionListener(new OnEditorActionListener() {

			@Override
			public boolean onEditorAction(TextView arg0, int arg1, KeyEvent arg2) {
				tv.setText(wantToShare(mPeriod, mRoom, ed.getText().toString()));
				dismissSoftKeyBoard(arg0);
				return true;
			}
		});

		Button shareWithServer = mShareDialog
				.getButton(DialogInterface.BUTTON_NEUTRAL);
		shareWithServer.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				share(mPeriod, mRoom, false, ed.getText().toString());
				mShareDialog.dismiss();
			}
		});

		Button shareWithFriends = mShareDialog
				.getButton(DialogInterface.BUTTON_POSITIVE);
		shareWithFriends.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				share(mPeriod, mRoom, true, ed.getText().toString());
				mShareDialog.dismiss();
			}
		});

		Spinner spinner = (Spinner) mShareView
				.findViewById(R.id.freeroom_layout_dialog_share_spinner_course);
		// Create an ArrayAdapter using the string array and a default spinner
		// layout
		ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
				this, R.array.planets_array,
				android.R.layout.simple_spinner_item);
		// Specify the layout to use when the list of choices appears
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		// Apply the mFavoritesAdapter to the spinner
		spinner.setAdapter(adapter);

		spinner.setOnItemSelectedListener(new OnItemSelectedListener() {

			@Override
			public void onItemSelected(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {
				// TODO do something with that
				System.out.println("selected" + arg0.getItemAtPosition(arg2));
			}

			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
				// TODO find out how is this relevant
				System.out.println("nothing selected!");
			}

		});

		// it's automatically in center of screen!
		mShareDialog.show();
	}

	/**
	 * Dismiss the keyboard associated with the view.
	 * 
	 * @param v
	 */
	private void dismissSoftKeyBoard(View v) {
		InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
	}

	/**
	 * Inits the dialog to diplay the information about a room.
	 */
	private void initSearchDialog() {
		// Instantiate an AlertDialog.Builder with its constructor
		AlertDialog.Builder builder = new AlertDialog.Builder(this);

		// Various setter methods to set the searchDialog characteristics

		builder.setTitle(getString(R.string.freeroom_search_title));
		builder.setPositiveButton(getString(R.string.freeroom_search_search),
				null);
		builder.setNegativeButton(getString(R.string.freeroom_search_cancel),
				null);
		builder.setNeutralButton(getString(R.string.freeroom_search_reset),
				null);
		builder.setIcon(R.drawable.magnify2x06);

		// Get the AlertDialog from create()

		mSearchDialog = builder.create();

		// redefine paramaters to dim screen when displayed
		WindowManager.LayoutParams lp = mSearchDialog.getWindow()
				.getAttributes();
		lp.dimAmount = 0.60f;
		// these doesn't work
		lp.width = LayoutParams.FILL_PARENT;
		lp.height = LayoutParams.FILL_PARENT;
		mSearchDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
		mSearchDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_DIM_BEHIND);
		mSearchDialog.getWindow().setAttributes(lp);

		mSearchView = mLayoutInflater.inflate(
				R.layout.freeroom_layout_dialog_search, null);
		// these work perfectly
		mSearchView.setMinimumWidth((int) (activityWidth * 0.9f));
		mSearchView.setMinimumHeight((int) (activityHeight * 0.8f));

		mSearchDialog.setView(mSearchView);
		final String textTitlePrevious = getString(R.string.freeroom_search_previous_search);
		prevSearchTitle = (TextView) mSearchView
				.findViewById(R.id.freeroom_layout_dialog_search_prev_search_title);
		prevSearchTitle.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				searchDialogMissSpaceExtendChangeState(searchDialogExtendMoreTriggered);
				if (searchDialogHasHeightExtenstionProblem) {
					if (searchDialogExtendMoreTriggered) {
						prevSearchTitle
								.setText(textTitlePrevious
										+ ": "
										+ getString(R.string.freeroom_search_previous_hide));
					} else {
						prevSearchTitle
								.setText(textTitlePrevious
										+ ": "
										+ getString(R.string.freeroom_search_previous_show));
					}
				}
				searchDialogExtendMoreTriggered = !searchDialogExtendMoreTriggered;
			}
		});

		mSearchDialog.setOnShowListener(new OnShowListener() {

			@Override
			public void onShow(DialogInterface dialog) {
				searchButton.setEnabled(auditSubmit() == 0);
				if (mModel.getPreviousRequest().isEmpty()) {
					prevSearchTitle.setText("");
				} else if (searchDialogHasHeightExtenstionProblem) {
					prevSearchTitle
							.setText(textTitlePrevious
									+ ": "
									+ getString(R.string.freeroom_search_previous_show));
				} else {
					prevSearchTitle.setText(textTitlePrevious);
				}
			}
		});
		// this is necessary o/w buttons don't exists!
		mSearchDialog.hide();
		mSearchDialog.show();
		mSearchDialog.dismiss();
		resetButton = mSearchDialog.getButton(DialogInterface.BUTTON_NEUTRAL);
		searchButton = mSearchDialog.getButton(DialogInterface.BUTTON_POSITIVE);

		mSummarySelectedRoomsTextViewSearchMenu = (TextView) mSearchView
				.findViewById(R.id.freeroom_layout_dialog_search_text_summary);
		// the view will be removed or the text changed, no worry
		mSummarySelectedRoomsTextViewSearchMenu.setText("empty");

		// display the previous searches
		mSearchPreviousListView = (ListView) mSearchView
				.findViewById(R.id.freeroom_layout_dialog_search_prev_search_list);
		ArrayAdapter<FRRequestDetails> adapter = new ArrayAdapter<FRRequestDetails>(
				this, R.layout.sdk_list_entry, R.id.sdk_list_entry_text,
				mModel.getPreviousRequest());
		mSearchPreviousListView.setAdapter(adapter);
		mSearchPreviousListView
				.setOnItemClickListener(new OnItemClickListener() {

					@Override
					public void onItemClick(AdapterView<?> arg0, View arg1,
							int arg2, long arg3) {
						FRRequestDetails req = mModel.getPreviousRequest().get(
								arg2);
						if (req != null) {
							fillSearchDialog(req);
						}

						searchDialogExtendMoreTriggered = true;
						if (searchDialogHasHeightExtenstionProblem) {
							prevSearchTitle
									.setText(textTitlePrevious
											+ ": "
											+ getString(R.string.freeroom_search_previous_show));
						}
						searchDialogMissSpaceExtendChangeState(false);
					}
				});

		searchDialogUpperLinearLayout = (LinearLayout) mSearchDialog
				.findViewById(R.id.freeroom_layout_dialog_search_scroll_main);
		searchDialogMainLinearLayout = (LinearLayout) mSearchDialog
				.findViewById(R.id.freeroom_layout_dialog_search_main);

		initSearch();
	}

	/**
	 * Finds if the available height in the search popup is not enough to store
	 * the layout, in order the minimize it's size.
	 * <p>
	 * TODO: this method has an issue and never work on 1st time! The mock
	 * filling seems not to be working regarding to the mesurements.
	 * 
	 * @return true if no problem
	 */
	private boolean findIfHeightProblem() {
		// TODO: seems useless regarding the issue
		searchDialogUpperLinearLayout
				.setLayoutParams(new LinearLayout.LayoutParams(
						LinearLayout.LayoutParams.FILL_PARENT, 1700));
		searchDialogUpperLinearLayout
				.setLayoutParams(new LinearLayout.LayoutParams(
						LinearLayout.LayoutParams.FILL_PARENT,
						LinearLayout.LayoutParams.WRAP_CONTENT));
		FRRequestDetails request = validRequest(true);
		request.setAny(false);
		request.setFav(true);
		request.setUser(true);
		SetArrayList<FRRoom> set = new SetArrayList<FRRoom>(100);
		List<String> uidList = new ArrayList<String>(100);
		for (int i = 0; i < 100; i++) {
			set.add(new FRRoom("BC898989", i + "123"));
			uidList.add(i + "123");
		}
		request.setUidNonFav(set);
		request.setUidList(uidList);
		fillSearchDialog(request);
		mSearchDialog.show();
		// TODO: seems useless regarding the issue
		searchDialogUpperLinearLayout.refreshDrawableState();
		searchDialogUpperLinearLayout.getDrawableState();
		searchDialogMainLayoutHeightAvailable = searchDialogMainLinearLayout
				.getMeasuredHeight();
		boolean toreturn = (searchDialogUpperLinearLayout.getMeasuredHeight() > (searchDialogExtended * searchDialogMainLayoutHeightAvailable));
		fillSearchDialog();
		return toreturn;
	}

	/**
	 * Display the search dialog and checks the compatibility of the UI and make
	 * some change if necessary.
	 */
	private void displaySearchDialog() {
		if (findIfHeightProblem()) {
			searchDialogHasHeightExtenstionProblem = true;
		}
		fillSearchDialog();
		if (!mModel.getPreviousRequest().isEmpty()) {
			searchDialogMissSpaceExtendChangeState(false);
		} else {
			searchDialogUpperLinearLayout
					.setLayoutParams(new LinearLayout.LayoutParams(
							LinearLayout.LayoutParams.FILL_PARENT,
							LinearLayout.LayoutParams.WRAP_CONTENT));
		}
		mSearchDialog.show();
	}

	/**
	 * Modify the height of the upper layout of the search dialog in order to
	 * show/hide the previous requests.
	 * 
	 * @param lessExtend
	 */
	private void searchDialogMissSpaceExtendChangeState(boolean lessExtend) {
		if (searchDialogHasHeightExtenstionProblem) {
			int height = (int) (searchDialogNonExtended * searchDialogMainLayoutHeightAvailable);

			if (lessExtend) {
				height = (int) (searchDialogExtended * searchDialogMainLayoutHeightAvailable);
			}
			searchDialogUpperLinearLayout
					.setLayoutParams(new LinearLayout.LayoutParams(
							LinearLayout.LayoutParams.FILL_PARENT, height));
			searchDialogUpperLinearLayout.refreshDrawableState();
		}
	}

	private void initWarningDialog() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(getString(R.string.freeroom_dialog_warn_title));
		builder.setMessage(getString(R.string.freeroom_dialog_warn_text));
		builder.setIcon(R.drawable.warning_white_50);
		builder.setPositiveButton(
				getString(R.string.freeroom_dialog_warn_reset),
				new AlertDialog.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						mModel.resetFavorites();
						mFavoritesAdapter.notifyDataSetChanged();
					}
				});
		builder.setNegativeButton(
				getString(R.string.freeroom_dialog_warn_cancel), null);

		// Get the AlertDialog from create()
		mWarningDialog = builder.create();

		// redefine paramaters to dim screen when displayed
		WindowManager.LayoutParams lp = mWarningDialog.getWindow()
				.getAttributes();
		lp.dimAmount = 0.60f;
		// these doesn't work
		lp.width = LayoutParams.WRAP_CONTENT;
		lp.height = LayoutParams.WRAP_CONTENT;
		mWarningDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
		mWarningDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_DIM_BEHIND);
		mWarningDialog.getWindow().setAttributes(lp);
	}

	public boolean onTouchEvent(MotionEvent event) {

		if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
			System.out
					.println("TOuch outside the dialog ******************** ");
			mSearchDialog.dismiss();
		}
		return false;
	}

	/**
	 * Overrides the legacy <code>onKeyDown</code> method in order to close the
	 * dialog if one was opened. TODO: test if really needed.
	 * 
	 * @param keyCode
	 * @param event
	 * @return
	 */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {

		// Override back button
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			boolean flag = false;
			if (mInfoRoomDialog.isShowing()) {
				mInfoRoomDialog.dismiss();
				flag = true;
			}
			if (mSearchDialog.isShowing()) {
				mSearchDialog.dismiss();
				flag = true;
			}
			if (mFavoritesDialog.isShowing()) {
				mFavoritesDialog.dismiss();
				flag = true;
			}
			selectedRooms.clear();
			if (flag) {
				resetUserDefined();
				return true;
			}
		}
		return super.onKeyDown(keyCode, event);
	}

	@Override
	public void anyError() {
		setTextSummary(getString(R.string.freeroom_home_error_sorry));
	}

	/**
	 * Sets the summary text box to the specified text.
	 * 
	 * @param text
	 *            the new summary to be displayed.
	 */
	private void setTextSummary(String text) {
		// always start by space!
		mTextView.setText(" " + text);
	}

	/**
	 * Constructs the default request and sets it in the model for future use.
	 * You may call <code>refresh</code> in order to actually send it to the
	 * server.
	 * 
	 * @param useFavorites
	 *            if the constructor of the request should consider the
	 *            favorites or not
	 */
	private void initDefaultRequest(boolean useFavorites) {
		mModel.setFRRequestDetails(validRequest(useFavorites), false);
	}

	/**
	 * Construct a valid and default request. If useFavorites is true, it will
	 * check all the favorites for the next valid period, otherwise or if there
	 * are not.
	 * 
	 * @param useFavorites
	 *            if it should consider the favorites or not
	 * @return a valid and default request, based or nor on the favorites.
	 */
	private FRRequestDetails validRequest(boolean useFavorites) {
		OrderMapListFew<String, List<FRRoom>, FRRoom> set = mModel
				.getFavorites();
		FRRequestDetails details = null;
		// if there are no favorites or we dont want to use them.
		if (set.isEmpty() || !useFavorites) {
			// NO FAV = check all free rooms
			// TODO change group accordingly, set to 1 by default and for
			// testing purpose

			details = new FRRequestDetails(FRTimes.getNextValidPeriod(), true,
					new ArrayList<String>(1), true, false, false,
					new SetArrayList<FRRoom>(), 1);
		} else {
			// FAV: check occupancy of ALL favs
			ArrayList<String> array = new ArrayList<String>(set.size());

			addAllFavoriteToCollection(array, AddCollectionCaller.SEARCH, true);

			// TODO change group accordingly, set to 1 by default and for
			// testing purpose

			details = new FRRequestDetails(FRTimes.getNextValidPeriod(), false,
					array, false, true, false, new SetArrayList<FRRoom>(), 1);
		}
		return details;
	}

	/**
	 * Asks the controller to send again the request which was already set in
	 * the model.
	 */
	private void refresh() {
		setTextSummary(getString(R.string.freeroom_home_please_wait));
		mController.sendFRRequest(this);
	}

	@Override
	public void occupancyResultsUpdated() {
		StringBuilder build = new StringBuilder(50);
		if (mModel.getOccupancyResults().isEmpty()) {
			build.append(getString(R.string.freeroom_home_error_no_results));
		} else {
			FRRequest request = mModel.getFRRequestDetails();

			if (request.isOnlyFreeRooms()) {
				build.append(getString(R.string.freeroom_home_info_free_rooms));
			} else {
				build.append(getString(R.string.freeroom_home_info_rooms));
			}
			FRPeriod period = mModel.getOverAllTreatedPeriod();
			build.append(generateFullTimeSummary(period));<commit_msg>[freeroom.android] to fix: period gets corrupted by server<commit_after>package org.pocketcampus.plugin.freeroom.android.views;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.pocketcampus.android.platform.sdk.core.PluginController;
import org.pocketcampus.android.platform.sdk.tracker.Tracker;
import org.pocketcampus.android.platform.sdk.ui.element.InputBarElement;
import org.pocketcampus.android.platform.sdk.ui.element.OnKeyPressedListener;
import org.pocketcampus.android.platform.sdk.ui.layout.StandardTitledLayout;
import org.pocketcampus.android.platform.sdk.ui.list.LabeledListViewElement;
import org.pocketcampus.plugin.freeroom.R;
import org.pocketcampus.plugin.freeroom.android.FreeRoomAbstractView;
import org.pocketcampus.plugin.freeroom.android.FreeRoomController;
import org.pocketcampus.plugin.freeroom.android.FreeRoomModel;
import org.pocketcampus.plugin.freeroom.android.adapter.ActualOccupationArrayAdapter;
import org.pocketcampus.plugin.freeroom.android.adapter.ExpandableListViewAdapter;
import org.pocketcampus.plugin.freeroom.android.adapter.ExpandableListViewFavoriteAdapter;
import org.pocketcampus.plugin.freeroom.android.adapter.FRRoomSuggestionArrayAdapter;
import org.pocketcampus.plugin.freeroom.android.iface.IFreeRoomView;
import org.pocketcampus.plugin.freeroom.android.utils.FRRequestDetails;
import org.pocketcampus.plugin.freeroom.android.utils.OrderMapListFew;
import org.pocketcampus.plugin.freeroom.android.utils.SetArrayList;
import org.pocketcampus.plugin.freeroom.shared.ActualOccupation;
import org.pocketcampus.plugin.freeroom.shared.AutoCompleteRequest;
import org.pocketcampus.plugin.freeroom.shared.FRPeriod;
import org.pocketcampus.plugin.freeroom.shared.FRRequest;
import org.pocketcampus.plugin.freeroom.shared.FRRoom;
import org.pocketcampus.plugin.freeroom.shared.ImWorkingRequest;
import org.pocketcampus.plugin.freeroom.shared.Occupancy;
import org.pocketcampus.plugin.freeroom.shared.WorkingOccupancy;
import org.pocketcampus.plugin.freeroom.shared.utils.FRStruct;
import org.pocketcampus.plugin.freeroom.shared.utils.FRTimes;

import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.app.TimePickerDialog.OnTimeSetListener;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnShowListener;
import android.content.Intent;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
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.CheckBox;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.TimePicker;
import android.widget.Toast;

import com.markupartist.android.widget.ActionBar.Action;

/**
 * <code>FreeRoomHomeView</code> is the main <code>View</code>, it's the entry
 * of the plugin. It displays the availabilities for the search given, and for
 * your favorites NOW at the start.
 * <p>
 * All others views are supposed to be dialog windows, therefore it's always
 * visible.
 * <p>
 * <code>AlertDialog</code> that exists are the following:
 * <p>
 * INFO ROOM display detailed information and occupancy about a room, and give
 * the ability to share the location.
 * <p>
 * SEARCH enables the user to enter a customized search, and retrieves
 * previously entered searches.
 * <p>
 * FAVORITES show the current favorites, with the possibility to remove them one
 * by one. Adding is done by the ADD ROOM dialog.
 * <p>
 * ADD ROOM gives the possibility to construct an user-defined list of selected
 * rooms, with auto-complete capabilities. It can be user to add favorites or a
 * custom search.
 * <p>
 * SHARE give the possibility to share the location with friends through a share
 * Intent. The server will also be notified, such that approximately occupancies
 * continues to be as accurate as possible.
 * <p>
 * 
 * @author FreeRoom Project Team (2014/05)
 * @author <NAME> <<EMAIL>>
 * @author <NAME> <<EMAIL>>
 */
public class FreeRoomHomeView extends FreeRoomAbstractView implements
		IFreeRoomView {

	/* MVC STRUCTURE */
	/**
	 * FreeRoom controller in MVC scheme.
	 */
	private FreeRoomController mController;
	/**
	 * FreeRoom model in MVC scheme.
	 */
	private FreeRoomModel mModel;

	/* COMMON SHARED VALUES */
	/**
	 * Class name for logs.
	 */
	private String className = this.getClass().getSimpleName();
	/**
	 * Width of the main Activity.
	 */
	private int activityWidth;
	/**
	 * Height of the main Activity.
	 */
	private int activityHeight;
	/**
	 * Common LayoutInflater for all Layout inflated from xml.
	 */
	private LayoutInflater mLayoutInflater;

	/* UI OF MAIN ACTIVITY */
	/**
	 * Titled layout that holds the title and the main layout.
	 */
	private StandardTitledLayout titleLayout;
	/**
	 * Main layout that hold all UI components.
	 */
	private LinearLayout mainLayout;
	/**
	 * TextView to display a short message about what is currently displayed.
	 */
	private TextView mTextView;
	/**
	 * ExpandableListView to display the results of occupancies building by
	 * building.
	 */
	private ExpandableListView mExpListView;
	/**
	 * Adapter for the results (to display the occupancies).
	 */
	private ExpandableListViewAdapter<Occupancy> mExpListAdapter;

	/* VIEW/DIALOGS FOR ALL ALERTDIALOG */
	/**
	 * View that holds the INFO dialog content, defined in xml in layout folder.
	 */
	private View mInfoRoomView;
	/**
	 * AlertDialog that holds the INFO dialog.
	 */
	private AlertDialog mInfoRoomDialog;
	/**
	 * View that holds the SEARCH dialog content, defined in xml in layout
	 * folder.
	 */
	private View mSearchView;
	/**
	 * Dialog that holds the SEARCH Dialog.
	 */
	private AlertDialog mSearchDialog;
	/**
	 * View that holds the FAVORITES dialog content, defined in xml in layout
	 * folder.
	 */
	private View mFavoritesView;
	/**
	 * AlertDialog that holds the FAVORITES dialog.
	 */
	private AlertDialog mFavoritesDialog;
	/**
	 * View that holds the ADDROOM dialog content, defined in xml in layout
	 * folder.
	 */
	private View mAddRoomView;
	/**
	 * AlertDialog that holds the ADDROOM dialog.
	 */
	private AlertDialog mAddRoomDialog;
	/**
	 * View that holds the SHARE dialog content, defined in xml in layout
	 * folder.
	 */
	private View mShareView;
	/**
	 * Dialog that holds the SHARE Dialog.
	 */
	private AlertDialog mShareDialog;
	/**
	 * Dialog that holds the WARNING Dialog.
	 */
	private AlertDialog mWarningDialog;

	/* UI ELEMENTS FOR ALL DIALOGS */
	/* UI ELEMENTS FOR DIALOGS - INFO ROOM */

	/* UI ELEMENTS FOR DIALOGS - SEARCH */
	/**
	 * ListView that holds previous searches.
	 */
	private ListView mSearchPreviousListView;
	/**
	 * TextView to write "previous searches" +show/hide
	 */
	private TextView prevSearchTitle;
	/**
	 * Layout of the first part, the search input (without the second part,
	 * previous searches).
	 */
	private LinearLayout searchDialogUpperLinearLayout;
	/**
	 * Main layout of the search dialog.
	 */
	private LinearLayout searchDialogMainLinearLayout;
	/**
	 * Stores the height available
	 */
	private int searchDialogMainLayoutHeightAvailable = 0;
	/**
	 * Stores if the screen is too small
	 */
	private boolean searchDialogHasHeightExtenstionProblem = false;
	/**
	 * Ratio of dialog that should be occupied with searches input when NOT
	 * displaying previous request.
	 */
	private double searchDialogNonExtended = 0.90;
	/**
	 * Ratio of dialog that should be occupied with searches input when
	 * displaying previous request.
	 */
	private double searchDialogExtended = 0.70;
	/**
	 * Stores if the previous search has been hidden (the rest is more
	 * extended).
	 */
	private boolean searchDialogExtendMoreTriggered = false;

	/* UI ELEMENTS FOR DIALOGS - FAVORITES */

	/* UI ELEMENTS FOR DIALOGS - ADDROOM */

	/* UI ELEMENTS FOR DIALOGS - SHARE */

	/* OTHER UTILS */
	/**
	 * Enum to have types and store the last caller of the "Add" dialog.
	 * 
	 */
	private enum AddRoomCaller {
		FAVORITES, SEARCH;
	}

	/**
	 * Stores the last caller of the ADDROOM dialog.
	 */
	private AddRoomCaller lastCaller = null;

	/* ACTIONS FOR THE ACTION BAR */
	/**
	 * Action to perform a customized search, by showing the search dialog.
	 */
	private Action search = new Action() {
		public void performAction(View view) {
			displaySearchDialog();
		}

		public int getDrawable() {
			return R.drawable.magnify2x06;
		}
	};

	/**
	 * Action to edit the user's favorites, by showing the favorites dialog.
	 */
	private Action editFavorites = new Action() {
		public void performAction(View view) {
			mFavoritesAdapter.notifyDataSetChanged();
			mFavoritesDialog.show();
		}

		public int getDrawable() {
			return R.drawable.star2x28;
		}
	};

	/**
	 * Action to refresh the view (it sends the same stored request again).
	 * <p>
	 * TODO: useful? useless ? delete !
	 */
	private Action refresh = new Action() {
		public void performAction(View view) {
			refresh();
		}

		public int getDrawable() {
			return R.drawable.refresh2x01;
		}
	};

	/* MAIN ACTIVITY - OVERRIDEN METHODS */

	@Override
	protected Class<? extends PluginController> getMainControllerClass() {
		return FreeRoomController.class;
	}

	@Override
	protected void onDisplay(Bundle savedInstanceState,
			PluginController controller) {
		// Tracker
		Tracker.getInstance().trackPageView("freeroom");

		// Get and cast the controller and model
		mController = (FreeRoomController) controller;
		mModel = (FreeRoomModel) controller.getModel();

		// Setup the layout
		mLayoutInflater = this.getLayoutInflater();
		titleLayout = (StandardTitledLayout) mLayoutInflater.inflate(
				R.layout.freeroom_layout_home, null);
		mainLayout = (LinearLayout) titleLayout
				.findViewById(R.id.freeroom_layout_home_main_layout);
		// The ActionBar is added automatically when you call setContentView
		setContentView(titleLayout);
		titleLayout.setTitle(getString(R.string.freeroom_title_main_title));

		mExpListView = (ExpandableListView) titleLayout
				.findViewById(R.id.freeroom_layout_home_list);
		mTextView = (TextView) titleLayout
				.findViewById(R.id.freeroom_layout_home_text_summary);
		setTextSummary(getString(R.string.freeroom_home_init_please_wait));
		initializeView();

		// This is necessary: xml definition don't support affFillerView!!
		titleLayout.removeView(mainLayout);
		titleLayout.addFillerView(mainLayout);
	}

	/**
	 * This is called when the Activity is resumed.
	 * 
	 * If the user presses back on the Authentication window, This Activity is
	 * resumed but we do not have the freeroomCookie. In this case we close the
	 * Activity.
	 */
	@Override
	protected void onResume() {
		super.onResume();
		/*
		 * if(mModel != null && mModel.getFreeRoomCookie() == null) { // Resumed
		 * and lot logged in? go back finish(); }
		 */
	}

	/**
	 * Handles an intent for coming from outside, eg. for specific search.
	 * <p>
	 * If it's not a specific intended Intent, it will simply construct the
	 * default request and refresh it. As specified in SDK javadoc, this method
	 * is called AFTER the onCreate and onResume methods, so it's used to
	 * initiate the default behavior at (re)launch.
	 * <p>
	 * It supports:
	 * <p>
	 * http://occupancy.epfl.ch/content format, with content being the
	 * autocomplete requet.
	 * <p>
	 * TODO: pockecampus://
	 * 
	 * @param intent
	 *            the intent to handle
	 */
	@Override
	protected void handleIntent(Intent intent) {
		logV("Starting the app: handling an Intent");
		// Intent and/or action seems to be null in some cases... so we just
		// skip these cases and launch the default settings.
		if (intent != null && intent.getAction() != null) {
			if (intent.getAction().equalsIgnoreCase(
					"android.intent.action.MAIN")) {
				logV("starting MAIN and default mode");
				defaultMainStart();
			} else if (intent.getAction().equalsIgnoreCase(
					"android.intent.action.VIEW")) {
				logV("starting the app and handling simple VIEW intent");
				String errorIntentHandled = ""
						+ getString(R.string.freeroom_urisearch_error_URINotUnderstood)
						+ " "
						+ getString(R.string.freeroom_urisearch_error_URINotSupported);
				String intentScheme = intent.getScheme();
				Uri intentUri = intent.getData();
				if (intentScheme != null && intentUri != null) {
					String intentUriHost = intentUri.getHost();
					String intentUriPath = intentUri.getPath();
					if (intentUriHost != null && intentUriPath != null) {
						String intentUriPathQuery = FRStruct
								.removeFirstCharSafely(intentUriPath);
						// using standard epfl http page
						if (intentScheme.equalsIgnoreCase("http")
								&& intentUriHost
										.equalsIgnoreCase("occupancy.epfl.ch")) {
							logV("Found an EPFL http://occupancy.epfl.ch/room URI");
							logV("With room query: \"" + intentUriPathQuery + "\"");
							errorIntentHandled = searchByUriPrepareArguments(intentUriPathQuery);
						}

						// using freeroom links.
						else if (intentScheme.equalsIgnoreCase("pocketcampus")
								&& intentUriHost
										.equalsIgnoreCase("freeroom.plugin.pocketcampus.org")) {
							logV("Found a pocketcampus://freeroom.plugin.pocketcampus.org/data URI");
							logV("With room query: \"" + intentUriPathQuery + "\"");
							// TODO: do something.
							errorIntentHandled = "URI NOR supported right now!";
						} else {
							logE("Unknow URI: \"" + intentUri + "\"");
						}
					}
				}
				if (errorIntentHandled.length() != 0) {
					onErrorHandleIntent(errorIntentHandled);
				}
			} else {
				logE("ERROR: Found an unhandled action: \""
						+ intent.getAction() + "\"");
				logE("Starting the app in default mode anyway");
				defaultMainStart();
			}
		} else {
			logE("ERROR: Found a null Intent or Action !!!");
			logE("Starting the app in default mode anyway");
			defaultMainStart();
		}
	}

	/**
	 * In case of error while handling an Intent, display a message to the user,
	 * and then launch a default request (without taking the favorites into
	 * account).
	 * 
	 * @param errorMessage
	 *            the error message to display.
	 */
	private void onErrorHandleIntent(String errorMessage) {
		// TODO: display a popup
		Log.e("uri-search-error",
				getString(R.string.freeroom_urisearch_error_basis));
		Log.e("uri-search-error", errorMessage);
		Log.e("uri-search-error",
				getString(R.string.freeroom_urisearch_error_end));
		if (mController != null && mModel != null) {
			initDefaultRequest(false);
			refresh();
		}
	}

	/**
	 * Constructs the default request and refreshes it.
	 */
	private void defaultMainStart() {
		logV("Starting in default mode.");
		if (mController != null && mModel != null) {
			initDefaultRequest(true);
			refresh();
			logV("Successful start in default mode: wait for server response.");
		} else {
			logE("Controller or Model not defined: cannot start default mode.");
		}
	}

	/**
	 * Logs a given message using Log.V (VERBOSE MODE)
	 * 
	 * @param msg
	 *            message to log.
	 */
	private void logV(String msg) {
		Log.v(className, msg);
	}

	/**
	 * Logs a given message using Log.E (ERROR MODE)
	 * 
	 * @param msg
	 *            message to log.
	 */
	private void logE(String msg) {
		Log.e(className, msg);
	}

	/**
	 * Stores if a search by URI has been initiated recently, in order for
	 * auto-complete to automatically launch a new search if triggered, using
	 * <code>searchByUriMakeRequest</code>
	 */
	private boolean mSearchByUriTriggered = false;

	/**
	 * Initiates a search by URI with the given constraint as the argument for
	 * the auto-complete.
	 * 
	 * <p>
	 * If the requirement for autocomplete are not met, it will simply start a
	 * standard request (any free room now). If the autocomplete gave relevant
	 * results, it will search the availabilities of these rooms now. If
	 * autocomplete gave no results, it will also search for any free room now.
	 * 
	 * @param constraint
	 *            argument for the auto-complete to search for rooms.
	 * @return an empty String if successful, an error message if
	 */
	private String searchByUriPrepareArguments(String constraint) {
		// TODO: constraint in common!!
		if (constraint.length() < 2) {
			return getString(R.string.freeroom_urisearch_error_AutoComplete_error)
					+ " "
					+ getString(R.string.freeroom_urisearch_error_AutoComplete_precond);
		} else {
			mSearchByUriTriggered = true;
			// TODO: group
			AutoCompleteRequest req = new AutoCompleteRequest(constraint, 1);
			mController.autoCompleteBuilding(this, req);
			return "";
		}
	}

	/**
	 * Make a FRRequest with the FRRoom given in argument, for the rest of the
	 * day. If the argument is empty, it will display free room now.
	 * 
	 * @param collection
	 *            collection of FRRoom to make a new search on.
	 */
	private void searchByUriMakeRequest(Collection<FRRoom> collection) {
		mSearchByUriTriggered = false;

		boolean empty = collection.isEmpty();
		if (empty) {
			// if nothing matched the search, we notify the user.
			onErrorHandleIntent(getString(R.string.freeroom_urisearch_error_AutoComplete_error)
					+ " "
					+ getString(R.string.freeroom_urisearch_error_AutoComplete_noMatch));
		} else {
			// TODO: warn if there is more than 1 result ? Val. think no.

			// search for the rest of the day.
			FRPeriod period = FRTimes.getNextValidPeriodTillEndOfDay();
			FRRequestDetails request = null;
			List<String> uidList = new ArrayList<String>();
			SetArrayList<FRRoom> uidNonFav = new SetArrayList<FRRoom>();
			// TODO: find a simpler and more efficient way ?
			Iterator<FRRoom> iter = collection.iterator();
			while (iter.hasNext()) {
				FRRoom room = iter.next();
				uidList.add(room.getUid());
				uidNonFav.add(room);
			}
			// TODO: usergroup
			request = new FRRequestDetails(period, false, uidList, false,
					false, true, uidNonFav, 1);
			mModel.setFRRequestDetails(request, !empty);
			refresh();
		}
	}

	/* MAIN ACTIVITY - INITIALIZATION */

	@Override
	public void initializeView() {
		// retrieve display dimensions
		Rect displayRectangle = new Rect();
		Window window = this.getWindow();
		window.getDecorView().getWindowVisibleDisplayFrame(displayRectangle);
		activityWidth = displayRectangle.width();
		activityHeight = displayRectangle.height();

		mExpListAdapter = new ExpandableListViewAdapter<Occupancy>(
				getApplicationContext(), mModel.getOccupancyResults(),
				mController, this);
		mExpListView.setAdapter(mExpListAdapter);
		addActionToActionBar(refresh);
		addActionToActionBar(editFavorites);
		addActionToActionBar(search);
		initInfoDialog();
		initSearchDialog();
		initFavoritesDialog();
		initAddRoomDialog();
		initShareDialog();
		initWarningDialog();
	}

	/**
	 * Inits the dialog to diplay the information about a room.
	 */
	private void initInfoDialog() {
		// Instantiate an AlertDialog.Builder with its constructor
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle("room name");
		builder.setIcon(R.drawable.details_white_50);
		builder.setPositiveButton(
				getString(R.string.freeroom_dialog_info_share), null);
		builder.setNegativeButton(
				getString(R.string.freeroom_dialog_fav_close), null);

		// Get the AlertDialog from create()
		mInfoRoomDialog = builder.create();

		// redefine paramaters to dim screen when displayed
		WindowManager.LayoutParams lp = mInfoRoomDialog.getWindow()
				.getAttributes();
		lp.dimAmount = 0.60f;
		// these doesn't work
		lp.width = LayoutParams.FILL_PARENT;
		lp.height = LayoutParams.WRAP_CONTENT;
		mInfoRoomDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
		mInfoRoomDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_DIM_BEHIND);
		mInfoRoomDialog.getWindow().setAttributes(lp);

		mInfoRoomView = mLayoutInflater.inflate(
				R.layout.freeroom_layout_dialog_info, null);

		// these work perfectly
		mInfoRoomView.setMinimumWidth((int) (activityWidth * 0.9f));
		mInfoRoomView.setMinimumHeight((int) (activityHeight * 0.8f));

		mInfoRoomDialog.setView(mInfoRoomView);
		mInfoRoomDialog.setOnShowListener(new OnShowListener() {

			@Override
			public void onShow(DialogInterface dialog) {

			}
		});
	}

	/**
	 * Inits the dialog to diplay the favorites.
	 */
	private ExpandableListViewFavoriteAdapter mFavoritesAdapter;

	private void initFavoritesDialog() {
		// Instantiate an AlertDialog.Builder with its constructor
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(getString(R.string.freeroom_dialog_fav_title));
		builder.setIcon(R.drawable.star2x28);
		builder.setPositiveButton(getString(R.string.freeroom_dialog_fav_add),
				null);
		builder.setNegativeButton(
				getString(R.string.freeroom_dialog_fav_close), null);
		builder.setNeutralButton(getString(R.string.freeroom_dialog_fav_reset),
				null);

		// Get the AlertDialog from create()
		mFavoritesDialog = builder.create();

		// redefine paramaters to dim screen when displayed
		WindowManager.LayoutParams lp = mFavoritesDialog.getWindow()
				.getAttributes();
		lp.dimAmount = 0.60f;
		// these doesn't work
		lp.width = LayoutParams.FILL_PARENT;
		lp.height = LayoutParams.WRAP_CONTENT;
		mFavoritesDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
		mFavoritesDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_DIM_BEHIND);
		mFavoritesDialog.getWindow().setAttributes(lp);

		mFavoritesView = mLayoutInflater.inflate(
				R.layout.freeroom_layout_dialog_fav, null);

		// these work perfectly
		mFavoritesView.setMinimumWidth((int) (activityWidth * 0.9f));
		mFavoritesView.setMinimumHeight((int) (activityHeight * 0.8f));

		mFavoritesDialog.setView(mFavoritesView);
		mFavoritesDialog.setOnShowListener(new OnShowListener() {

			@Override
			public void onShow(DialogInterface dialog) {
				mFavoritesAdapter.notifyDataSetChanged();
			}
		});

		mFavoritesDialog.hide();
		mFavoritesDialog.show();
		mFavoritesDialog.dismiss();

		mFavoritesDialog
				.setOnDismissListener(new AlertDialog.OnDismissListener() {

					@Override
					public void onDismiss(DialogInterface dialog) {
						// sends a new request with the new favorites
						initDefaultRequest(true);
						refresh();
					}
				});

		Button tv = mFavoritesDialog.getButton(DialogInterface.BUTTON_POSITIVE);
		tv.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if (!mAddRoomDialog.isShowing()) {
					displayAddRoomDialog(AddRoomCaller.FAVORITES);
				}
			}
		});

		Button bt = mFavoritesDialog.getButton(DialogInterface.BUTTON_NEUTRAL);
		bt.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				mWarningDialog.show();
			}
		});

		ExpandableListView lv = (ExpandableListView) mFavoritesView
				.findViewById(R.id.freeroom_layout_dialog_fav_list);
		mFavoritesAdapter = new ExpandableListViewFavoriteAdapter(this, mModel
				.getFavorites().keySetOrdered(), mModel.getFavorites(), mModel);
		lv.setAdapter(mFavoritesAdapter);
		mFavoritesAdapter.notifyDataSetChanged();
	}

	private void displayAddRoomDialog(AddRoomCaller calling) {
		mAddRoomDialog.show();
		// TODO: reset the data ? the text input, the selected room ?
		lastCaller = calling;
	}

	private void dimissAddRoomDialog() {
		if (lastCaller.equals(AddRoomCaller.FAVORITES)) {
			Iterator<FRRoom> iter = selectedRooms.iterator();
			while (iter.hasNext()) {
				FRRoom mRoom = iter.next();
				// TODO: add all in batch!
				mModel.addFavorite(mRoom);
			}
			mFavoritesAdapter.notifyDataSetChanged();
			resetUserDefined();
		} else if (lastCaller.equals(AddRoomCaller.SEARCH)) {
			// we do nothing: reset will be done at search time
			mSummarySelectedRoomsTextViewSearchMenu
					.setText(getSummaryTextFromCollection(selectedRooms));
		}
	}

	private void initAddRoomDialog() {
		// Instantiate an AlertDialog.Builder with its constructor
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(getString(R.string.freeroom_dialog_add_room_title));
		builder.setIcon(R.drawable.ic_dialog_adding);

		// Get the AlertDialog from create()
		mAddRoomDialog = builder.create();

		// redefine paramaters to dim screen when displayed
		WindowManager.LayoutParams lp = mAddRoomDialog.getWindow()
				.getAttributes();
		lp.dimAmount = 0.60f;
		// these doesn't work
		lp.width = LayoutParams.FILL_PARENT;
		lp.height = LayoutParams.WRAP_CONTENT;
		mAddRoomDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
		mAddRoomDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_DIM_BEHIND);
		mAddRoomDialog.getWindow().setAttributes(lp);

		mAddRoomView = mLayoutInflater.inflate(
				R.layout.freeroom_layout_dialog_add_room, null);
		// these work perfectly
		mAddRoomView.setMinimumWidth((int) (activityWidth * 0.9f));
		// mAddRoomView.setMinimumHeight((int) (activityHeight * 0.8f));

		mAddRoomDialog.setView(mAddRoomView);
		mAddRoomDialog.setOnShowListener(new OnShowListener() {

			@Override
			public void onShow(DialogInterface dialog) {
				// searchButton.setEnabled(auditSubmit() == 0);
			}
		});

		Button bt_done = (Button) mAddRoomView
				.findViewById(R.id.freeroom_layout_dialog_add_room_done);
		bt_done.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				dismissSoftKeyBoard(v);
				mAddRoomDialog.dismiss();
				dimissAddRoomDialog();
			}
		});

		mSummarySelectedRoomsTextView = (TextView) mAddRoomView
				.findViewById(R.id.freeroom_layout_dialog_add_room_summary);

		UIConstructInputBar();
		LinearLayout ll = (LinearLayout) mAddRoomView
				.findViewById(R.id.freeroom_layout_dialog_add_layout_main);
		ll.addView(mAutoCompleteSuggestionInputBarElement);
		createSuggestionsList();

	}

	private void initShareDialog() {
		// Instantiate an AlertDialog.Builder with its constructor
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(getString(R.string.freeroom_dialog_share_title));
		builder.setPositiveButton(
				getString(R.string.freeroom_dialog_share_button_friends), null);
		builder.setNegativeButton(getString(R.string.freeroom_search_cancel),
				null);
		builder.setNeutralButton(
				getString(R.string.freeroom_dialog_share_button_server), null);
		builder.setIcon(R.drawable.share_white_50);

		// Get the AlertDialog from create()
		mShareDialog = builder.create();

		// redefine paramaters to dim screen when displayed
		WindowManager.LayoutParams lp = mShareDialog.getWindow()
				.getAttributes();
		lp.dimAmount = 0.60f;
		// these doesn't work
		lp.width = LayoutParams.FILL_PARENT;
		lp.height = LayoutParams.FILL_PARENT;
		mShareDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
		mShareDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_DIM_BEHIND);
		mShareDialog.getWindow().setAttributes(lp);

		mShareView = mLayoutInflater.inflate(
				R.layout.freeroom_layout_dialog_share, null);
		// these work perfectly
		mShareView.setMinimumWidth((int) (activityWidth * 0.95f));
		// mShareView.setMinimumHeight((int) (activityHeight * 0.8f));
		mShareDialog.setOnShowListener(new OnShowListener() {

			@Override
			public void onShow(DialogInterface dialog) {
				dismissSoftKeyBoard(mShareView);
			}
		});

		mShareDialog.setView(mShareView);

	}

	public void displayShareDialog(final FRPeriod mPeriod, final FRRoom mRoom) {
		mShareDialog.hide();
		mShareDialog.show();

		final TextView tv = (TextView) mShareView
				.findViewById(R.id.freeroom_layout_dialog_share_textBasic);
		tv.setText(wantToShare(mPeriod, mRoom, ""));

		final EditText ed = (EditText) mShareView
				.findViewById(R.id.freeroom_layout_dialog_share_text_edit);
		ed.setOnEditorActionListener(new OnEditorActionListener() {

			@Override
			public boolean onEditorAction(TextView arg0, int arg1, KeyEvent arg2) {
				tv.setText(wantToShare(mPeriod, mRoom, ed.getText().toString()));
				dismissSoftKeyBoard(arg0);
				return true;
			}
		});

		Button shareWithServer = mShareDialog
				.getButton(DialogInterface.BUTTON_NEUTRAL);
		shareWithServer.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				share(mPeriod, mRoom, false, ed.getText().toString());
				mShareDialog.dismiss();
			}
		});

		Button shareWithFriends = mShareDialog
				.getButton(DialogInterface.BUTTON_POSITIVE);
		shareWithFriends.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				share(mPeriod, mRoom, true, ed.getText().toString());
				mShareDialog.dismiss();
			}
		});

		Spinner spinner = (Spinner) mShareView
				.findViewById(R.id.freeroom_layout_dialog_share_spinner_course);
		// Create an ArrayAdapter using the string array and a default spinner
		// layout
		ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
				this, R.array.planets_array,
				android.R.layout.simple_spinner_item);
		// Specify the layout to use when the list of choices appears
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		// Apply the mFavoritesAdapter to the spinner
		spinner.setAdapter(adapter);

		spinner.setOnItemSelectedListener(new OnItemSelectedListener() {

			@Override
			public void onItemSelected(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {
				// TODO do something with that
				System.out.println("selected" + arg0.getItemAtPosition(arg2));
			}

			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
				// TODO find out how is this relevant
				System.out.println("nothing selected!");
			}

		});

		// it's automatically in center of screen!
		mShareDialog.show();
	}

	/**
	 * Dismiss the keyboard associated with the view.
	 * 
	 * @param v
	 */
	private void dismissSoftKeyBoard(View v) {
		InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
	}

	/**
	 * Inits the dialog to diplay the information about a room.
	 */
	private void initSearchDialog() {
		// Instantiate an AlertDialog.Builder with its constructor
		AlertDialog.Builder builder = new AlertDialog.Builder(this);

		// Various setter methods to set the searchDialog characteristics

		builder.setTitle(getString(R.string.freeroom_search_title));
		builder.setPositiveButton(getString(R.string.freeroom_search_search),
				null);
		builder.setNegativeButton(getString(R.string.freeroom_search_cancel),
				null);
		builder.setNeutralButton(getString(R.string.freeroom_search_reset),
				null);
		builder.setIcon(R.drawable.magnify2x06);

		// Get the AlertDialog from create()

		mSearchDialog = builder.create();

		// redefine paramaters to dim screen when displayed
		WindowManager.LayoutParams lp = mSearchDialog.getWindow()
				.getAttributes();
		lp.dimAmount = 0.60f;
		// these doesn't work
		lp.width = LayoutParams.FILL_PARENT;
		lp.height = LayoutParams.FILL_PARENT;
		mSearchDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
		mSearchDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_DIM_BEHIND);
		mSearchDialog.getWindow().setAttributes(lp);

		mSearchView = mLayoutInflater.inflate(
				R.layout.freeroom_layout_dialog_search, null);
		// these work perfectly
		mSearchView.setMinimumWidth((int) (activityWidth * 0.9f));
		mSearchView.setMinimumHeight((int) (activityHeight * 0.8f));

		mSearchDialog.setView(mSearchView);
		final String textTitlePrevious = getString(R.string.freeroom_search_previous_search);
		prevSearchTitle = (TextView) mSearchView
				.findViewById(R.id.freeroom_layout_dialog_search_prev_search_title);
		prevSearchTitle.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				searchDialogMissSpaceExtendChangeState(searchDialogExtendMoreTriggered);
				if (searchDialogHasHeightExtenstionProblem) {
					if (searchDialogExtendMoreTriggered) {
						prevSearchTitle
								.setText(textTitlePrevious
										+ ": "
										+ getString(R.string.freeroom_search_previous_hide));
					} else {
						prevSearchTitle
								.setText(textTitlePrevious
										+ ": "
										+ getString(R.string.freeroom_search_previous_show));
					}
				}
				searchDialogExtendMoreTriggered = !searchDialogExtendMoreTriggered;
			}
		});

		mSearchDialog.setOnShowListener(new OnShowListener() {

			@Override
			public void onShow(DialogInterface dialog) {
				searchButton.setEnabled(auditSubmit() == 0);
				if (mModel.getPreviousRequest().isEmpty()) {
					prevSearchTitle.setText("");
				} else if (searchDialogHasHeightExtenstionProblem) {
					prevSearchTitle
							.setText(textTitlePrevious
									+ ": "
									+ getString(R.string.freeroom_search_previous_show));
				} else {
					prevSearchTitle.setText(textTitlePrevious);
				}
			}
		});
		// this is necessary o/w buttons don't exists!
		mSearchDialog.hide();
		mSearchDialog.show();
		mSearchDialog.dismiss();
		resetButton = mSearchDialog.getButton(DialogInterface.BUTTON_NEUTRAL);
		searchButton = mSearchDialog.getButton(DialogInterface.BUTTON_POSITIVE);

		mSummarySelectedRoomsTextViewSearchMenu = (TextView) mSearchView
				.findViewById(R.id.freeroom_layout_dialog_search_text_summary);
		// the view will be removed or the text changed, no worry
		mSummarySelectedRoomsTextViewSearchMenu.setText("empty");

		// display the previous searches
		mSearchPreviousListView = (ListView) mSearchView
				.findViewById(R.id.freeroom_layout_dialog_search_prev_search_list);
		ArrayAdapter<FRRequestDetails> adapter = new ArrayAdapter<FRRequestDetails>(
				this, R.layout.sdk_list_entry, R.id.sdk_list_entry_text,
				mModel.getPreviousRequest());
		mSearchPreviousListView.setAdapter(adapter);
		mSearchPreviousListView
				.setOnItemClickListener(new OnItemClickListener() {

					@Override
					public void onItemClick(AdapterView<?> arg0, View arg1,
							int arg2, long arg3) {
						FRRequestDetails req = mModel.getPreviousRequest().get(
								arg2);
						if (req != null) {
							fillSearchDialog(req);
						}

						searchDialogExtendMoreTriggered = true;
						if (searchDialogHasHeightExtenstionProblem) {
							prevSearchTitle
									.setText(textTitlePrevious
											+ ": "
											+ getString(R.string.freeroom_search_previous_show));
						}
						searchDialogMissSpaceExtendChangeState(false);
					}
				});

		searchDialogUpperLinearLayout = (LinearLayout) mSearchDialog
				.findViewById(R.id.freeroom_layout_dialog_search_scroll_main);
		searchDialogMainLinearLayout = (LinearLayout) mSearchDialog
				.findViewById(R.id.freeroom_layout_dialog_search_main);

		initSearch();
	}

	/**
	 * Finds if the available height in the search popup is not enough to store
	 * the layout, in order the minimize it's size.
	 * <p>
	 * TODO: this method has an issue and never work on 1st time! The mock
	 * filling seems not to be working regarding to the mesurements.
	 * 
	 * @return true if no problem
	 */
	private boolean findIfHeightProblem() {
		// TODO: seems useless regarding the issue
		searchDialogUpperLinearLayout
				.setLayoutParams(new LinearLayout.LayoutParams(
						LinearLayout.LayoutParams.FILL_PARENT, 1700));
		searchDialogUpperLinearLayout
				.setLayoutParams(new LinearLayout.LayoutParams(
						LinearLayout.LayoutParams.FILL_PARENT,
						LinearLayout.LayoutParams.WRAP_CONTENT));
		FRRequestDetails request = validRequest(true);
		request.setAny(false);
		request.setFav(true);
		request.setUser(true);
		SetArrayList<FRRoom> set = new SetArrayList<FRRoom>(100);
		List<String> uidList = new ArrayList<String>(100);
		for (int i = 0; i < 100; i++) {
			set.add(new FRRoom("BC898989", i + "123"));
			uidList.add(i + "123");
		}
		request.setUidNonFav(set);
		request.setUidList(uidList);
		fillSearchDialog(request);
		mSearchDialog.show();
		// TODO: seems useless regarding the issue
		searchDialogUpperLinearLayout.refreshDrawableState();
		searchDialogUpperLinearLayout.getDrawableState();
		searchDialogMainLayoutHeightAvailable = searchDialogMainLinearLayout
				.getMeasuredHeight();
		boolean toreturn = (searchDialogUpperLinearLayout.getMeasuredHeight() > (searchDialogExtended * searchDialogMainLayoutHeightAvailable));
		fillSearchDialog();
		return toreturn;
	}

	/**
	 * Display the search dialog and checks the compatibility of the UI and make
	 * some change if necessary.
	 */
	private void displaySearchDialog() {
		if (findIfHeightProblem()) {
			searchDialogHasHeightExtenstionProblem = true;
		}
		fillSearchDialog();
		if (!mModel.getPreviousRequest().isEmpty()) {
			searchDialogMissSpaceExtendChangeState(false);
		} else {
			searchDialogUpperLinearLayout
					.setLayoutParams(new LinearLayout.LayoutParams(
							LinearLayout.LayoutParams.FILL_PARENT,
							LinearLayout.LayoutParams.WRAP_CONTENT));
		}
		mSearchDialog.show();
	}

	/**
	 * Modify the height of the upper layout of the search dialog in order to
	 * show/hide the previous requests.
	 * 
	 * @param lessExtend
	 */
	private void searchDialogMissSpaceExtendChangeState(boolean lessExtend) {
		if (searchDialogHasHeightExtenstionProblem) {
			int height = (int) (searchDialogNonExtended * searchDialogMainLayoutHeightAvailable);

			if (lessExtend) {
				height = (int) (searchDialogExtended * searchDialogMainLayoutHeightAvailable);
			}
			searchDialogUpperLinearLayout
					.setLayoutParams(new LinearLayout.LayoutParams(
							LinearLayout.LayoutParams.FILL_PARENT, height));
			searchDialogUpperLinearLayout.refreshDrawableState();
		}
	}

	private void initWarningDialog() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(getString(R.string.freeroom_dialog_warn_title));
		builder.setMessage(getString(R.string.freeroom_dialog_warn_text));
		builder.setIcon(R.drawable.warning_white_50);
		builder.setPositiveButton(
				getString(R.string.freeroom_dialog_warn_reset),
				new AlertDialog.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						mModel.resetFavorites();
						mFavoritesAdapter.notifyDataSetChanged();
					}
				});
		builder.setNegativeButton(
				getString(R.string.freeroom_dialog_warn_cancel), null);

		// Get the AlertDialog from create()
		mWarningDialog = builder.create();

		// redefine paramaters to dim screen when displayed
		WindowManager.LayoutParams lp = mWarningDialog.getWindow()
				.getAttributes();
		lp.dimAmount = 0.60f;
		// these doesn't work
		lp.width = LayoutParams.WRAP_CONTENT;
		lp.height = LayoutParams.WRAP_CONTENT;
		mWarningDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
		mWarningDialog.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_DIM_BEHIND);
		mWarningDialog.getWindow().setAttributes(lp);
	}

	public boolean onTouchEvent(MotionEvent event) {

		if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
			System.out
					.println("TOuch outside the dialog ******************** ");
			mSearchDialog.dismiss();
		}
		return false;
	}

	/**
	 * Overrides the legacy <code>onKeyDown</code> method in order to close the
	 * dialog if one was opened. TODO: test if really needed.
	 * 
	 * @param keyCode
	 * @param event
	 * @return
	 */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {

		// Override back button
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			boolean flag = false;
			if (mInfoRoomDialog.isShowing()) {
				mInfoRoomDialog.dismiss();
				flag = true;
			}
			if (mSearchDialog.isShowing()) {
				mSearchDialog.dismiss();
				flag = true;
			}
			if (mFavoritesDialog.isShowing()) {
				mFavoritesDialog.dismiss();
				flag = true;
			}
			selectedRooms.clear();
			if (flag) {
				resetUserDefined();
				return true;
			}
		}
		return super.onKeyDown(keyCode, event);
	}

	@Override
	public void anyError() {
		setTextSummary(getString(R.string.freeroom_home_error_sorry));
	}

	/**
	 * Sets the summary text box to the specified text.
	 * 
	 * @param text
	 *            the new summary to be displayed.
	 */
	private void setTextSummary(String text) {
		// always start by space!
		mTextView.setText(" " + text);
	}

	/**
	 * Constructs the default request and sets it in the model for future use.
	 * You may call <code>refresh</code> in order to actually send it to the
	 * server.
	 * 
	 * @param useFavorites
	 *            if the constructor of the request should consider the
	 *            favorites or not
	 */
	private void initDefaultRequest(boolean useFavorites) {
		mModel.setFRRequestDetails(validRequest(useFavorites), false);
	}

	/**
	 * Construct a valid and default request. If useFavorites is true, it will
	 * check all the favorites for the next valid period, otherwise or if there
	 * are not.
	 * 
	 * @param useFavorites
	 *            if it should consider the favorites or not
	 * @return a valid and default request, based or nor on the favorites.
	 */
	private FRRequestDetails validRequest(boolean useFavorites) {
		OrderMapListFew<String, List<FRRoom>, FRRoom> set = mModel
				.getFavorites();
		FRRequestDetails details = null;
		// if there are no favorites or we dont want to use them.
		if (set.isEmpty() || !useFavorites) {
			// NO FAV = check all free rooms
			// TODO change group accordingly, set to 1 by default and for
			// testing purpose

			details = new FRRequestDetails(FRTimes.getNextValidPeriod(), true,
					new ArrayList<String>(1), true, false, false,
					new SetArrayList<FRRoom>(), 1);
		} else {
			// FAV: check occupancy of ALL favs
			ArrayList<String> array = new ArrayList<String>(set.size());

			addAllFavoriteToCollection(array, AddCollectionCaller.SEARCH, true);

			// TODO change group accordingly, set to 1 by default and for
			// testing purpose

			details = new FRRequestDetails(FRTimes.getNextValidPeriod(), false,
					array, false, true, false, new SetArrayList<FRRoom>(), 1);
		}
		return details;
	}

	/**
	 * Asks the controller to send again the request which was already set in
	 * the model.
	 */
	private void refresh() {
		setTextSummary(getString(R.string.freeroom_home_please_wait));
		mController.sendFRRequest(this);
	}

	@Override
	public void occupancyResultsUpdated() {
		StringBuilder build = new StringBuilder(50);
		if (mModel.getOccupancyResults().isEmpty()) {
			build.append(getString(R.string.freeroom_home_error_no_results));
		} else {
			FRRequest request = mModel.getFRRequestDetails();

			if (request.isOnlyFreeRooms()) {
				build.append(getString(R.string.freeroom_home_info_free_rooms));
			} else {
				build.append(getString(R.string.freeroom_home_info_rooms));
			}
			FRPeriod period = mModel.getOverAllTreatedPeriod();
			// TODO: for tests only, please keep this line
//			build.append(generateFullTimeSummary(period));
			// TODO: for tests only, please remove these 4 lines.
			build.append("\n sent from client: ");
			build.append(generateFullTimeSummary(mModel.getFRRequestDetails()
					.getPeriod()));
			build.append("\n recieve from server: ");
			build.append(generateFullTimeSummary(period));
{'fraction_non_alphanumeric': 0.10100217270131613, 'fraction_numerical': 0.0029917300845192186, 'mean_word_length': 4.14725686515604, 'pattern_counts': {'":': 8, '<': 127, '<?xml version=': 0, '>': 125, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 14}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1122531', 'n_tokens_mistral': 30529, 'n_tokens_neox': 25928, 'n_words': 6318}