const { calculateIndex } = Utils;

function currentCardIsInThisList(listId, swimlaneId) {
  const currentCard = Cards.findOne(Session.get('currentCard'));
  const currentUser = Meteor.user();
  if (currentUser.profile.boardView === 'board-view-lists')
    return currentCard && currentCard.listId === listId;
  else if (currentUser.profile.boardView === 'board-view-swimlanes')
    return currentCard && currentCard.listId === listId && currentCard.swimlaneId === swimlaneId;
  else if (currentUser.profile.boardView === 'board-view-cal')
    return currentCard;
  else
    return false;
}

function initSortable(boardComponent, $listsDom) {
  // We want to animate the card details window closing. We rely on CSS
  // transition for the actual animation.
  $listsDom._uihooks = {
    removeElement(node) {
      const removeNode = _.once(() => {
        node.parentNode.removeChild(node);
      });
      if ($(node).hasClass('js-card-details')) {
        $(node).css({
          flexBasis: 0,
          padding: 0,
        });
        $listsDom.one(CSSEvents.transitionend, removeNode);
      } else {
        removeNode();
      }
    },
  };

  $listsDom.sortable({
    tolerance: 'pointer',
    helper: 'clone',
    handle: '.js-list-header',
    items: '.js-list:not(.js-list-composer)',
    placeholder: 'list placeholder',
    distance: 7,
    start(evt, ui) {
      ui.placeholder.height(ui.helper.height());
      EscapeActions.executeUpTo('popup-close');
      boardComponent.setIsDragging(true);
    },
    stop(evt, ui) {
      // To attribute the new index number, we need to get the DOM element
      // of the previous and the following card -- if any.
      const prevListDom = ui.item.prev('.js-list').get(0);
      const nextListDom = ui.item.next('.js-list').get(0);
      const sortIndex = calculateIndex(prevListDom, nextListDom, 1);

      $listsDom.sortable('cancel');
      const listDomElement = ui.item.get(0);
      const list = Blaze.getData(listDomElement);

      Lists.update(list._id, {
        $set: {
          sort: sortIndex.base,
        },
      });

      boardComponent.setIsDragging(false);
    },
  });

  function userIsMember() {
    return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
  }

  // Disable drag-dropping while in multi-selection mode, or if the current user
  // is not a board member
  boardComponent.autorun(() => {
    const $listDom = $listsDom;
    if ($listDom.data('sortable')) {
      $listsDom.sortable('option', 'disabled',
        MultiSelection.isActive() || !userIsMember());
    }
  });
}

BlazeComponent.extendComponent({
  onRendered() {
    const boardComponent = this.parentComponent();
    const $listsDom = this.$('.js-lists');

    if (!Session.get('currentCard')) {
      boardComponent.scrollLeft();
    }

    initSortable(boardComponent, $listsDom);
  },
  onCreated() {
    this.draggingActive = new ReactiveVar(false);

    this._isDragging = false;
    this._lastDragPositionX = 0;
  },

  id() {
    return this._id;
  },

  currentCardIsInThisList(listId, swimlaneId) {
    return currentCardIsInThisList(listId, swimlaneId);
  },

  events() {
    return [{
      // Click-and-drag action
      'mousedown .board-canvas'(evt) {
        // Translating the board canvas using the click-and-drag action can
        // conflict with the build-in browser mechanism to select text. We
        // define a list of elements in which we disable the dragging because
        // the user will legitimately expect to be able to select some text with
        // his mouse.
        const noDragInside = ['a', 'input', 'textarea', 'p', '.js-list-header'];
        if ($(evt.target).closest(noDragInside.join(',')).length === 0 && this.$('.swimlane').prop('clientHeight') > evt.offsetY) {
          this._isDragging = true;
          this._lastDragPositionX = evt.clientX;
        }
      },
      'mouseup'() {
        if (this._isDragging) {
          this._isDragging = false;
        }
      },
      'mousemove'(evt) {
        if (this._isDragging) {
          // Update the canvas position
          this.listsDom.scrollLeft -= evt.clientX - this._lastDragPositionX;
          this._lastDragPositionX = evt.clientX;
          // Disable browser text selection while dragging
          evt.stopPropagation();
          evt.preventDefault();
          // Don't close opened card or inlined form at the end of the
          // click-and-drag.
          EscapeActions.executeUpTo('popup-close');
          EscapeActions.preventNextClick();
        }
      },
    }];
  },
}).register('swimlane');

BlazeComponent.extendComponent({
  // Proxy
  open() {
    this.childComponents('inlinedForm')[0].open();
  },

  events() {
    return [{
      submit(evt) {
        evt.preventDefault();
        const titleInput = this.find('.list-name-input');
        const title = titleInput.value.trim();
        if (title) {
          Lists.insert({
            title,
            boardId: Session.get('currentBoard'),
            sort: $('.list').length,
          });

          titleInput.value = '';
          titleInput.focus();
        }
      },
    }];
  },
}).register('addListForm');

BlazeComponent.extendComponent({
  // Proxy
  open() {
    this.childComponents('inlinedForm')[0].open();
  },

  events() {
    return [{
      submit(evt) {
        evt.preventDefault();
        let titleInput = this.find('.list-name-input');
        if (titleInput) {
          const title = titleInput.value.trim();
          if (title) {
            Lists.insert({
              title,
              boardId: Session.get('currentBoard'),
              sort: $('.list').length,
            });

            titleInput.value = '';
            titleInput.focus();
          }
        } else {
          titleInput = this.find('.swimlane-name-input');
          const title = titleInput.value.trim();
          if (title) {
            Swimlanes.insert({
              title,
              boardId: Session.get('currentBoard'),
              sort: $('.swimlane').length,
            });

            titleInput.value = '';
            titleInput.focus();
          }
        }
      },
    }];
  },
}).register('addListAndSwimlaneForm');

Template.swimlane.helpers({
  canSeeAddList() {
    return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
  },
});

BlazeComponent.extendComponent({
  currentCardIsInThisList(listId, swimlaneId) {
    return currentCardIsInThisList(listId, swimlaneId);
  },
  onRendered() {
    const boardComponent = this.parentComponent();
    const $listsDom = this.$('.js-lists');

    if (!Session.get('currentCard')) {
      boardComponent.scrollLeft();
    }

    initSortable(boardComponent, $listsDom);
  },
}).register('listsGroup');
