/**
 * items must be in the format id : { id, param1, ... , paramn }
 */

function FilterControl(box_find_exp, cb_find_exp, items) {
  
  /******************************************
   * Function definitions
  ******************************************/
  
  this.doAnim = doAnimFunc;
  this.setType = setTypeFunc;
  this.onFilterStart = onFilterStartFunc;
  this.onFilterStop = onFilterStopFunc;
  this.animate = animateFunc;
  this.addRangeSliderControl = addRangeSliderControlFunc;
  this.setControl = setControlFunc;

  /******************************************
   * Class Variables
  ******************************************/
  
  // Find the item boxes
  this.box_find_exp = box_find_exp;
  
  // Find the checkboxes
  this.cb_find_exp = cb_find_exp;
  
  // The list of items (in JSON)
  this.items = new Array();
  for (var i in items) {
    var item = items[i];
    item.status = 'show';
    this.items[item.id] = item;
  }
  
  // Controls
  this.controls = new Array();
  
  // Selected checkboxes
  this.selected_types = new Array();
  
  // Is the user currently in the process of filtering (dragging sliders, etc.)
  this.filtering = false;
  
  // Should we use animation effects (turn off for slow computers)
  this.enable_anim = true;
    
  /******************************************
   * Functions
  ******************************************/
  
  function addRangeSliderControlFunc(id, values) {
    this.controls[id] = new Object({ id:id, type:'slider', value:values });
    this.doAnim(false);
  }
  
  function setControlFunc(id, value, animate) {
    var animate = (animate == null) ? this.enable_anim : animate;
  
    if (this.controls[id] == 'undefined') return;
    var control = this.controls[id];
    control.value = value;
    this.controls[id] = control;
    
    this.doAnim(animate);
  }
  
  /**
   * Checks the category checkboxes
   */
  function setTypeFunc(refresh) {
    var refresh = (refresh == null) ? true : refresh;
    var selected_types = this.selected_types;
    $(this.cb_find_exp).each( function() {
      selected_types[$(this).attr('value')] = $(this).attr('checked');
    });
    
    if (refresh) this.doAnim();
  }
  
  /**
   * Called when filtering begins
   */
  function onFilterStartFunc() {
    this.filtering =  true;
  }
  
  /**
   * Called when filtering ends
   */
  function onFilterStopFunc() {
    this.filtering = false;
    this.doAnim();
  }
  
  /**
   * Enables / disables animations
   */
  function animateFunc(anim) {
    this.enable_anim = anim;
  }
  
  /**
   * Animates the boxes.
   *
   * Causes the invalid ones to fade out
   * and then disappear. Makes valid ones
   * appear.
   */
  function doAnimFunc(animate) {

    // Should we use animations or not
    var animate = (animate == null) ? this.enable_anim : animate;

    // To get around scope issues
    var controls = this.controls;
    var items = this.items;
    var selected_types = this.selected_types;
    var filtering = this.filtering;
    
    // Decide who lives and who....DIES!!
    $(this.box_find_exp).each( function() {
      id = $(this).attr('id');
      
      var within_range = true;
      
      // Determine if item lies outside search parameters
      
      // TEST CHECK BOX CATEGORIES
      if (selected_types[items[id].category_id] == false ) {
        within_range = false;
      }
            
      // TEST SLIDERS
      if (within_range) {
        for (var i in controls) {
          var control = controls[i];
          var item_param_val = items[id][control.id];
          if (control.type == 'slider') {
            if (control.value.length == 1) { // single handle slider
              if (item_param_val < control.value[0]) {
                within_range = false;
                break;
              }
            } else { // double handle slider (range slider)
              if (parseFloat(item_param_val) < parseFloat(control.value[0])
                  || parseFloat(item_param_val) > parseFloat(control.value[1])) {
                within_range = false;
                break;
              }
            } 
          } 
        }
      }

      // SHOW / HIDE BOXES DEPENDING ON OUTCOME OF TESTS
      if ( (!within_range)) { // Item is OUTSIDE search parameters
          
        if (items[id].status == 'show') {
          if (filtering) {
            (animate) ? $(this).stop().fadeTo('fast', '0.3') : $(this).stop().fadeTo(0, '0.3');
          } else {
            (animate) ? $(this).stop().fadeOut('slow') : $(this).stop().fadeOut(0);  
            items[id].status = 'hide';
          }
        }
        
      } else { // Item is WITHIN search parameters
      
        if (items[id].status == 'show') {
          (animate) ? $(this).stop().fadeTo('fast', '1.0') : $(this).stop().fadeTo(0, '1.0');
        } else if (items[id].status == 'hide') {
          if (!filtering) {
            $(this).css({'opacity':'1.0'});
            (animate) ? $(this).stop().fadeIn('slow') : $(this).stop().fadeIn(0);            
          } else {
            (animate) ? $(this).stop().fadeIn('slow') : $(this).stop().fadeIn(0);
          }
          items[id].status = 'show';
        }
        
      }
      
    });
  
  }
  
}