import getDraggablesInsideDroppable from "../../get-draggables-inside-droppable";
import moveToNextCombine from "./move-to-next-combine";
import moveToNextIndex from "./move-to-next-index";
import isHomeOf from "../../droppable/is-home-of";
import getPageBorderBoxCenter from "../../get-center-from-impact/get-page-border-box-center";
import speculativelyIncrease from "../../update-displacement-visibility/speculatively-increase";
import getClientFromPageBorderBoxCenter from "../../get-center-from-impact/get-client-border-box-center/get-client-from-page-border-box-center";
import { subtract } from "../../position";
import isTotallyVisibleInNewLocation from "./is-totally-visible-in-new-location";

const moveToNextPlace = ({
  isMovingForward,
  draggable,
  destination,
  draggables,
  previousImpact,
  viewport,
  previousPageBorderBoxCenter,
  previousClientSelection,
  afterCritical
}) => {
  if (!destination.isEnabled) {
    return null;
  }
  const insideDestination = getDraggablesInsideDroppable(destination.descriptor.id, draggables);
  const isInHomeList = isHomeOf(draggable, destination);
  const impact =
    moveToNextCombine({
      isMovingForward,
      draggable,
      destination,
      insideDestination,
      previousImpact
    }) ||
    moveToNextIndex({
      isMovingForward,
      isInHomeList,
      draggable,
      draggables,
      destination,
      insideDestination,
      previousImpact,
      viewport,
      afterCritical
    });
  if (!impact) {
    return null;
  }
  const pageBorderBoxCenter = getPageBorderBoxCenter({
    impact,
    draggable,
    droppable: destination,
    draggables,
    afterCritical
  });
  const isVisibleInNewLocation = isTotallyVisibleInNewLocation({
    draggable,
    destination,
    newPageBorderBoxCenter: pageBorderBoxCenter,
    viewport: viewport.frame,
    // already taken into account by getPageBorderBoxCenter
    withDroppableDisplacement: false,
    // we only care about it being visible relative to the main axis
    // this is important with dynamic changes as scroll bar and toggle
    // on the cross axis during a drag
    onlyOnMainAxis: true
  });
  if (isVisibleInNewLocation) {
    // using the client center as the selection point
    const clientSelection = getClientFromPageBorderBoxCenter({
      pageBorderBoxCenter,
      draggable,
      viewport
    });
    return {
      clientSelection,
      impact,
      scrollJumpRequest: null
    };
  }
  const distance = subtract(pageBorderBoxCenter, previousPageBorderBoxCenter);
  const cautious = speculativelyIncrease({
    impact,
    viewport,
    destination,
    draggables,
    maxScrollChange: distance
  });
  return {
    clientSelection: previousClientSelection,
    impact: cautious,
    scrollJumpRequest: distance
  };
};

export default moveToNextPlace;
