define([
		'jquery/jquery-2.1.3',
		'lodash/lodash',
		'text!partials/filteredSelect.html'
	],
	function(
		jQ,
		_,
		partial) {
		var filteredSelectDirective = function($filter, KEYCODES) {
			return {
				restrict: 'E',
				scope: {
					options: "&",
					ngModel: "=",

					display: "@",
					value: "@",
					placeholder: "@",
				},
				template: partial,
				link: function(scope, element, attrs) {
					var eleId = _.uniqueId('text_');
					scope.root = scope;

					scope.contains = function(option, index) {
						if(_.isUndefined(angular.element(element).find('input').val()) ||
							scope.ngModel === angular.element(element).find('input').val()) {
							return true;
						} else {
							return _.contains(scope.getValue(option), angular.element(element).find('input').val());
						}
					}

					scope.getValue = function(selected) {
						if(_.isUndefined(scope.value)) {
							return selected;
						} else {
							return selected[scope.value];
						}
					}

					scope.getDisplay = function(selected) {
						if(_.isUndefined(scope.display)) {
							return selected;
						} else {
							return selected[scope.display];
						}
					}

					var getFilteredResults = function (argument) {
						var results = _.chain(scope.options())
							.values()
							.flatten()
							.value();

						return angular.element(element).find('input').val().length > 0 ? $filter('filter')(results, scope.contains) : results;
					}

					scope.handleKeyup = function(event) {
						switch(event.keyCode) {
							case KEYCODES.RETURN:
								scope.suggesting = false;
								(element.find('input')[0]).blur()
								scope.ngModel = scope.getValue(_.first(getFilteredResults()));
								break;
						}
					}

					scope.$on("$destroy", function() {
						angular.element(document).off((['click', eleId]).join('.'));
					});

					$(document).on((['click', eleId]).join('.'), function(event) {
						if(event && !element[0].contains(event.target)) {
							var filteredResults = getFilteredResults();

							if(scope.suggesting) {
								scope.$apply(function() {
									scope.suggesting = false;
									if(filteredResults.length === 1) {
										scope.ngModel = scope.getValue(_.first(filteredResults))
									} else {
										scope.ngModel = null
									}
								});
							}
						}
					});
				},
			};
		};

		return filteredSelectDirective;
	}
);
