define(['jquery', 'lodash', 'i18n', 'core/eventifier', 'handlebars', 'lib/handlebars/helpers', 'ui/selecter'], function ($$1, _, __, eventifier, Handlebars, Helpers0, selecter) { 'use strict';

    $$1 = $$1 && Object.prototype.hasOwnProperty.call($$1, 'default') ? $$1['default'] : $$1;
    _ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _;
    __ = __ && Object.prototype.hasOwnProperty.call(__, 'default') ? __['default'] : __;
    eventifier = eventifier && Object.prototype.hasOwnProperty.call(eventifier, 'default') ? eventifier['default'] : eventifier;
    Handlebars = Handlebars && Object.prototype.hasOwnProperty.call(Handlebars, 'default') ? Handlebars['default'] : Handlebars;
    Helpers0 = Helpers0 && Object.prototype.hasOwnProperty.call(Helpers0, 'default') ? Helpers0['default'] : Helpers0;

    if (!Helpers0.__initialized) {
      Helpers0(Handlebars);
      Helpers0.__initialized = true;
    }
    var Template = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
      this.compilerInfo = [4,'>= 1.0.0'];
    helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
      var buffer = "", stack1, functionType="function", escapeExpression=this.escapeExpression, self=this;

    function program1(depth0,data) {
      
      var buffer = "", stack1, helper;
      buffer += "\n    <label class=\"form_desc\">";
      if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "</label>\n    ";
      return buffer;
      }

      buffer += "<div>\n    ";
      stack1 = helpers['if'].call(depth0, (depth0 && depth0.label), {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
      if(stack1 || stack1 === 0) { buffer += stack1; }
      buffer += "\n    <div class=\"item-filter\"></div>\n</div>";
      return buffer;
      });
    function filterTpl(data, options, asString) {
      var html = Template(data, options);
      return (asString || true) ? html : $(html);
    }

    /**
     * Copyright (c) 2016 Open Assessment Technologies, S.A.
     *
     * @author Bertrand Chevrier <bertrand@taotesting.com>
     * @author Alexander Zagovorichev <zagovorichev@1pt.com>
     * @author Ivan Klimchuk <klimchuk@1pt.com>
     * @author Mikhail Kamarouski <kamarouski@1pt.com>
     */
    var defaults = {
      placeholder: __('Filter by value'),
      width: 300,
      minimumResultsForSearch: 10,
      minimumInputLength: 3,
      enable: true,
      quietMillis: 2000,
      label: false
    };

    /**
     * Creates a item filter component
     *
     * @param {Object[]} items - the list of items
     * @param {Object} [options] - configuration options
     * @param {String} [options.placeholder] - the filter placeholder
     * @param {Number} [options.width] - the select width
     * @param {Function} [options.formatter] - function for formatting result lines
     * @returns {itemFilter} the component
     */
    function itemFilterFactory($container, options) {
      var selected = {
        uri: '',
        code: '',
        name: ''
      };
      options = _.defaults(options || {}, defaults);

      /**
       * The item filter component
       * @typedef {Object} itemFilter
       */
      return eventifier({
        /**
         * Render the component into a container
         * @returns {itemFilter} chains
         * @fires itemFilter#change
         */
        render: function render(format) {
          var self = this;
          var $component = $$1(filterTpl(options));
          var $list = $$1('.item-filter', $component);
          $list.select2({
            placeholder: options.placeholder,
            allowClear: true,
            width: options.width,
            minimumResultsForSearch: options.minimumResultsForSearch,
            minimumInputLength: options.minimumInputLength,
            maximumInputLength: 200,
            formatResult: _.isFunction(options.formatter) ? options.formatter : data => _.template(format)(data),
            ajax: {
              quietMillis: options.quietMillis,
              data: (term, page) => ({
                q: term,
                // search term
                page: page
              }),
              transport: function (params) {
                self.trigger('request', params);
              },
              results: function (data, page) {
                var more = page * 25 < data.total;
                return {
                  results: data.items,
                  more: more
                };
              },
              cache: true
            }
          });
          $list.select2('enable', options.enable);
          $list.on('change.select2', function () {
            selected = $list.select2('data');
            self.trigger('change', selected && selected.uri ? selected.uri : '');
          });
          $container.append($component);
          return this;
        },
        enable: function enable() {
          $$1('.item-filter', $container).select2('enable', true);
        },
        disable: function disable() {
          $$1('.item-filter', $container).select2('enable', false);
        },
        getSelected: function getSelected() {
          return selected;
        },
        reset: function reset() {
          var $list = $$1('.item-filter', $container);
          $list.select2('val', '');
        },
        /**
         * Leave the place as clean as before
         * @returns {selector} for chaining
         * @fires selector#destroy
         */
        destroy: function destroy() {
          var $list = $$1('.item-filter', $container);
          $list.select2('destroy');
          $list.remove();

          /**
           * The selector is destroyed
           * @event selector#destroy
           */
          this.trigger('destroy');
          return this;
        }
      });
    }

    return itemFilterFactory;

});
