// bind_func() allows scope altering
Function.prototype.bind_func = function(obj) {
  var method = this;
  var temp_func = function() {
    return method.apply(obj, arguments);
  };
             
  return temp_func;
}

Array.prototype.sortIgnoreCase = function() {
  return this.sort(function (a, b) {
                     return ((a.toLowerCase() > b.toLowerCase()) ? 1 : ((a.toLowerCase() < b.toLowerCase()) ? -1 : 0));
                   });
}


// the dataFinder class allows user to filter a list of data using multiple pickers(dropdowns)
var DataFinder = function (pickerDiv, resultDiv, countDiv, formatObj) {
  this.name = 'DataFinder';
  this.loaded = false;
  this.pickers = [];
  this.picked = {};
  this.dataRows = [];
  this.pickerDiv = $(pickerDiv);
  this.resultDiv = $(resultDiv);
  this.countDiv = $(countDiv);
  this.formatObj = new formatObj();

  this.toString = function() {
    return this.name + '(' + this.pickerDiv.id + ', ' + this.resultDiv.id + ', ' + this.countDiv.id + ')';
  };

  this.init = function (data) {
    this.pickers = data[0];
    this.dataRows = data[1];
    this.loaded = true;
    this.finder = $('finder');
    this.finderBg = $('finderBg');
    this.open();
  };

  this.open = function () {
    this.populate_pickers();
    $('loading').style.display = "none";
  };

  this.close = function () {
    this.clearResults();
  };

  this.reset = function () {
    this.hideCount();
    this.clearResults();
    this.clearPicked();
    this.populate_pickers();
  };
  
  this.hideResults = function () {
    this.resultDiv.style.display = "none";
  };

  this.showResults = function () {
    this.resultDiv.style.display = "block";
  };

  this.clearResults = function () {
    this.resultDiv.empty();
  };

  this.showCount = function () {
    this.countDiv.getParent().style.display = "inline";
  };

  this.hideCount = function () {
    this.countDiv.getParent().getParent().style.display = "none";
  };

  this.print_product = function (prod_data) {
    $E('body').addClass("print_popup");
    var results = new Element('table', {'class': 'results_table'});
    var tbody = new Element('tbody');
    tbody.inject(results);
    var row = prod_data.parentNode.parentNode.parentNode;
    $extend(row, new Element()); // IE cloning bug fix
    row.clone().inject(tbody);
    results.inject($('printer'));
  };

  this.select_all = function () {
    $$('.print_this_one').each(function(item) {
      item.checked = true;
    });
  };

  this.clear_all = function () {
    $$('.print_this_one').each(function(item) {
      item.checked = false;
    });
  };

  this.print_list = function () {
    $E('body').addClass("print_popup");
    var results = new Element('table', {'class': 'results_table'});
    var tbody = new Element('tbody');
    tbody.inject(results);
    var dots = $$('.dotted_row')[0];
    $extend(dots, new Element()); // IE cloning bug fix
    $$('.print_this_one').each(function(item) {
      if (item.checked) {
        var row = item.parentNode.parentNode.parentNode;
        $extend(row, new Element()); // IE cloning bug fix
        row.clone().inject(tbody);
        dots.clone().inject(tbody);
      }
    });
    results.inject($('printer'));
  };

  this.format_product_print = function () {
  };

  this.close_printer = function () {
    $E('body').removeClass("print_popup");
    $('printer').getElement('table').remove();
  };

  this.hideMenus = function () {
    $$('.pick_menu').each(function(item) {
      item.style.display = "none";
    });
  };

  this.showMenu = function(eObj) {
    eObj.parentNode.lastChild.style.display = "block";
  };
  this.hideMenu = function(eObj) {
    eObj.parentNode.lastChild.style.display = "none";
  };

  this.clearPicked = function (pick) {
    if (pick) {
      this.picked[pick] = '';
    } else {
      this.picked = {};
    }
  };

  this.setPicked = function (pick, val) {
    this.picked[pick] = val;
  };

  this.pickEvent = function(eObj) {
    var pick = eObj.parentNode.parentNode.id;
    this.hideMenus();
    this.setPicked(pick, eObj.id);
    this.filter_list();
    return
  };

  this.clearEvent = function(eObj) {
    var pick = eObj.parentNode.parentNode.id;
    this.hideMenus();
    this.clearPicked(pick);
    var _picked = this.picked;
    var pickStr = false;
    this.pickers.each(function(pick) {
      if (_picked[pick]) {
        pickStr = true;
      }
    });
    if (!pickStr) {
      this.hideResults();
      this.populate_pickers();
    } else {
      this.filter_list();
    }
  };

  this.chooseEvent = function(eObj) {
    this.hideMenus();
    eObj.parentNode.lastChild.style.display = "block";
  };

  this.populate_pickers = function (dataList) {
    var data = dataList || this.dataRows;
    var _picked = this.picked;
    this.pickerDiv.empty();
    var valDict = {};
    var linkDict = {};
    this.pickers.each(function(pick) {
      valDict[pick] = [];
      linkDict[pick] = [];
    });


    var get_unique_opts = function(info, i) {
      this.pickers.each(function(pick) {
        var val = info[pick];
        var id = info['id']
        if (val && !valDict[pick].contains(val)) { 
            valDict[pick].push(val);
            linkDict[pick].push(['<!-- order by: ', info[pick+'_order'], ' -->', '<a id="', val, '" class="opt_link" onclick="javascript:finder.pickEvent(this);">', val, '</a>'].join(''));
        }
      });
    }
    var process_func = get_unique_opts.bind_func(this);
    data.each(process_func);

    // If list is filterd to 1 value due to other choices, set value as picked
    this.pickers.each(function(pick) {
      if (valDict[pick].length == 1) {
        _picked[pick] = valDict[pick][0];
      }
    });

    var makePickerHtml = function(pick) {
      var dd = ['<div id="',
                pick,
                '" class="pick_link"><a class="chooser',
                (_picked[pick]) ? ' picked' : '',
                '" id="',
                pick,
                '" onclick="javascript:finder.chooseEvent(this);">',
                (_picked[pick]) ? _picked[pick] : pick,
                '</a><div class="pick_menu" onmouseover="javascript:finder.showMenu(this);" onmouseout="javascript:finder.hideMenu(this);"><a class="clearer" onclick="javascript:finder.clearEvent(this);">[Clear Choice]</a>'
                ];
      var links = linkDict[pick];
      links.sortIgnoreCase();
      dd.extend(links);
      dd.push('</div></div>');
      return dd.join('');
    };

    var picker_func = makePickerHtml.bind_func(this);
    var pickHTML = [];
    this.pickers.each(function(pick) {
      pickHTML.push(picker_func(pick));
    });
    this.pickerDiv.innerHTML = pickHTML.join('');
  };
  
  this.populate_results = function (dataList) {
    var data = dataList || this.dataRows;
    this.resultDiv.empty();
    this.resultDiv.innerHTML = this.formatObj.get_results(data, this.picked);
    this.countDiv.innerHTML = (data.length);
  };

  this.filter_list = function () {
    this.hideResults();
    var _pickers = this.pickers;
    var _picked = this.picked;

    var newList = this.dataRows.filter(function(item, i) {
      var show = true;
      _pickers.each(function(k) {
        if (_picked[k]) {
          show = (show && item[k] == _picked[k]);
        }
      });
      return show
    });

    this.populate_pickers(newList);
    this.populate_results(newList);
    this.showCount();
  };
};
