const SORTABLE_ATTRIBUTE = 'sortable';
const SORTABLE_DATA_ATTRIBUTE = 'data-sortable';
/**
 * Original item list from default slot - clone to specified container,
 * show after sorting, detect if item is sortable
 */
export default class OriginalSortableItemList {
  constructor () {
    /**
     * @type {HTMLElement}
     */
    this.container = null;
  }

  /**
   * @param {HTMLElement} element
   */
  setContainer (element) {
    this.container = element;
  }

  hide () {
    this.container.classList.add('hidden');
  }

  /**
   * @param {number} positionToFocus
   */
  restore (positionToFocus) {
    this.container.classList.remove('hidden');
    if (positionToFocus !== null) {
      const item = this.container.children.item(positionToFocus);
      const focusedItem =
        item && !item.hasAttribute('tabindex')
          ? item.querySelector('[tabindex]')
          : item;
      if (focusedItem) {
        focusedItem.focus();
      }
    }
  }

  /**
   * @param {HTMLElement} element
   */
  cloneTo (element) {
    for (let i = 0; i < this.container.children.length; i += 1) {
      const originalElement = this.container.children.item(i);
      const clonedElement = originalElement.cloneNode(true);
      clonedElement.removeAttribute('v-for');
      element.appendChild(clonedElement);
    }
  }

  /**
   * @param {HTMLElement} target
   * @param {boolean} requireSortableAttribute
   * @returns {boolean}
   */
  isSortable (target, requireSortableAttribute) {
    if (
      (target.tagName === 'A' ||
        target.tagName === 'BUTTON' ||
        target.tagName === 'INPUT') &&
      !requireSortableAttribute
    ) {
      return false;
    }
    if (requireSortableAttribute) {
      const attribute = SORTABLE_ATTRIBUTE;
      if (
        target.getAttribute(attribute) === 'true' ||
        target.getAttribute(attribute) === attribute ||
        target.getAttribute(SORTABLE_DATA_ATTRIBUTE) === 'true'
      ) {
        return true;
      }
      return target.parentElement
        ? this.isSortable(target.parentElement, requireSortableAttribute)
        : false;
    }
    return true;
  }

  /**
   * @param {HTMLElement} element
   * @returns {number}
   */
  getItemIndexByElement (element) {
    return Array.prototype.indexOf.call(this.container.children, element);
  }

  /**
   * @param {HTMLElement} element
   * @returns {object|null}
   */
  getSortItem (element) {
    if (element.parentElement === this.container) {
      return element;
    }
    return element.parentElement
      ? this.getSortItem(element.parentElement)
      : null;
  }
}
