var resultParentElement = "results";

// CSS class constants
var resultClass = "result_content";
var resultHeaderClass = "result_header";
var resultClassHighlight = "result_content_highlight";
var resultHeaderClassHighlight = "result_header_highlight";
var disabledButtonClass = "disabled_submit";

var departureCityElement = "outbound_depart_city_name";
var arrivalCityElement = "outbound_arrive_city_name";
var startDateElement = "outbound_depart_date";
var endDateElement = "inbound_depart_date";

var displayedResultsElement = "num_displayed_results";
var totalResultsElement = "num_total_results";
var lowPriceElement = "results_low_price";
var highPriceElement = "results_high_price";

var formOriginElement = "search_origin";
var formDestElement = "search_destination";
var formDepartDateElement = "search_depart_date";
var formReturnDateElement = "search_return_date";

var searchInfoElement = "results_info";
var searchCitiesElement = "search_param_cities";
var searchDatesElement = "search_param_dates";
var searchPriceElement = "price_info";

var filterElement = "filter_panel";

// Overconstraint
var overconstraintDisplayElement = "overconstraint_display";
var k_OVERCONSTRAINT_SEARCH = 'search';
var k_OVERCONSTRAINT_FILTER = 'filter';

var resultsTable = "search_results_table";
var resultsHeaderElement = "results_header";
var resultsTableHeaderClassSelector = ".search_results_header_cell";

function airlineIconURL(code) {
  return "http://expedia.com/pubspec/images/airlines/sm" +
    code.toUpperCase() + ".gif";
}

function airlineIconImg(code) {
  return new Element('img', {src: airlineIconURL(code)});
}

function hideInterstitial()
{
	$('result_spinner').style.display = "none";	
}

function showInterstitial(origin_tla, dest_tla, depart_date, return_date, num_travelers)
{
  if( navigator.userAgent.indexOf("MSIE") != -1 )
    $('result_spinner').show();
  else
    new Effect.Appear('result_spinner', {duration: .5});
  
  $('interstitial_message_server_origin').update(friendlyCityName(origin_tla) + (friendlyCityName(origin_tla) == origin_tla.toUpperCase() ? "" : " (" + origin_tla.toUpperCase() +")" ));
  $('interstitial_message_server_dest').update(friendlyCityName(dest_tla) + (friendlyCityName(dest_tla) == dest_tla.toUpperCase() ? "" : " (" + dest_tla.toUpperCase() +")" ));
  $('interstitial_message_server_travelers').update(" for " + num_travelers + " traveler" +  (num_travelers == 1 ? "" : "s"));
}

// TODO: see if there's anything here that belongs in TripDisplayList
function enableResultsDisplay(unfiltered) {
	// hide the spinner
	hideInterstitial();
	
	// populate the search params display<span class="param_date">
	origin = $(formOriginElement).value;
	dest = $(formDestElement).value;
  if ( origin.match(/\(\w\w\w\)/) ) {  origin = origin.match(/\(\w\w\w\)/)[0].match(/\w\w\w/)[0]; }
  if ( dest.match(/\(\w\w\w\)/) ) {  dest = dest.match(/\(\w\w\w\)/)[0].match(/\w\w\w/)[0]; }
  $(departureCityElement).update(friendlyCityName(origin) + " <span class='param_date' style='font-variant:small-caps;'>(" + origin.toLowerCase() + ")</span>" );
  $(arrivalCityElement).update(friendlyCityName(dest) + " <span class='param_date' style='font-variant:small-caps;'>(" + dest.toLowerCase() + ")</span>" );
	
	var departDate = new Date($(formDepartDateElement).value);
	$(startDateElement).update(formatAbbrevDate(departDate, false, true));
	
	var returnDate = new Date($(formReturnDateElement).value);
	$(endDateElement).update(formatAbbrevDate(returnDate, true, true));
	
	// populate the search info display
	$(displayedResultsElement).update(unfiltered.length);
	$(totalResultsElement).update(unfiltered.length);
	
	var prices = unfiltered.pluck('price');
	var maxPrice = prices.max();
	var minPrice = prices.min();

//	$(lowPriceElement).update(formatPrice(minPrice));
//	$(highPriceElement).update(formatPrice(maxPrice));
	
	// Show the search information
	$(searchCitiesElement).style.visibility = "visible";
	$(searchDatesElement).style.visibility = "visible";
	$(searchInfoElement).style.visibility = "visible";
//	$(searchPriceElement).style.visibility = "visible";

	// Show the filters
	$(filterElement).style.visibility = "visible";
	
	// Show the results header table
//	$(resultsTableHeaderElement).style.visibility = "visible";
	$(resultsTable).style.visibility = "visible";
	
}

// hide the UI elements when a new search is launched
function disableResultsDisplay()
{
	$('interstitial_message_server').style.display = "inline";
	$('interstitial_message_results').style.display = "none";
  
//  $('sidebar_history_buttons').style.visibility = "hidden";
	$(searchCitiesElement).style.visibility = "hidden";
	$(searchCitiesElement).style.visibility = "hidden";
	$(searchDatesElement).style.visibility = "hidden";
	$(searchInfoElement).style.visibility = "hidden";
//	$(searchPriceElement).style.visibility = "hidden";
	$(filterElement).style.visibility = "hidden";
	
	hideOverconstraintDisplay();
	
	// Hide the results table header
	$$('.sort_arrow').each(function(element) {
	  element.style.visibility = "hidden";
	});
	
	// Hide any highlighted results
	$$('.highlighted .buttons').each(function(element) {
	  element.style.visibility = "hidden";
	});
	
	$(resultsTable).style.visibility = "hidden";
}

function showServerErrorMessage(message) {
  var elt = $('server_error_message');
  removeAllChildren(elt);
  elt.insert(message);
  elt.show();
}

function hideServerErrorMessage(message) {
  $('server_error_message').hide();
}

// These variables are to be used only by the withSpinner function.
// TODO: refactor all the spinner code into its own class (or two).
var spinnerMessages = []

// This function has to defer execution in order for the spinner to show up, so it is executed asynchronously. The last argument is an optional callback for when the call to fn completes.
function withSpinner(fn, message, callback) {
  message = message || "";
  
  // Keep a queue of messages in case withSpinner gets called while the spinner is already in place. If it is, our new message has to wait for its turn.
  spinnerMessages.push(message);
  
  var spinner = $('result_spinner');
  var messageElt =  $('interstitial_message');

  // We only need to show & update the spinner if a spinner message is not already being displayed.
  if(spinnerMessages.length == 1) {  
    messageElt.update(message);
    spinner.addClassName('overlay_result_spinner');
    spinner.show();
  }
	
	// Perform computation and then update or hide the display as needed. If the message queue is empty, we hide the spinner. If there are more messages waiting, we show them.
  (function () {
    var result = fn();
    
    spinnerMessages.shift();
    if(spinnerMessages.length > 0) {
      messageElt.update(spinnerMessages.first());
    } else {
      spinner.hide();
      messageElt.update('');
      spinner.removeClassName('overlay_result_spinner');
    }
    if(callback) callback(result);
  }).defer();
}

function updateResultCount(n) {
  $(displayedResultsElement).update(n);
}

/* DEPRECATED
function showUndoButtonIf(bool) {
  hideIf($('sidebar_undo_button'), !bool);
}

function showRedoButtonIf(bool) {
  hideIf($('sidebar_redo_button'), !bool);
}
*/

function hideIf(elt, bool) {
  if(bool) {
    elt.style.visibility = "hidden";
  } else {
    elt.style.visibility = "visible";
  }
}

function showOverconstraintDisplay() {
	$(overconstraintDisplayElement).style.display = "inline";
}

function hideOverconstraintDisplay() {
	$(overconstraintDisplayElement).style.display = "none";
}
