import { invariant } from "../invariant";
import getHomeLocation from "./get-home-location";
import getDraggablesInsideDroppable from "./get-draggables-inside-droppable";
import getDisplacedBy from "./get-displaced-by";
import getDisplacementGroups from "./get-displacement-groups";

const getLiftEffect = ({ draggable, home, draggables, viewport }) => {
  const displacedBy = getDisplacedBy(home.axis, draggable.displaceBy);
  const insideHome = getDraggablesInsideDroppable(home.descriptor.id, draggables);

  // in a list that does not start at 0 the descriptor.index might be different from the index in the list
  // eg a list could be: [2,3,4]. A descriptor.index of '2' would actually be in index '0' of the list
  const rawIndex = insideHome.indexOf(draggable);
  invariant(rawIndex !== -1, "Expected draggable to be inside home list");
  const afterDragging = insideHome.slice(rawIndex + 1);
  const effected = afterDragging.reduce((previous, item) => {
    previous[item.descriptor.id] = true;
    return previous;
  }, {});
  const afterCritical = {
    inVirtualList: home.descriptor.mode === "virtual",
    displacedBy,
    effected
  };
  const displaced = getDisplacementGroups({
    afterDragging,
    destination: home,
    displacedBy,
    last: null,
    viewport: viewport.frame,
    // originally we do not want any animation as we want
    // everything to be fixed in the same position that
    // it started in
    forceShouldAnimate: false
  });
  const impact = {
    displaced,
    displacedBy,
    at: {
      type: "REORDER",
      destination: getHomeLocation(draggable.descriptor)
    }
  };
  return {
    impact,
    afterCritical
  };
};

export default getLiftEffect;
