/**
* Peopler: multi autocomplete field for looking up users by email or name
*/

jQuery.fn.peopler = function(form_field_prefix, new_users_only) {
  return this.each(function() {
		new $.Peopler(this, form_field_prefix, new_users_only);
	});
};

jQuery.Peopler = function(div, form_field_prefix, new_users_only) {
  var USER_LIST_URL = "/people.json";
  var PROMPT_STRING = "Enter username or full email address";
  
  var $input = $(div).find('input');
  var $options = $(div).find('ul.options');
  var $selections = $(div).find('ul.selections');
  
  var user_list = new Array();
  
  /**
  * Register event handlers
  */
  $input.focus(function() {
    if ($(this).val() == PROMPT_STRING) $(this).val('').removeClass('prompt');
    populate_options_from_input();
  }).blur(function() {
    if ($(this).val() == "") $(this).val(PROMPT_STRING).addClass('prompt');
    setTimeout(function() {
      $options.hide();
    }, 200);
  }).keydown(function(e) {
    var propagate = true;
    switch (e.keyCode) {
    case jQuery.keyCodes.ENTER:
      create_selection();
      propagate = false;
      break;
    case jQuery.keyCodes.UP:
    case jQuery.keyCodes.DOWN:
      var $selected_option = $options.find('li.sel');
      highlight_option( e.keyCode == jQuery.keyCodes.UP ? $selected_option.prev() : $selected_option.next())
      break;
    case jQuery.keyCodes.TAB:
    case jQuery.keyCodes.ESCAPE:
      $options.hide();
      break;
    default:
      if (!this.new_users_only) setTimeout(populate_options_from_input, 1);
    }
    return propagate;
  });
  $input.blur();
  
  $(div).find('a.add').click(function() {
    create_selection();
    return false;
  });
  
  $selections.click(function() {
    $input.focus();
  });
  
  $(div).parents('form').submit(function() {
    if (!create_selection()) return false; // flush whatever seemed selected; don't submit if it's bad data!
  });
  
  /**
  * Init: Preload user data and init serverside-populated fields
  */
  if (!new_users_only) {
    $.get(USER_LIST_URL, {}, function(data) {
      user_list = data;
    }, "json");
  }
  $selections.find('li').each(function() {
    $(this).acts_as_selection(form_field_prefix);
  });
  
  /**
  * Look at the user-entered text fragment and put together an options list
  */
  function populate_options_from_input() {
    $options.empty();
    if ($input.val().length) {
      $(user_list).each(function() {
        if (this.name.toLowerCase().match('^'+$input.val())) {
          $options.append(jQuery.create('li', {'user_id': this.id}, this.name).click(function() {
            create_selection();
          }).mouseover(function() {
            highlight_option($(this));
          }));
        }
      });
      if ($options.children().length) $options.show().children().eq(0).addClass('sel');
      else $options.hide();
    }
  }
  
  /**
  * Highlight item in options list (clicked or arrow-keyed)
  */
  function highlight_option($option_to_highlight) {
    if ($option_to_highlight.is('li')) {
      $options.children().removeClass('sel');
      $option_to_highlight.addClass('sel');
    }
  }
  
  /**
  * Add something to 'selections' box: either an existing user (autocomplete option) or a new one (email only).
  * This just creates the LI and hands of the dirty work to acts_as_selection
  */
  function create_selection() {
    var validation_error_found = false;
    var $new_selection = null;
    if ($input.val() != "" && $input.val() != PROMPT_STRING) {
      var $selection = $options.find('li.sel');
      if ($selection.length) {
        $new_selection = $selection.clone().attr({'className': 'id'});
        $options.hide();
      } else { // maybe user typed an email address?
        if (is_email($input.val())) {
          $new_selection = jQuery.create('li', {className: 'email'}, $input.val());
        } else {
          alert("That email doesn't look valid");
          validation_error_found = true;
        }
      }
      if ($new_selection) {
        $selections.append($new_selection.acts_as_selection(form_field_prefix));
        $input.val("");
      }
    }
    return !validation_error_found;
  }
  
};


/**
* Take a plain old LI and ennoble it with event handlers and hidden inputs for the server to parse.
*/
jQuery.fn.acts_as_selection = function(form_field_prefix) {
  var $selection = $(this);
  var form_params = {'id': this.attr('user_id'), 'email': this.text()};
  jQuery.each(form_params, function(key, value) {
    $selection.append(hidden_field(form_field_prefix+'['+key+']', value));
  });
  
  return $selection.click(function() {
    $(this).remove();
  }).mouseover(function() {
    $(this).addClass('del');
  }).mouseout(function() {
    $(this).removeClass('del')
  });
};
