import getDisplacedBy from "../../get-displaced-by";
import { emptyGroups, noDisplacedBy } from "../../no-impact";
import getPageBorderBoxCenter from "../../get-center-from-impact/get-page-border-box-center";
import isTotallyVisibleInNewLocation from "../move-to-next-place/is-totally-visible-in-new-location";
import { addPlaceholder } from "../../droppable/with-placeholder";
import isHomeOf from "../../droppable/is-home-of";
import calculateReorderImpact from "../../calculate-drag-impact/calculate-reorder-impact";

const moveToNewDroppable = ({
  previousPageBorderBoxCenter,
  moveRelativeTo,
  insideDestination,
  draggable,
  draggables,
  destination,
  viewport,
  afterCritical
}) => {
  if (!moveRelativeTo) {
    // Draggables available, but none are candidates for movement
    if (insideDestination.length) {
      return null;
    }

    // Try move to top of empty list if it is visible
    const proposed = {
      displaced: emptyGroups,
      displacedBy: noDisplacedBy,
      at: {
        type: "REORDER",
        destination: {
          droppableId: destination.descriptor.id,
          index: 0
        }
      }
    };
    const proposedPageBorderBoxCenter = getPageBorderBoxCenter({
      impact: proposed,
      draggable,
      droppable: destination,
      draggables,
      afterCritical
    });

    // need to add room for a placeholder in a foreign list
    const withPlaceholder = isHomeOf(draggable, destination)
      ? destination
      : addPlaceholder(destination, draggable, draggables);
    const isVisibleInNewLocation = isTotallyVisibleInNewLocation({
      draggable,
      destination: withPlaceholder,
      newPageBorderBoxCenter: proposedPageBorderBoxCenter,
      viewport: viewport.frame,
      // already taken into account by getPageBorderBoxCenter
      withDroppableDisplacement: false,
      onlyOnMainAxis: true
    });
    return isVisibleInNewLocation ? proposed : null;
  }
  const isGoingBeforeTarget = Boolean(
    // Using <= as we optimise slightly for moving before items in a new list
    // This is nicer in lists with fixed height items
    previousPageBorderBoxCenter[destination.axis.line] <= moveRelativeTo.page.borderBox.center[destination.axis.line]
  );
  const proposedIndex = (() => {
    const relativeTo = moveRelativeTo.descriptor.index;
    if (moveRelativeTo.descriptor.id === draggable.descriptor.id) {
      return relativeTo;
    }
    if (isGoingBeforeTarget) {
      return relativeTo;
    }
    return relativeTo + 1;
  })();
  const displacedBy = getDisplacedBy(destination.axis, draggable.displaceBy);
  return calculateReorderImpact({
    draggable,
    insideDestination,
    destination,
    viewport,
    displacedBy,
    // last groups won't be relevant
    last: emptyGroups,
    index: proposedIndex
  });
};

export default moveToNewDroppable;
