text: // Licensed to Cloudera, Inc. under one
  // or more contributor license agreements.  See the NOTICE file
  // distributed with this work for additional information
  // regarding copyright ownership.  Cloudera, Inc. licenses this file
  // to you under the Apache License, Version 2.0 (the
  // "License"); you may not use this file except in compliance
  // with the License.  You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  import $ from 'jquery';
  
  /*
   * jHue selector plugin
   * it tranforms a select multiple into a searchable/selectable alphabetical list
   */
  
  const pluginName = 'jHueSelector',
    defaults = {
      selectAllLabel: 'Select all',
      showSelectAll: true,
      searchPlaceholder: 'Search',
      noChoicesFound: 'No choices found for this element',
      width: 300,
      height: 200,
      onChange: function () {}
    };
  
  function Plugin(element, options) {
    this.element = element;
    this.options = $.extend({}, defaults, options);
    this._defaults = defaults;
    this._name = pluginName;
    this.init();
  }
  
  Plugin.prototype.setOptions = function (options) {
    this.options = $.extend({}, defaults, options);
  };
  
  Plugin.prototype.init = function () {
    const _this = this;
    const addressBook = [];
    const selectorContainer = $('<div>');
    if (this.options.width != 300) {
      selectorContainer.width(this.options.width);
    }
    $(_this.element).hide();
    $(_this.element)
      .find('option')
      .each((cnt, opt) => {
        const initial = $(opt).text().substr(0, 1).toLowerCase();
        if (addressBook[initial] == null) {
          addressBook[initial] = [];
        }
        addressBook[initial].push($(opt));
      });
    const sortedKeys = [];
    for (const key in addressBook) {
      if (addressBook.hasOwnProperty(key)) {
        sortedKeys.push(key);
      }
    }
    sortedKeys.sort();
  
    if (sortedKeys.length == 0) {
      $(_this.element).after(
        $('<div>')
          .addClass('alert')
          .css('margin-top', '-2px')
          .css('float', 'left')
          .html(this.options.noChoicesFound)
      );
    } else {
      selectorContainer.addClass('jHueSelector');
      const body = $('<div>').addClass('jHueSelectorBody');
      body.appendTo(selectorContainer);
  
      for (let i = 0; i < sortedKeys.length; i++) {
        const key = sortedKeys[i];
        const ul = $('<ul>');
        const dividerLi = $('<li>').addClass('selectorDivider');
        dividerLi.html('<strong>' + key.toUpperCase() + '</strong>');
        dividerLi.appendTo(ul);
        $.each(addressBook[key], (cnt, opt) => {
          const li = $('<li>');
          const lbl = $('<label>').text(opt.text());
          const chk = $('<input>')
            .attr('type', 'checkbox')
            .addClass('selector')
            .change(function () {
              if ($(this).is(':checked')) {
                $(this).data('opt').attr('selected', 'selected');
              } else {
                $(this).data('opt').removeAttr('selected');
              }
              _this.options.onChange();
            })
            .data('opt', opt)
            .prependTo(lbl);
          if (opt.is(':selected')) {
            chk.attr('checked', 'checked');
          }
          lbl.appendTo(li);
          li.appendTo(ul);
        });
        ul.appendTo(body);
      }
  
      const header = $('<div>').addClass('jHueSelectorHeader');
      header.prependTo(selectorContainer);
  
      const selectAll = $('<label>').html('&nbsp;');
  
      if (this.options.showSelectAll) {
        selectAll.text(this.options.selectAllLabel);
        $('<input>')
          .attr('type', 'checkbox')
          .change(function () {
            const isChecked = $(this).is(':checked');
            selectorContainer.find('input.selector:visible').each(function () {
              if (isChecked) {
                $(this).prop('checked', true);
                $(this).data('opt').attr('selected', 'selected');
              } else {
                $(this).prop('checked', false);
                $(this).data('opt').removeAttr('selected');
              }
            });
            if (searchBox.val() != '') {
              $(this).prop('checked', false);
            }
            _this.options.onChange();
          })
          .prependTo(selectAll);
      }
  
      selectAll.appendTo(header);
  
      const searchBox = $('<input>')
        .attr('type', 'text')
        .attr('placeholder', this.options.searchPlaceholder)
        .keyup(function () {
          body.find('ul').attr('show', true).show();
          const q = $.trim($(this).val());
          if (q != '') {
            body.find('li.selectorDivider').hide();
            body.find('label').each(function () {
              if ($(this).text().toLowerCase().indexOf(q.toLowerCase()) > -1) {
                $(this).parent().show();
              } else {
                $(this).parent().hide();
              }
            });
            body.find('ul').attr('show', false);
            body.find('ul > *:visible').parent().attr('show', true).find('li.selectorDivider').show();
          } else {
            body.find('li.selectorDivider').show();
            body.find('label').parent().show();
          }
          body.find('ul[show=false]').hide();
          body.find('ul[show=true]').show();
        });
      if (this.options.width != 300) {
        searchBox.css('margin-left', this.options.width - 120 + 'px');
      }
      searchBox.prependTo(header);
  
      body.height(this.options.height - header.outerHeight());
  
      $(_this.element).after(selectorContainer);
    }
  };
  
  $.fn[pluginName] = function (options) {
    return this.each(function () {
      if (!$.data(this, 'plugin_' + pluginName)) {
        $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
      } else {
        $.data(this, 'plugin_' + pluginName).setOptions(options);
      }
    });
  };
  