(function() {
  var GitLabDropdown, GitLabDropdownFilter, GitLabDropdownRemote,
    bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  GitLabDropdownFilter = (function() {
    var ARROW_KEY_CODES, BLUR_KEYCODES, HAS_VALUE_CLASS;

    BLUR_KEYCODES = [27, 40];

    ARROW_KEY_CODES = [38, 40];

    HAS_VALUE_CLASS = "has-value";

    function GitLabDropdownFilter(input, options) {
      var $clearButton, $inputContainer, ref, timeout;
      this.input = input;
      this.options = options;
      this.filterInputBlur = (ref = this.options.filterInputBlur) != null ? ref : true;
      $inputContainer = this.input.parent();
      $clearButton = $inputContainer.find('.js-dropdown-input-clear');
      this.indeterminateIds = [];
      $clearButton.on('click', (function(_this) {
        return function(e) {
          e.preventDefault();
          e.stopPropagation();
          return _this.input.val('').trigger('keyup').focus();
        };
      })(this));
      timeout = "";
      this.input
        .on('keydown', function (e) {
          var keyCode = e.which;
          if (keyCode === 13 && !options.elIsInput) {
            e.preventDefault()
          }
        })
        .on('keyup', function(e) {
          var keyCode;
          keyCode = e.which;
          if (ARROW_KEY_CODES.indexOf(keyCode) >= 0) {
            return;
          }
          if (this.input.val() !== "" && !$inputContainer.hasClass(HAS_VALUE_CLASS)) {
            $inputContainer.addClass(HAS_VALUE_CLASS);
          } else if (this.input.val() === "" && $inputContainer.hasClass(HAS_VALUE_CLASS)) {
            $inputContainer.removeClass(HAS_VALUE_CLASS);
          }
          if (keyCode === 13 && !options.elIsInput) {
            return false;
          }
          if (this.options.remote) {
            clearTimeout(timeout);
            return timeout = setTimeout(function() {
              var blurField = this.shouldBlur(keyCode);
              if (blurField && this.filterInputBlur) {
                this.input.blur();
              }
              return this.options.query(this.input.val(), function(data) {
                return this.options.callback(data);
              }.bind(this));
            }.bind(this), 250);
          } else {
            return this.filter(this.input.val());
          }
        }.bind(this));
    }

    GitLabDropdownFilter.prototype.shouldBlur = function(keyCode) {
      return BLUR_KEYCODES.indexOf(keyCode) >= 0;
    };

    GitLabDropdownFilter.prototype.filter = function(search_text) {
      var data, elements, group, key, results, tmp;
      if (this.options.onFilter) {
        this.options.onFilter(search_text);
      }
      data = this.options.data();
      if ((data != null) && !this.options.filterByText) {
        results = data;
        if (search_text !== '') {
          if (_.isArray(data)) {
            results = fuzzaldrinPlus.filter(data, search_text, {
              key: this.options.keys
            });
          } else {
            if (gl.utils.isObject(data)) {
              results = {};
              for (key in data) {
                group = data[key];
                tmp = fuzzaldrinPlus.filter(group, search_text, {
                  key: this.options.keys
                });
                if (tmp.length) {
                  results[key] = tmp.map(function(item) {
                    return item;
                  });
                }
              }
            }
          }
        }
        return this.options.callback(results);
      } else {
        elements = this.options.elements();
        if (search_text) {
          return elements.each(function() {
            var $el, matches;
            $el = $(this);
            matches = fuzzaldrinPlus.match($el.text().trim(), search_text);
            if (!$el.is('.dropdown-header')) {
              if (matches.length) {
                return $el.show().removeClass('option-hidden');
              } else {
                return $el.hide().addClass('option-hidden');
              }
            }
          });
        } else {
          return elements.show().removeClass('option-hidden');
        }
      }
    };

    return GitLabDropdownFilter;

  })();

  GitLabDropdownRemote = (function() {
    function GitLabDropdownRemote(dataEndpoint, options) {
      this.dataEndpoint = dataEndpoint;
      this.options = options;
    }

    GitLabDropdownRemote.prototype.execute = function() {
      if (typeof this.dataEndpoint === "string") {
        return this.fetchData();
      } else if (typeof this.dataEndpoint === "function") {
        if (this.options.beforeSend) {
          this.options.beforeSend();
        }
        return this.dataEndpoint("", (function(_this) {
          return function(data) {
            if (_this.options.success) {
              _this.options.success(data);
            }
            if (_this.options.beforeSend) {
              return _this.options.beforeSend();
            }
          };
        })(this));
      }
    };

    GitLabDropdownRemote.prototype.fetchData = function() {
      return $.ajax({
        url: this.dataEndpoint,
        dataType: this.options.dataType,
        beforeSend: (function(_this) {
          return function() {
            if (_this.options.beforeSend) {
              return _this.options.beforeSend();
            }
          };
        })(this),
        success: (function(_this) {
          return function(data) {
            if (_this.options.success) {
              return _this.options.success(data);
            }
          };
        })(this)
      });
    };

    return GitLabDropdownRemote;

  })();

  GitLabDropdown = (function() {
    var ACTIVE_CLASS, FILTER_INPUT, INDETERMINATE_CLASS, LOADING_CLASS, PAGE_TWO_CLASS, NON_SELECTABLE_CLASSES, SELECTABLE_CLASSES, currentIndex;

    LOADING_CLASS = "is-loading";

    PAGE_TWO_CLASS = "is-page-two";

    ACTIVE_CLASS = "is-active";

    INDETERMINATE_CLASS = "is-indeterminate";

    currentIndex = -1;

    NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-link';

    SELECTABLE_CLASSES = ".dropdown-content li:not(" + NON_SELECTABLE_CLASSES + ", .option-hidden)";

    CURSOR_SELECT_SCROLL_PADDING = 5

    FILTER_INPUT = '.dropdown-input .dropdown-input-field';

    function GitLabDropdown(el1, options) {
      var ref, ref1, ref2, ref3, searchFields, selector, self;
      this.el = el1;
      this.options = options;
      this.updateLabel = bind(this.updateLabel, this);
      this.hidden = bind(this.hidden, this);
      this.opened = bind(this.opened, this);
      this.shouldPropagate = bind(this.shouldPropagate, this);
      self = this;
      selector = $(this.el).data("target");
      this.dropdown = selector != null ? $(selector) : $(this.el).parent();
      ref = this.options, this.filterInput = (ref1 = ref.filterInput) != null ? ref1 : this.getElement(FILTER_INPUT), this.highlight = (ref2 = ref.highlight) != null ? ref2 : false, this.filterInputBlur = (ref3 = ref.filterInputBlur) != null ? ref3 : true;
      self = this;
      if (_.isString(this.filterInput)) {
        this.filterInput = this.getElement(this.filterInput);
      }
      searchFields = this.options.search ? this.options.search.fields : [];
      if (this.options.data) {
        if (_.isObject(this.options.data) && !_.isFunction(this.options.data)) {
          this.fullData = this.options.data;
          currentIndex = -1;
          this.parseData(this.options.data);
        } else {
          this.remote = new GitLabDropdownRemote(this.options.data, {
            dataType: this.options.dataType,
            beforeSend: this.toggleLoading.bind(this),
            success: (function(_this) {
              return function(data) {
                _this.fullData = data;
                _this.parseData(_this.fullData);
                if (_this.options.filterable && _this.filter && _this.filter.input) {
                  return _this.filter.input.trigger('keyup');
                }
              };
            })(this)
          });
        }
      }
      if (this.options.filterable) {
        this.filter = new GitLabDropdownFilter(this.filterInput, {
          elIsInput: $(this.el).is('input'),
          filterInputBlur: this.filterInputBlur,
          filterByText: this.options.filterByText,
          onFilter: this.options.onFilter,
          remote: this.options.filterRemote,
          query: this.options.data,
          keys: searchFields,
          elements: (function(_this) {
            return function() {
              selector = '.dropdown-content li:not(' + NON_SELECTABLE_CLASSES + ')';
              if (_this.dropdown.find('.dropdown-toggle-page').length) {
                selector = ".dropdown-page-one " + selector;
              }
              return $(selector);
            };
          })(this),
          data: (function(_this) {
            return function() {
              return _this.fullData;
            };
          })(this),
          callback: (function(_this) {
            return function(data) {
              _this.parseData(data);
              if (_this.filterInput.val() !== '') {
                selector = SELECTABLE_CLASSES;
                if (_this.dropdown.find('.dropdown-toggle-page').length) {
                  selector = ".dropdown-page-one " + selector;
                }
                if ($(_this.el).is('input')) {
                  currentIndex = -1;
                } else {
                  $(selector, _this.dropdown).first().find('a').addClass('is-focused');
                  currentIndex = 0;
                }
              }
            };
          })(this)
        });
      }
      this.dropdown.on("shown.bs.dropdown", this.opened);
      this.dropdown.on("hidden.bs.dropdown", this.hidden);
      $(this.el).on("update.label", this.updateLabel);
      this.dropdown.on("click", ".dropdown-menu, .dropdown-menu-close", this.shouldPropagate);
      this.dropdown.on('keyup', (function(_this) {
        return function(e) {
          if (e.which === 27) {
            return $('.dropdown-menu-close', _this.dropdown).trigger('click');
          }
        };
      })(this));
      this.dropdown.on('blur', 'a', (function(_this) {
        return function(e) {
          var $dropdownMenu, $relatedTarget;
          if (e.relatedTarget != null) {
            $relatedTarget = $(e.relatedTarget);
            $dropdownMenu = $relatedTarget.closest('.dropdown-menu');
            if ($dropdownMenu.length === 0) {
              return _this.dropdown.removeClass('open');
            }
          }
        };
      })(this));
      if (this.dropdown.find(".dropdown-toggle-page").length) {
        this.dropdown.find(".dropdown-toggle-page, .dropdown-menu-back").on("click", (function(_this) {
          return function(e) {
            e.preventDefault();
            e.stopPropagation();
            return _this.togglePage();
          };
        })(this));
      }
      if (this.options.selectable) {
        selector = ".dropdown-content a";
        if (this.dropdown.find(".dropdown-toggle-page").length) {
          selector = ".dropdown-page-one .dropdown-content a";
        }
        this.dropdown.on("click", selector, function(e) {
          var $el, selected;
          $el = $(this);
          selected = self.rowClicked($el);
          if (self.options.clicked) {
            self.options.clicked(selected, $el, e);
          }
          return $el.trigger('blur');
        });
      }
    }

    GitLabDropdown.prototype.getElement = function(selector) {
      return this.dropdown.find(selector);
    };

    GitLabDropdown.prototype.toggleLoading = function() {
      return $('.dropdown-menu', this.dropdown).toggleClass(LOADING_CLASS);
    };

    GitLabDropdown.prototype.togglePage = function() {
      var menu;
      menu = $('.dropdown-menu', this.dropdown);
      if (menu.hasClass(PAGE_TWO_CLASS)) {
        if (this.remote) {
          this.remote.execute();
        }
      }
      menu.toggleClass(PAGE_TWO_CLASS);
      return this.dropdown.find('[class^="dropdown-page-"]:visible :text:visible:first').focus();
    };

    GitLabDropdown.prototype.parseData = function(data) {
      var full_html, groupData, html, name;
      this.renderedData = data;
      if (this.options.filterable && data.length === 0) {
        html = [this.noResults()];
      } else {
        if (gl.utils.isObject(data)) {
          html = [];
          for (name in data) {
            groupData = data[name];
            html.push(this.renderItem({
              header: name
            }, name));
            this.renderData(groupData, name).map(function(item) {
              return html.push(item);
            });
          }
        } else {
          html = this.renderData(data);
        }
      }
      full_html = this.renderMenu(html);
      return this.appendMenu(full_html);
    };

    GitLabDropdown.prototype.renderData = function(data, group) {
      if (group == null) {
        group = false;
      }
      return data.map((function(_this) {
        return function(obj, index) {
          return _this.renderItem(obj, group, index);
        };
      })(this));
    };

    GitLabDropdown.prototype.shouldPropagate = function(e) {
      var $target;
      if (this.options.multiSelect) {
        $target = $(e.target);
        if ($target && !$target.hasClass('dropdown-menu-close') && !$target.hasClass('dropdown-menu-close-icon') && !$target.data('is-link')) {
          e.stopPropagation();
          return false;
        } else {
          return true;
        }
      }
    };

    GitLabDropdown.prototype.opened = function() {
      var contentHtml;
      this.resetRows();
      this.addArrowKeyEvent();
      if (this.options.setIndeterminateIds) {
        this.options.setIndeterminateIds.call(this);
      }
      if (this.options.setActiveIds) {
        this.options.setActiveIds.call(this);
      }
      if (this.fullData && this.dropdown.find('.dropdown-menu-toggle').hasClass('js-filter-bulk-update')) {
        this.parseData(this.fullData);
      }
      contentHtml = $('.dropdown-content', this.dropdown).html();
      if (this.remote && contentHtml === "") {
        this.remote.execute();
      }
      if (this.options.filterable) {
        this.filterInput.focus();
      }
      return this.dropdown.trigger('shown.gl.dropdown');
    };

    GitLabDropdown.prototype.hidden = function(e) {
      var $input;
      this.resetRows();
      this.removeArrayKeyEvent();
      $input = this.dropdown.find(".dropdown-input-field");
      if (this.options.filterable) {
        $input.blur().val("");
      }
      if (!this.options.persistWhenHide) {
        $input.trigger("keyup");
      }
      if (this.dropdown.find(".dropdown-toggle-page").length) {
        $('.dropdown-menu', this.dropdown).removeClass(PAGE_TWO_CLASS);
      }
      if (this.options.hidden) {
        this.options.hidden.call(this, e);
      }
      return this.dropdown.trigger('hidden.gl.dropdown');
    };

    GitLabDropdown.prototype.renderMenu = function(html) {
      var menu_html;
      menu_html = "";
      if (this.options.renderMenu) {
        menu_html = this.options.renderMenu(html);
      } else {
        menu_html = $('<ul />').append(html);
      }
      return menu_html;
    };

    GitLabDropdown.prototype.appendMenu = function(html) {
      var selector;
      selector = '.dropdown-content';
      if (this.dropdown.find(".dropdown-toggle-page").length) {
        selector = ".dropdown-page-one .dropdown-content";
      }
      return $(selector, this.dropdown).empty().append(html);
    };

    GitLabDropdown.prototype.renderItem = function(data, group, index) {
      var cssClass, field, fieldName, groupAttrs, html, selected, text, url, value;
      if (group == null) {
        group = false;
      }
      if (index == null) {
        index = false;
      }
      html = "";
      if (data === "divider") {
        return "<li class='divider'></li>";
      }
      if (data === "separator") {
        return "<li class='separator'></li>";
      }
      if (data.header != null) {
        return _.template('<li class="dropdown-header"><%- header %></li>')({ header: data.header });
      }
      if (this.options.renderRow) {
        html = this.options.renderRow.call(this.options, data, this);
      } else {
        if (!selected) {
          value = this.options.id ? this.options.id(data) : data.id;
          fieldName = typeof this.options.fieldName === 'function' ? this.options.fieldName() : this.options.fieldName;

          field = this.dropdown.parent().find("input[name='" + fieldName + "'][value='" + value + "']");
          if (field.length) {
            selected = true;
          }
        }
        if (this.options.url != null) {
          url = this.options.url(data);
        } else {
          url = data.url != null ? data.url : '#';
        }
        if (this.options.text != null) {
          text = this.options.text(data);
        } else {
          text = data.text != null ? data.text : '';
        }
        cssClass = "";
        if (selected) {
          cssClass = "is-active";
        }
        if (this.highlight) {
          text = this.highlightTextMatches(text, this.filterInput.val());
        }
        if (group) {
          groupAttrs = 'data-group=' + group + ' data-index=' + index;
        } else {
          groupAttrs = '';
        }
        html = _.template('<li><a href="<%- url %>" <%- groupAttrs %> class="<%- cssClass %>"><%= text %></a></li>')({
          url: url,
          groupAttrs: groupAttrs,
          cssClass: cssClass,
          text: text
        });
      }
      return html;
    };

    GitLabDropdown.prototype.highlightTextMatches = function(text, term) {
      var occurrences;
      occurrences = fuzzaldrinPlus.match(text, term);
      return text.split('').map(function(character, i) {
        if (indexOf.call(occurrences, i) >= 0) {
          return "<b>" + character + "</b>";
        } else {
          return character;
        }
      }).join('');
    };

    GitLabDropdown.prototype.noResults = function() {
      var html;
      return html = "<li class='dropdown-menu-empty-link'> <a href='#' class='is-focused'> No matching results. </a> </li>";
    };

    GitLabDropdown.prototype.rowClicked = function(el) {
      var field, fieldName, groupName, isInput, selectedIndex, selectedObject, value;
      isInput = $(this.el).is('input');
      if (this.renderedData) {
        groupName = el.data('group');
        if (groupName) {
          selectedIndex = el.data('index');
          selectedObject = this.renderedData[groupName][selectedIndex];
        } else {
          selectedIndex = el.closest('li').index();
          selectedObject = this.renderedData[selectedIndex];
        }
      }
      fieldName = typeof this.options.fieldName === 'function' ? this.options.fieldName(selectedObject) : this.options.fieldName;
      value = this.options.id ? this.options.id(selectedObject, el) : selectedObject.id;
      if (isInput) {
        field = $(this.el);
      } else {
        field = this.dropdown.parent().find("input[name='" + fieldName + "'][value='" + escape(value) + "']");
      }
      if (el.hasClass(ACTIVE_CLASS)) {
        el.removeClass(ACTIVE_CLASS);
        if (isInput) {
          field.val('');
        } else {
          field.remove();
        }
      } else if (el.hasClass(INDETERMINATE_CLASS)) {
        el.addClass(ACTIVE_CLASS);
        el.removeClass(INDETERMINATE_CLASS);
        if (value == null) {
          field.remove();
        }
        if (!field.length && fieldName) {
          this.addInput(fieldName, value, selectedObject);
        }
      } else {
        if (!this.options.multiSelect || el.hasClass('dropdown-clear-active')) {
          this.dropdown.find("." + ACTIVE_CLASS).removeClass(ACTIVE_CLASS);
          if (!isInput) {
            this.dropdown.parent().find("input[name='" + fieldName + "']").remove();
          }
        }
        if (value == null) {
          field.remove();
        }
        el.addClass(ACTIVE_CLASS);
        if (value != null) {
          if (!field.length && fieldName) {
            this.addInput(fieldName, value, selectedObject);
          } else {
            field.val(value).trigger('change');
          }
        }
      }

      // Update label right after input has been added
      if (this.options.toggleLabel) {
        this.updateLabel(selectedObject, el, this);
      }

      return selectedObject;
    };

    GitLabDropdown.prototype.addInput = function(fieldName, value, selectedObject) {
      var $input;
      $input = $('<input>').attr('type', 'hidden').attr('name', fieldName).val(value);
      if (this.options.inputId != null) {
        $input.attr('id', this.options.inputId);
      }
      if (selectedObject && selectedObject.type) {
        $input.attr('data-type', selectedObject.type);
      }
      return this.dropdown.before($input);
    };

    GitLabDropdown.prototype.selectRowAtIndex = function(index) {
      var $el, selector;
      // If we pass an option index
      if (typeof index !== "undefined") {
        selector = SELECTABLE_CLASSES + ":eq(" + index + ") a";
      } else {
        selector = ".dropdown-content .is-focused";
      }
      if (this.dropdown.find(".dropdown-toggle-page").length) {
        selector = ".dropdown-page-one " + selector;
      }
      $el = $(selector, this.dropdown);
      if ($el.length) {
        var href = $el.attr('href');
        if (href && href !== '#') {
          Turbolinks.visit(href);
        } else {
          $el.first().trigger('click');
        }
      }
    };

    GitLabDropdown.prototype.addArrowKeyEvent = function() {
      var $input, ARROW_KEY_CODES, selector;
      ARROW_KEY_CODES = [38, 40];
      $input = this.dropdown.find(".dropdown-input-field");
      selector = SELECTABLE_CLASSES;
      if (this.dropdown.find(".dropdown-toggle-page").length) {
        selector = ".dropdown-page-one " + selector;
      }
      return $('body').on('keydown', (function(_this) {
        return function(e) {
          var $listItems, PREV_INDEX, currentKeyCode;
          currentKeyCode = e.which;
          if (ARROW_KEY_CODES.indexOf(currentKeyCode) >= 0) {
            e.preventDefault();
            e.stopImmediatePropagation();
            PREV_INDEX = currentIndex;
            $listItems = $(selector, _this.dropdown);
            if (currentKeyCode === 40) {
              if (currentIndex < ($listItems.length - 1)) {
                currentIndex += 1;
              }
            } else if (currentKeyCode === 38) {
              if (currentIndex > 0) {
                currentIndex -= 1;
              }
            }
            if (currentIndex !== PREV_INDEX) {
              _this.highlightRowAtIndex($listItems, currentIndex);
            }
            return false;
          }
          if (currentKeyCode === 13 && currentIndex !== -1) {
            _this.selectRowAtIndex();
          }
        };
      })(this));
    };

    GitLabDropdown.prototype.removeArrayKeyEvent = function() {
      return $('body').off('keydown');
    };

    GitLabDropdown.prototype.resetRows = function resetRows() {
      currentIndex = -1;
      $('.is-focused', this.dropdown).removeClass('is-focused');
    };

    GitLabDropdown.prototype.highlightRowAtIndex = function($listItems, index) {
      var $dropdownContent, $listItem, dropdownContentBottom, dropdownContentHeight, dropdownContentTop, dropdownScrollTop, listItemBottom, listItemHeight, listItemTop;
      $('.is-focused', this.dropdown).removeClass('is-focused');
      $listItem = $listItems.eq(index);
      $listItem.find('a:first-child').addClass("is-focused");
      $dropdownContent = $listItem.closest('.dropdown-content');
      dropdownScrollTop = $dropdownContent.scrollTop();
      dropdownContentHeight = $dropdownContent.outerHeight();
      dropdownContentTop = $dropdownContent.prop('offsetTop');
      dropdownContentBottom = dropdownContentTop + dropdownContentHeight;
      listItemHeight = $listItem.outerHeight();
      listItemTop = $listItem.prop('offsetTop');
      listItemBottom = listItemTop + listItemHeight;
      if (!index) {
        $dropdownContent.scrollTop(0)
      } else if (index === ($listItems.length - 1)) {
        $dropdownContent.scrollTop($dropdownContent.prop('scrollHeight'));
      } else if (listItemBottom > (dropdownContentBottom + dropdownScrollTop)) {
        $dropdownContent.scrollTop(listItemBottom - dropdownContentBottom + CURSOR_SELECT_SCROLL_PADDING);
      } else if (listItemTop < (dropdownContentTop + dropdownScrollTop)) {
        return $dropdownContent.scrollTop(listItemTop - dropdownContentTop - CURSOR_SELECT_SCROLL_PADDING);
      }
    };

    GitLabDropdown.prototype.updateLabel = function(selected, el, instance) {
      if (selected == null) {
        selected = null;
      }
      if (el == null) {
        el = null;
      }
      if (instance == null) {
        instance = null;
      }
      return $(this.el).find(".dropdown-toggle-text").text(this.options.toggleLabel(selected, el, instance));
    };

    return GitLabDropdown;

  })();

  $.fn.glDropdown = function(opts) {
    return this.each(function() {
      if (!$.data(this, 'glDropdown')) {
        return $.data(this, 'glDropdown', new GitLabDropdown(this, opts));
      }
    });
  };

}).call(this);