/* global $:false, jQuery:false */
/*
Drag & Drop Table Columns v.3.1.5
for jQuery 3.x
by Oleksandr Nikitin (a.nikitin@i.ua)
https://github.com/alexshnur/drag-n-drop-table-columns
*/
(function ($, window) {
  let cols;
  let dragSrcEl = null;
  let dragSrcEnter = null;
  let dragableColumns;
  let
    _this;

  function insertAfter(elem, refElem) {
    return refElem.parentNode.insertBefore(elem, refElem.nextSibling);
  }

  function isIE() {
    const nav = navigator.userAgent.toLowerCase();
    return (nav.indexOf('msie') !== -1) ? parseInt(nav.split('msie')[1]) : false;
  }

  dragableColumns = (function () {
    let $table;

    function dragColumns(table, options) {
      _this = this;
      $table = table;
      _this.options = $.extend({}, _this.options, options);
      if (_this.options.drag) {
        if (isIE() === 9) {
          $table.find('thead tr th').each(function () {
            if ($(this).find('.drag-ie').length === 0) {
              $(this).html($('<a>').html($(this).html()).attr('href', '#').addClass(
                'drag-ie',
              ));
            }
          });
        }
        cols = $table.find('thead tr th');

        jQuery.event.addProp('dataTransfer');
        [].forEach.call(cols, (col) => {
          col.setAttribute('draggable', true);

          $(col).on('dragstart', _this.handleDragStart);
          $(col).on('dragenter', _this.handleDragEnter);
          $(col).on('dragover', _this.handleDragOver);
          $(col).on('dragleave', _this.handleDragLeave);
          $(col).on('drop', _this.handleDrop);
          $(col).on('dragend', _this.handleDragEnd);
        });
      }
    }

    dragColumns.prototype = {
      options: {
        drag: true,
        dragClass: 'drag',
        overClass: 'over',
        movedContainerSelector: '.dnd-moved',
      },
      handleDragStart(e) {
        $(this).addClass(_this.options.dragClass);
        dragSrcEl = this;
        e.dataTransfer.effectAllowed = 'copy';
        e.dataTransfer.setData('text/html', this.id);
      },
      handleDragOver(e) {
        if (e.preventDefault) {
          e.preventDefault();
        }
        e.dataTransfer.dropEffect = 'copy';
      },
      handleDragEnter(e) {
        dragSrcEnter = this;
        [].forEach.call(cols, (col) => {
          $(col).removeClass(_this.options.overClass);
        });
        $(this).addClass(_this.options.overClass);
      },
      handleDragLeave(e) {
        if (dragSrcEnter !== e) {
          // this.classList.remove(_this.options.overClass);
        }
      },
      handleDrop(e) {
        if (e.stopPropagation) {
          e.stopPropagation();
        }
        if (dragSrcEl !== e) {
          _this.moveColumns($(dragSrcEl).index(), $(this).index());
        }
      },
      handleDragEnd(e) {
        const colPositions = {
          array: [],
          object: {},
        };
        [].forEach.call(cols, (col) => {
          const name = $(col).attr('data-name') || $(col).index();
          $(col).removeClass(_this.options.overClass);
          colPositions.object[name] = $(col).index();
          colPositions.array.push($(col).index());
        });
        if (typeof _this.options.onDragEnd === 'function') {
          _this.options.onDragEnd(colPositions);
        }
        $(dragSrcEl).removeClass(_this.options.dragClass);
      },
      moveColumns(fromIndex, toIndex) {
        const rows = $table.find(_this.options.movedContainerSelector);
        for (let i = 0; i < rows.length; i++) {
          if (toIndex > fromIndex) {
            insertAfter(rows[i].children[fromIndex], rows[i].children[toIndex]);
          } else if (toIndex < $table.find('thead tr th').length - 1) {
            rows[i].insertBefore(rows[i].children[fromIndex], rows[i].children[toIndex]);
          }
        }
      },
    };

    return dragColumns;
  }());

  return $.fn.extend({
    dragableColumns() {
      const option = (arguments[0]);
      return this.each(function () {
        const $table = $(this);
        new dragableColumns($table, option);
      });
    },
  });
}(window.jQuery, window));
