// @flow
import { getRect, type Rect, type Spacing, type BoxModel } from 'css-box-model';
import type {
  Axis,
  Scrollable,
  DroppableSubject,
  PlaceholderInSubject,
} from '../../../types';
import executeClip from './clip';
import { offsetByPosition } from '../../spacing';

const scroll = (target: Spacing, frame: ?Scrollable): Spacing => {
  if (!frame) {
    return target;
  }

  return offsetByPosition(target, frame.scroll.diff.displacement);
};

const increase = (
  target: Spacing,
  axis: Axis,
  withPlaceholder: ?PlaceholderInSubject,
): Spacing => {
  if (withPlaceholder && withPlaceholder.increasedBy) {
    return {
      ...target,
      [axis.end]: target[axis.end] + withPlaceholder.increasedBy[axis.line],
    };
  }
  return target;
};

const clip = (target: Spacing, frame: ?Scrollable): ?Rect => {
  if (frame && frame.shouldClipSubject) {
    return executeClip(frame.pageMarginBox, target);
  }
  return getRect(target);
};

type Args = {|
  page: BoxModel,
  withPlaceholder: ?PlaceholderInSubject,
  axis: Axis,
  frame: ?Scrollable,
|};

export default ({
  page,
  withPlaceholder,
  axis,
  frame,
}: Args): DroppableSubject => {
  const scrolled: Spacing = scroll(page.marginBox, frame);
  const increased: Spacing = increase(scrolled, axis, withPlaceholder);
  const clipped: ?Rect = clip(increased, frame);

  return {
    page,
    withPlaceholder,
    active: clipped,
  };
};
