/*
 * The filtermap is a map of key,val pairs. The object is checked for the key. If it exists then
 * the corresponding value is compared to the value specified in filtermap. If they are unequal
 * the match fails
 */
 
 /** Used to store the value of select box*/
var selectedModel = null;

var Filter = function(filterMap)
{
  this.filterMap = filterMap;
  var matchesAll = 'All';
  
  this.matches = function(object){
    for(key in filterMap){
      if(object[key] != undefined && filterMap[key] != matchesAll && object[key] != filterMap[key]){
        return false;
      }
    }
    return true;
  }
}

/*
 * Used to store a set of objects under a key(which is a property of that object)
 * keyPropName   : The property of the object that is used as key. Note that the object is stored only if the key exists
 */
var Set = function(keyPropName)
{
  this.keyPropName = keyPropName;
  this.values = {};

  this.add = function(object){
    if(!object[this.keyPropName]){
      return;
    }
    this.values[object[this.keyPropName]] = object;
  }

  this.remove = function(value){
    this.values[value] = false;
  }
}

/*
 * name     : Name of select box
 * propName   : Name that is searched for in object for display text
 * valueName : Name that is searched for in object for selected value
 * isRequired: If false a value All is added
 * allValueDisplay : The display text value for the 'all' option
 */
var SelectBox = function(name, propName, valueName, isRequired, allValueDisplay)
{
  this.name = name;
  this.propName = propName;
  this.valueName = valueName;
  this.isRequired = isRequired;
  if(allValueDisplay){
    this.allValueDisplay = allValueDisplay;
  }
  else{
    this.allValueDisplay = "All";
  }

  /*
   * Adds an option to select box
   */
  this.addOption = function(selectElement, option)
  {
    try{
      selectElement.add(option, null);
    }
    catch(ex){
      selectElement.add(option);
    }
  }
  
  /*
   * Returns the selected value for this select box
   */
  this.getVal = function(formElement)
  {
    return formElement[this.name].options[formElement[this.name].selectedIndex].value;
  }
  
  /*
   * Removes all elements. Adds an 'All' selection if required
   */
  this.clear = function(formElement)
  {
    formElement[this.name].innerHTML = "";
    if(!this.isRequired)
    {
      var allOption = document.createElement('option');
      allOption.value = 'All';
      allOption.text = this.allValueDisplay;
      this.addOption(formElement[this.name], allOption);
    }
  }
  
  /*
   * Populates the this.propName from Obsectset in this select box
   * also sorts the vehicles in order.
   */
  this.populate = function(objectSet, formElement)
  {
    this.clear(formElement);
    // Need to create a set of values(We don't want to populate a value more than once)
    var optionSet = new Set('text');
    if(this.name == 'VehicleType' || this.name == 'modelId'){
      for(var i = 0; i < objectSet.length - 1; i++){
        for(var j = i + 1; j < objectSet.length; j++){
          if(objectSet[i][this.propName] > objectSet[j][this.propName]){
            var tmp = objectSet[i];
            objectSet[i] = objectSet[j];
            objectSet[j] = tmp;
          }
        }
      }
    }
    for(object in objectSet){
      var option = document.createElement('option');
      option.value = objectSet[object][this.valueName];
      option.text = objectSet[object][this.propName];
      if(option.value && option.text){
        optionSet.add(option);
      }
    }
    for(option in optionSet.values)
    {
      this.addOption(formElement[this.name], optionSet.values[option]);
    }
  }
}

/*
 * FormName    Name of the form. 
 * selectList  List of selection filters
 * allModels  List of models
 * crossFiltering  boolean to disable/enable crossFiltering
 */
var ModelSearch = function(formName, selectList, allModels, crossFiltering)
{
  // The list of selection boxes that are to be populated; The dependency is assumed to be 0->1->2...
  this.selectList = selectList;
  this.invForm = document.forms[formName];
  this.allModels = allModels;
  this.currentSelection = [];
  this.crossFiltering = crossFiltering;
  
  /*
   * Initializes the object. Populates the select boxes
   */
  this.init = function()
  {
    this.currentSelection = this.allModels;
    this.refreshSelects(-1);
    this.selectionChanged(0);
  }
  
  /*
   * Index denotes selectBox in the selectList that has changed
   */ 
  this.selectionChanged = function(index)
  {  
    var s = YAHOO.util.Dom.get('inv-search-modelId');
    // To get the value from the select box
    if (s !== null) selectedModel = s.options[s.selectedIndex].text;
    // If cross filtering is disabled don't do any thing
    if(!this.crossFiltering)
    {
      return;
    }
    this.filterModels(index);
    this.refreshSelects(index);
  }
  
  /*
   * Selects vehicles based on the set of values set for selects <= index
   */
  this.filterModels = function(index)
  {
    var filterMap = {};
    for(var i = 0;i <= index; i++)
    {
      filterMap[this.selectList[i].valueName] = this.selectList[i].getVal(this.invForm);
    }
    
    var filter = new Filter(filterMap);
    this.currentSelection = [];
    var counter = 0;
    
    for(i in this.allModels)
    {
      if(filter.matches(this.allModels[i]))
      {
        this.currentSelection[counter] = this.allModels[i];
        counter++;
      }
    }
  }
  
  /*
   * Refreshes the models that are displayed depending upon the current selections
   */
  this.refreshSelects = function(index)
  {
    for(var i = index + 1; i< this.selectList.length; i++)
    {
      this.selectList[i].populate(this.currentSelection, this.invForm);
    }
    // To check the variable have a value
    if (index == 0 && selectedModel !== null)
    {
      for (var j = 0; j < this.currentSelection.length; j++)
      {
        // To check the selected model and current selection is same
        if (selectedModel == this.currentSelection[j].name)
        {
          // To get the value from the select box
          var modelSelector = YAHOO.util.Dom.get('inv-search-modelId');
          // To select the value in the select box
          modelSelector.options[j].selected = true;
          return;
        }
      }
    }
  }
}
