/*
 * Author: Yves Van Broekhoven & Simon Menke
 * Created at: 2012-07-05
 *
 * Fork: Andy Thomas (http://and.yt)
 * Fork Created at: 2014-08-04
 * Fork URL: https://github.com/antom/jquery-chosen-sortable
 *
 * Requirements:
 * - jQuery
 * - jQuery UI
 * - Chosen
 *
 * Version: 1.0.1
 */
(function($) {
   $.fn.chosenClassPrefix = function() {
      return $(this).is('[class^="chzn-"]')
         ? 'chzn'
         : 'chosen';
   };

   $.fn.preBind = function(type, parameters, fn) {
      type = type.split(/\s+/);

      this.each(function() {
         var len = type.length;
         while (len--) {
            if (typeof parameters === 'function') {
               $(this).bind(type[len], parameters);
            } else {
               $(this).bind(type[len], parameters, fn);
            }

            var evt = $._data(this, 'events')[type[len]];
            evt.splice(0, 0, evt.pop());
         }
      });
   };

   $.fn.chosenOrder = function() {
      var $this = this.filter('.selecter-sortable[multiple]').first(),
          $chosen = $this.siblings('.' + this.chosenClassPrefix() + '-container');

      return $($.map($chosen.find('.' + this.chosenClassPrefix() + '-choices li[class!="search-field"]').map(function() {
         if (!this) {
            return undefined;
         }

         return $this.find('option[value="' + $(this).data('option-value') + '"]').toArray();
      }), function(x) {
         return x;
      }));
   };


   /*
    * Extend jQuery
    */
   $.fn.chosenSortable = function() {
      var $this = this.filter('.selecter-sortable[multiple]');

      $this.each(function() {
         var $select = $(this);
         var $chosen = $select.siblings('.' + $select.chosenClassPrefix() + '-container');

         if ($.ui) {
            // On mousedown of choice element,
            // we don't want to display the dropdown list
            $chosen.find('.' + $select.chosenClassPrefix() + '-choices').bind('mousedown', function(event) {
               if ($(event.target).is('span')) {
                  event.stopPropagation();
               }
            }).preBind('click', function(event) {
               if ($(event.target).is('span')) {
                  event.stopImmediatePropagation();
               }
            });
            const orderCallback = function() {
               var $options = $select.chosenOrder();
               $select.children().remove();
               $select.append($options);
            };

            $form = $select.closest('form');
            // Initialize jQuery UI Sortable
            $chosen.find('.' + $select.chosenClassPrefix() + '-choices').sortable({
               placeholder: 'search-choice-placeholder',
               items: 'li:not(.search-field)',
               tolerance: 'pointer',
               start: function(e, ui) {
                  ui.placeholder.width(ui.item.innerWidth());
                  ui.placeholder.height(ui.item.innerHeight());
               },
               stop: function(e, ui) {
                  orderCallback();
                  $form.trigger('orderChanged');
                  $select.trigger('chosen:updated');
               }
            });

            // Intercept form submit & order the chosens
            if ($form) {
               const orderCallback = function() {
                  var $options = $select.chosenOrder();
                  $select.children().remove();
                  $select.append($options);
               };

               $form.bind('submit', orderCallback);
            }
         } else {
            console.error('jquery-chosen-sortable requires JQuery UI to have been initialised.');
         }

      });

   };

}(jQuery));
