/**
 * metrics Data Set Selector
 * By Joe Turgeon [http://arithmetric.com]
 * 2/17/2010
 */

var metricsSetSelector = function () {
  var selector, active = false, wordsApplied = [], tagApplied = false, suggestions = [], sindex = 0, responder, responderObj;

  function activate(func, obj) {
    responder = func;
    responderObj = obj || window;
    wordsApplied = [];
    tagApplied = false;
    suggestions = [];
    sindex = 0;
    show();
  }

  function show() {
    if (!selector || !selector.length) {
      selector = $('<div id="selector" class="window"><div id="selector-wrapper"><div class="description">Select a data set to continue or <a href="#" onclick="metricsSetSelector.hide();return false;">cancel</a> this action.</div><div id="selector-search"><label>Search data sets:</label> <input id="selector-input" /></div> <div id="selector-tags"><label>Filter by tag:</label></div> <div id="selector-suggestions-wrapper"><label>Results:</label> <div id="selector-suggestions" /></div> <div style="clear:both;" /></div></div>');
      $('body').append(selector);
      var tags = $('#selector-tags', selector);
      for (var tagname in MetricsSetSelectorTags) {
        if (MetricsSetSelectorTags.hasOwnProperty(tagname)) {
          $('<div>' + MetricsSetSelectorTags[tagname] + '</div>')
            .data('tag', tagname)
            .click(function () {metricsSetSelector.tag($(this).data('tag'));})
            .appendTo(tags);
        }
      }
      $('#selector-suggestions').css({'max-height': $('#selector-tags').height() - 15, overflow: 'auto'});
      $('#selector-input').focus(function () {$(this).blur();});
    }
    else {
      $('#selector-input').val('');
      $('#selector-tags > div').removeClass('selected');
      $('#selector-suggestions').empty();
      selector.show();
    }
    active = true;
    update();
  }

  function hide() {
    selector.hide();
    active = false;
  }

  function hasFocus() {
    return active;
  }

  function input(keycode) {
    var handled = false;
    var entry = $('#selector-input').val();

    switch (keycode) {
      case 38: // up arrow
        if (sindex > 1) {
          sindex--;
        }
        else {
          sindex = suggestions.length;
        }
        handled = true;
        break;
      case 40: // down arrow
        if (sindex == suggestions.length) {
          sindex = 1;
        }
        else {
          sindex++;
        }
        handled = true;
        break;
      case 8: // backspace
        entry = entry.substr(0, entry.length - 1);
        handled = true;
        break;
      case 13: // enter
        if (sindex && suggestions[sindex - 1] && suggestions[sindex - 1].name) {
          responder.call(responderObj, suggestions[sindex - 1].name);
          hide();
        }
        else if (metricsData.validDataSet(entry)) {
          responder.call(responderObj, entry);
          hide();
        }
        handled = true;
        break;
      case 27: // escape
        hide();
        handled = true;
        break;
      default: // alphanumeric and space
        if (keycode == 32 || (keycode >= 48 && keycode <= 57) || (keycode >= 65 && keycode <= 122)) {
          var chr = String.fromCharCode(keycode);
          entry += chr;
        }
        handled = true;
        break;
    }
    $('#selector-input').val(entry);
    if (entry.length) {
      suggest(entry);
    }
    else {
      update();
    }
    return handled;
  }

  function select(name) {
    if (responder) {
      responder.call(responderObj, name);
    }
    $('#selector-input').val('');
    hide();
  }

  function suggest(entry) {
    var entries = String(entry).split(' ');
    var num = entries.length;
    var words = [];
    for (var i = 0; i < num; i++) {
      if (String(entries[i]).length && words.indexOf(entries[i]) == -1) {
        words.push(entries[i]);
      }
    }
    wordsApplied = words;
    update();
  }

  function update() {
    suggestions = metricsData.findDataSets({words: wordsApplied, tag: tagApplied});
    var sshtml = '';
    var num = suggestions.length;
    var itemClass;
    for (var i = 0; i < num; i++) {
      itemClass = (i % 2) ? 'odd' : 'even';
      if (sindex && (sindex - 1) == i) {
        itemClass += ' focus';
      }
      var stitle = String(suggestions[i].title);
      if (!stitle.length) {
        stitle = '&nbsp;';
      }
//<div class="item-name">' + suggestions[i].name + '</div>
      sshtml += '<div class="item ' + itemClass + '" onclick="metricsSetSelector.select(\'' + suggestions[i].name + '\');return false;");"><div class="item-title">' + stitle + '</div></div>';
    }
    if (!num) {
      sshtml += '<div>No data sets match the selected criteria.</div>';
    }
    $('#selector-suggestions').html(sshtml);
    var ss = $('#selector-suggestions').get(0);
    var si = $('div.item.focus', '#selector-suggestions');
    if (si.length) {
      var sitop = si.get(0).offsetTop;
      if (sitop < ss.scrollTop || sitop > (ss.scrollTop + ss.clientHeight)) {
        $('#selector-suggestions').scrollTop((sitop - ss.clientHeight / 2) ? sitop - ss.clientHeight / 2 : 0);
      }
    }
  }

  function tag(tagname) {
    var tags = $('#selector-tags > div');
    var selected = tags.filter(':contains(' + MetricsSetSelectorTags[tagname] + ')');
    tags.not(selected).removeClass('selected');
    selected.toggleClass('selected');
    tagApplied = (tagApplied == tagname) ? false : tagname;
    update();
  }

  return {
    activate: activate,
    input: input,
    hasFocus: hasFocus,
    hide: hide,
    select: select,
    show: show,
    tag: tag
  };
}();

var MetricsSetSelectorTags = {
  'economy': 'Economic indicators',
  'interest rates': 'Interest rates',
  'index': 'Indices',
  'stock': 'Stocks',
  'etf': 'ETFs',
  'bond': 'Bonds',
  'commodity': 'Commodities',
  'consumer price': 'Consumer prices',
  'currency': 'Currencies',
  'real estate': 'Real estate'
};
