(function($) {

  var pluginName = "typeahead_selector";

  var defaultOptions = {
  };

  var methods = {
    initialize: function (opts, sources) {

      return this.each(function() {
        var options = $.extend({}, defaultOptions, opts);
        var $this = $(this);
        $this.typeahead(opts, sources);

        $this
          .on("typeahead:change", function(evt, value) {
            privateMethods.change($this, value);
          })
          .on("typeahead:select", function(evt, value) {
            privateMethods.select($this, value);
          })
          .on("typeahead:autocomplete", function(evt, value) {
            privateMethods.autocomplete($this, value);
          });
      });
    },

    val: function() {
      if (this.length) {
        return $(this[0]).data('typeahead_selected');
      } else {
        return null;
      }
    }
  };

  var privateMethods = {
    change: function($this, value) {
      var item = $this.data('typeahead_pending');
      if (item) {
        $this.data('typeahead_pending', null);
        $this.data('typeahead_selected', item);
        $this.trigger("typeahead_selector:selected", item);
      } else {
        $this.data('typeahead_selected', null);
        $this.trigger("typeahead_selector:invalid", value);
      }
    },

    select: function($this, item) {
      $this.data('typeahead_pending', item);
    },

    autocomplete: function($this, item) {
      $this.data('typeahead_pending', item);
    }
  };

  $.fn[pluginName] = function (method) {
    if (methods[method]) {
      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    } else if (typeof method === 'object' || ! method) {
      return methods.initialize.apply(this, arguments);
    } else {
      $.error('Method ' +  method + ' does not exist on jQuery.' + pluginName);
    }
  };

})(jQuery);