// Goal is browser support for IE6+, FF2+, Safari and Opera
// Can assume jQuery support

// Extend Array object to be more useful                                                                                            
Array.prototype.contains = function (element) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] == element) {return true;}
  }
  return false;
};
// Array Remove - By John Resig (MIT Licensed)                                                                                      
Array.prototype.remove = function(from, to) {
  var rest = this.slice((to || from) + 1 || this.length);
  this.length = from < 0 ? this.length + from : from;
  return this.push.apply(this, rest);
};
Array.prototype.removeItem = function (item) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] == item) {
      this.remove(i);
      return true;
    }
  }
  return false;
};


// Common utility actions, in a nice namespace. 
Riven = {

  // Format a floating point value as a price with dollar sign, etc.
  toPrice: function(price) {
    price = ''+price;
    var sign = '';
    if (price.substring(0,1) == '-') { sign = '-'; price = price.replace('-', ''); }
    var bits = price.split(/\./);
    var dollars = bits[0];
    if (dollars.length > 3) {
      dollars = dollars.replace(/([0-9]*)([0-9]{3})$/, '$1,$2');
    }
    var cents = '';
    if (bits[1]) { cents = ''+bits[1]; }
    while (cents.length < 2) {
      cents = cents + '0';
    }
    if (cents.length > 2) {
      cents = cents.substring(0,2);
    }
    return sign + '$' + dollars + '.' + cents;
  },

  // Sets a cookie's value, defaults to 1 year duration, root path
  setCookie: function(name, value, expiresHours, path) {
    if (!expiresHours) { expiresHours = 24*365; }
    if (!path) { path = '/'; }

    var today = new Date();
    var expiresDate = new Date( today.getTime() + (expiresHours * 60 * 60 * 1000) );

    // Actually set the cookie
    document.cookie = name + "=" +escape(value) +
      ";expires=" + expiresDate.toGMTString() +
      ";path=" + path;
  },

  // Gets a cookie's value
  getCookie: function(name) {
    var cookies = document.cookie.split( ';' );
    for ( i = 0; i < cookies.length; i++ ) {
      var parts = cookies[i].split('=');
      if (parts[0].trim() == name) {
        return (parts.length > 1) ? unescape(parts[1]) : '';
      }
    }
    return false;
  },

  // Post a hash of params to a given url, then call the given callback (with 'this' optionally set to
  // the passed context) on success or failure.  Callback is required, and must be a function that
  // accepts two parameters, a success flag (of the ajax call, not necessarily the page result) and
  // a hash of result data if any from the called page (passed via JSON).
  //
  // Sample usage:
  //
  // function onResults(success, data) {
  //   if (success) {
  //     alert(data.message);
  //   } else {
  //     alert('Failed!');
  // }
  //
  // function saveValue(val) {
  //   url = '/site/module/page';
  //   params = {
  //     value: val
  //   };
  //   Riven.postAJAX(url, params, onResults);
  // }
  postAJAX: function(url,params,callback,context) {
    params = params || {};
    $.ajax({
      type: 'POST',
      url: url,
      data: params,
      cache: false,
      dataType: 'json',
      success: function(json) {
          callback.call(context||this, true, json);
      },
      error: function(xhr,status) {
          callback.call(context||this, false, null);
      }
    });
  },

  // Filters a select input element's states based on a select with
  // national markets listed - used in CRM for market editing.
  // Pass in id's for national and state select elements as params.
  filterStates: function(nationID, stateID) {
    var nations = $('#'+nationID);
    var states = $('#'+stateID);
    var cache = $('#'+stateID+'-cache');
    
    // Sanity check
    if (!nations || !states) {
      return;
    }

    var curNation = nations.val();
    if (!this.curNation || curNation != this.curNation) {
      // Save our current val, and clear out the states select
      this.curNation = curNation;
      states.empty();

      if (curNation) {
        // Clone all options that have their national market id set to our current selection into the states control
        var selID = cache.val().match(/[^\-]+$/);
        cache.find("option[national_market_id='"+curNation+"']").clone().appendTo(states);
        states.find("option").each(function() {
            // Set option vals to correct value (strip national id)
            $(this).attr('value',$(this).attr('value').match(/[^\-]+$/));
        });
        states.show();
        states.val(selID);
        $('#'+stateID+'-none').hide();
      } else {
        // No selected nation, so reset value and hide it
        states.hide();
        $('#'+stateID+'-none').show();
      }
    }
    
  },

  filterCities: function(mode) {
    // If mode is not set, do both modes
    if (mode == null) {
      Riven.filterCities('quicksearch');
      Riven.filterCities('body');
      return;
    }

    // Get our nodes
    var states = $('#'+mode+'-state');
    if (!states || states.length == 0) { return; }
    var cities = $('#'+mode+'-city');
    var cache = $('#'+mode+'-city-cache');
    var curCity = cities.val();

    // Ensure the cache is populated
    if (cache.find('option').length <= 0) {
      cities.find('option').appendTo(cache);
    }

    // Populate the main select with the appropriate items
    var curState = states.val();
    if (!this.curState || curState != this.curState[mode]) {
      // Save our current val, and clear out the cities select
      if (!this.curState) { this.curState = []; }
      this.curState[mode] = curState;
      cities.empty();

      if (curState.length > 0) {
          // Clone first option ("any") and all options that have the state attribute set to our state abbreviation
          cache.find("option:first, option[state='"+curState+"']").clone().appendTo(cities);
          if (curCity && curCity != '') {cities.val(curCity);}
          $('#'+mode+'-city-row').show();
      } else {
          // No selected state, so reset city value and hide it
          $('#'+mode+'-city-row').hide();
      }
    }
  },

  // New mouseover code for our new-style graphical buttons
  hoverButton: function(node, over) {
    // Add/remove our pseudo-hover class for IE6 (hate hate)
    node.toggleClass('iehover', over);
    // If we don't have a src attr, find our child who does
    if (!node.attr('src')) { node = node.find('*[src]'); }
    // Update our src attr to point to appropriate image
    var newSrc = node.attr('src');
    if (over) {
      // Add '-over' to image url
      newSrc = newSrc.replace(/(-over)?\./,'-over.');
    } else {
      // Remove '-over'
      newSrc = newSrc.replace(/-over\./,'.');
    }
    node.attr('src',newSrc);
  },
  
  amenityToggle: function(node) {
    // Find our nodes
    var root = node.parents('.amenity-select');
    var data = root.find('.data');
    var id = node.attr('amenity_id');

    // Get val array, update as appropriate
    var val = data.val();
    if (!val) { val = []; }
    if (val.contains(id)) {
      val.removeItem(id);
    } else {
      val.push(id);
    }
    
    // Set new val array back
    data.val(val);
    
    Riven.amenityUpdate(root);
  },
  
  amenityUpdate: function(root) {
    if (!root) { root = $('.amenity-select'); }
    var data = root.find('.data');
    var val = data.val();
    if (!val) { val = []; }

    root.find('.amenity').each(function() {
      var amenity = $(this);
      var sel = val.contains(amenity.attr('amenity_id'));
      amenity.toggleClass('selected', sel);
    });
  },

  // Called once on page load
  onNewContent: function(node) {
    // If we don't have a specified node, look for all body contents
    if (!node) {
      node = $('body');
    }
    
    // Update visibility of elements based on javascript availability
    $('.js-hide').hide().removeClass('js-hide');
    $('.js-show').show().removeClass('js-show');
    
    // Enable lightbox on items that request it
    $('a[rel*=lightbox]').lightBox();
    
    // New-style buttons, hover to do mouseover look
    $('.button').hover(
      function() { Riven.hoverButton($(this),true) },
      function() { Riven.hoverButton($(this),false) }
    );
  }

};

function AddToMylist(returnPage) {
	var str = '';
	
	for (var i=0;i< document.results.elements.length;i++) {
    if (document.results.elements[i].name == 'listing_ids[]') {
    	if (document.results.elements[i].checked == true) {
	    	if (str != '') { str = str + ','; }
	      str = str + document.results.elements[i].value;
	    }
  	}
  }
  
  var url = '/site/mylist/add_listings?listing_ids=' + str;
  if (returnPage) { url += '&clause=' + returnPage; }
  top.location.href = url;
};

function resetQuickSearch(){
	var f = document.QuickSearch;
	for (var i=0;i<f.elements.length; i++ ){
		if (f.elements[i].type == 'select-one'){
			f.elements[i].selectedIndex=0;
		}
	}
};

function changeImages(id, src) { 
	  var el = Riven.get(id);
	  if (el) { el.src = src; }
};


// jQuery extensions
(function($) {
  // We're adding new methods to the jQuery result set object
  $.fn.extend({
    
    setMask: function(status) {
      // Sanity check
      var node = this;
      if (node.length <= 0) {
        return;
      }
      // Remove loading mask, if any
      node.find('.status-mask').remove();
      if (status) {
        // Create a mask object and overlay the node with it
        mask = '<div class="status-mask"><div class="status-mask-text">' + status + '</div></div>';
        node.prepend(mask);
        
        // Resize the mask to fit the node, and then show it
        maskNode = node.find('.status-mask');
        maskStatusNode = maskNode.find('.status-mask-text');
        w = node.width();
        h = node.height();
        maskNode.css({
          'width': w,
          'height': h,
          'opacity': 0.85
        });
        maskStatusNode.css({
          'margin-top': (h/2-10) | 0   // the "| 0" truncates the float result back to an int - all css sizes are in px
        });
      }
    },
    
    // Loads an html fragment into the current node
    loadUrl: function(loadingText, url, params, callback, context) {
      // Sanity check
      var node = this;
      if (node.length <= 0) {
        return;
      }
      // Note our loading status, if we have one.
      if (loadingText) {node.setMask(loadingText);}

      // Do the ajax call
      $.ajax({
        type: 'POST',  // Use post, since we may be sending arbitrarily large data chunks, and servers will barf on too-long urls
        url: url,
        data: params,
        cache: false,
        dataType: 'text',
        success: function(text) {
          node.html(text);
          Riven.onNewContent(node);
          if (callback) {
            callback.call(context||this, true);
          }
        },
        error: function(xhr,status) {
          alert('Unable to load '+url+'\n\n'+status);
          node.setMask(false);
          if (callback) {
            callback.call(context||this, false);
          }
        }
      });
    },

    // Common case handler - sets a hover behavior that sets/removes a given css class on hover for all selected items
    hoverClass: function(className) {
      return this.hover(
        function() {
          $(this).addClass(className);
        },
        function() {
          $(this).removeClass(className);
        }
      );
    }

  });



})(jQuery);


// Sets up any global page js stuff needed after page load
$(function() {
  // Setup styles, lightboxes, etc.
  Riven.onNewContent();
            
  // Layout specific items
  Riven.filterCities();
});

